summaryrefslogtreecommitdiff
path: root/libcap/cap_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcap/cap_alloc.c')
-rw-r--r--libcap/cap_alloc.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/libcap/cap_alloc.c b/libcap/cap_alloc.c
new file mode 100644
index 0000000..5fa5e93
--- /dev/null
+++ b/libcap/cap_alloc.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1997-8 Andrew G Morgan <morgan@kernel.org>
+ *
+ * This file deals with allocation and deallocation of internal
+ * capability sets as specified by POSIX.1e (formerlly, POSIX 6).
+ */
+
+#include "libcap.h"
+
+/*
+ * Obtain a blank set of capabilities
+ */
+
+cap_t cap_init(void)
+{
+ __u32 *raw_data;
+ cap_t result;
+
+ raw_data = malloc( sizeof(__u32) + sizeof(*result) );
+
+ if (raw_data == NULL) {
+ _cap_debug("out of memory");
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ *raw_data = CAP_T_MAGIC;
+ result = (cap_t) (raw_data + 1);
+ memset(result, 0, sizeof(*result));
+
+ result->head.version = _LIBCAP_CAPABILITY_VERSION;
+ capget(&result->head, NULL); /* load the kernel-capability version */
+
+ switch (result->head.version) {
+#ifdef _LINUX_CAPABILITY_VERSION_1
+ case _LINUX_CAPABILITY_VERSION_1:
+ break;
+#endif
+#ifdef _LINUX_CAPABILITY_VERSION_2
+ case _LINUX_CAPABILITY_VERSION_2:
+ break;
+#endif
+#ifdef _LINUX_CAPABILITY_VERSION_3
+ case _LINUX_CAPABILITY_VERSION_3:
+ break;
+#endif
+ default: /* No idea what to do */
+ cap_free(result);
+ result = NULL;
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * This is an internal library function to duplicate a string and
+ * tag the result as something cap_free can handle.
+ */
+
+char *_libcap_strdup(const char *old)
+{
+ __u32 *raw_data;
+
+ if (old == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ raw_data = malloc( sizeof(__u32) + strlen(old) + 1 );
+ if (raw_data == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ *(raw_data++) = CAP_S_MAGIC;
+ strcpy((char *) raw_data, old);
+
+ return ((char *) raw_data);
+}
+
+/*
+ * This function duplicates an internal capability set with
+ * malloc()'d memory. It is the responsibility of the user to call
+ * cap_free() to liberate it.
+ */
+
+cap_t cap_dup(cap_t cap_d)
+{
+ cap_t result;
+
+ if (!good_cap_t(cap_d)) {
+ _cap_debug("bad argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ result = cap_init();
+ if (result == NULL) {
+ _cap_debug("out of memory");
+ return NULL;
+ }
+
+ memcpy(result, cap_d, sizeof(*cap_d));
+
+ return result;
+}
+
+
+/*
+ * Scrub and then liberate an internal capability set.
+ */
+
+int cap_free(void *data_p)
+{
+ if ( !data_p )
+ return 0;
+
+ if ( good_cap_t(data_p) ) {
+ data_p = -1 + (__u32 *) data_p;
+ memset(data_p, 0, sizeof(__u32) + sizeof(struct _cap_struct));
+ free(data_p);
+ data_p = NULL;
+ return 0;
+ }
+
+ if ( good_cap_string(data_p) ) {
+ int length = strlen(data_p) + sizeof(__u32);
+ data_p = -1 + (__u32 *) data_p;
+ memset(data_p, 0, length);
+ free(data_p);
+ data_p = NULL;
+ return 0;
+ }
+
+ _cap_debug("don't recognize what we're supposed to liberate");
+ errno = EINVAL;
+ return -1;
+}