summaryrefslogtreecommitdiff
path: root/libcap/cap_extint.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcap/cap_extint.c')
-rw-r--r--libcap/cap_extint.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/libcap/cap_extint.c b/libcap/cap_extint.c
new file mode 100644
index 0000000..5a0cc8e
--- /dev/null
+++ b/libcap/cap_extint.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1997-8 Andrew G Morgan <morgan@kernel.org>
+ *
+ * This file deals with exchanging internal and external
+ * representations of capability sets.
+ */
+
+#include "libcap.h"
+
+/*
+ * External representation for capabilities. (exported as a fixed
+ * length)
+ */
+#define CAP_EXT_MAGIC "\220\302\001\121"
+#define CAP_EXT_MAGIC_SIZE 4
+const static __u8 external_magic[CAP_EXT_MAGIC_SIZE+1] = CAP_EXT_MAGIC;
+
+struct cap_ext_struct {
+ __u8 magic[CAP_EXT_MAGIC_SIZE];
+ __u8 length_of_capset;
+ /*
+ * note, we arrange these so the caps are stacked with byte-size
+ * resolution
+ */
+ __u8 bytes[CAP_SET_SIZE][NUMBER_OF_CAP_SETS];
+};
+
+/*
+ * return size of external capability set
+ */
+
+ssize_t cap_size(cap_t caps)
+{
+ return sizeof(struct cap_ext_struct);
+}
+
+/*
+ * Copy the internal (cap_d) capability set into an external
+ * representation. The external representation is portable to other
+ * Linux architectures.
+ */
+
+ssize_t cap_copy_ext(void *cap_ext, cap_t cap_d, ssize_t length)
+{
+ struct cap_ext_struct *result = (struct cap_ext_struct *) cap_ext;
+ int i;
+
+ /* valid arguments? */
+ if (!good_cap_t(cap_d) || length < sizeof(struct cap_ext_struct)
+ || cap_ext == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* fill external capability set */
+ memcpy(&result->magic, external_magic, CAP_EXT_MAGIC_SIZE);
+ result->length_of_capset = CAP_SET_SIZE;
+
+ for (i=0; i<NUMBER_OF_CAP_SETS; ++i) {
+ int j;
+ for (j=0; j<CAP_SET_SIZE; ) {
+ __u32 val;
+
+ val = cap_d->u[j/sizeof(__u32)].flat[i];
+
+ result->bytes[j++][i] = val & 0xFF;
+ result->bytes[j++][i] = (val >>= 8) & 0xFF;
+ result->bytes[j++][i] = (val >>= 8) & 0xFF;
+ result->bytes[j++][i] = (val >> 8) & 0xFF;
+ }
+ }
+
+ /* All done: return length of external representation */
+ return (sizeof(struct cap_ext_struct));
+}
+
+/*
+ * Import an external representation to produce an internal rep.
+ * the internal rep should be liberated with cap_free().
+ */
+
+cap_t cap_copy_int(const void *cap_ext)
+{
+ const struct cap_ext_struct *export =
+ (const struct cap_ext_struct *) cap_ext;
+ cap_t cap_d;
+ int set, blen;
+
+ /* Does the external representation make sense? */
+ if ((export == NULL)
+ || memcmp(export->magic, external_magic, CAP_EXT_MAGIC_SIZE)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Obtain a new internal capability set */
+ if (!(cap_d = cap_init()))
+ return NULL;
+
+ blen = export->length_of_capset;
+ for (set=0; set<NUMBER_OF_CAP_SETS; ++set) {
+ int blk;
+ int bno = 0;
+ for (blk=0; blk<(CAP_SET_SIZE/sizeof(__u32)); ++blk) {
+ __u32 val = 0;
+
+ if (bno != blen)
+ val = export->bytes[bno++][set];
+ if (bno != blen)
+ val |= export->bytes[bno++][set] << 8;
+ if (bno != blen)
+ val |= export->bytes[bno++][set] << 16;
+ if (bno != blen)
+ val |= export->bytes[bno++][set] << 24;
+
+ cap_d->u[blk].flat[set] = val;
+ }
+ }
+
+ /* all done */
+ return cap_d;
+}
+