1 /* 2 * Copyright (c) 1997-8 Andrew G Morgan <morgan (at) kernel.org> 3 * 4 * This file deals with exchanging internal and external 5 * representations of capability sets. 6 */ 7 8 #include "libcap.h" 9 10 /* 11 * External representation for capabilities. (exported as a fixed 12 * length) 13 */ 14 #define CAP_EXT_MAGIC "\220\302\001\121" 15 #define CAP_EXT_MAGIC_SIZE 4 16 const static __u8 external_magic[CAP_EXT_MAGIC_SIZE+1] = CAP_EXT_MAGIC; 17 18 struct cap_ext_struct { 19 __u8 magic[CAP_EXT_MAGIC_SIZE]; 20 __u8 length_of_capset; 21 /* 22 * note, we arrange these so the caps are stacked with byte-size 23 * resolution 24 */ 25 __u8 bytes[CAP_SET_SIZE][NUMBER_OF_CAP_SETS]; 26 }; 27 28 /* 29 * return size of external capability set 30 */ 31 32 ssize_t cap_size(cap_t caps) 33 { 34 return ssizeof(struct cap_ext_struct); 35 } 36 37 /* 38 * Copy the internal (cap_d) capability set into an external 39 * representation. The external representation is portable to other 40 * Linux architectures. 41 */ 42 43 ssize_t cap_copy_ext(void *cap_ext, cap_t cap_d, ssize_t length) 44 { 45 struct cap_ext_struct *result = (struct cap_ext_struct *) cap_ext; 46 int i; 47 48 /* valid arguments? */ 49 if (!good_cap_t(cap_d) || length < ssizeof(struct cap_ext_struct) 50 || cap_ext == NULL) { 51 errno = EINVAL; 52 return -1; 53 } 54 55 /* fill external capability set */ 56 memcpy(&result->magic, external_magic, CAP_EXT_MAGIC_SIZE); 57 result->length_of_capset = CAP_SET_SIZE; 58 59 for (i=0; i<NUMBER_OF_CAP_SETS; ++i) { 60 size_t j; 61 for (j=0; j<CAP_SET_SIZE; ) { 62 __u32 val; 63 64 val = cap_d->u[j/sizeof(__u32)].flat[i]; 65 66 result->bytes[j++][i] = val & 0xFF; 67 result->bytes[j++][i] = (val >>= 8) & 0xFF; 68 result->bytes[j++][i] = (val >>= 8) & 0xFF; 69 result->bytes[j++][i] = (val >> 8) & 0xFF; 70 } 71 } 72 73 /* All done: return length of external representation */ 74 return (ssizeof(struct cap_ext_struct)); 75 } 76 77 /* 78 * Import an external representation to produce an internal rep. 79 * the internal rep should be liberated with cap_free(). 80 */ 81 82 cap_t cap_copy_int(const void *cap_ext) 83 { 84 const struct cap_ext_struct *export = 85 (const struct cap_ext_struct *) cap_ext; 86 cap_t cap_d; 87 int set, blen; 88 89 /* Does the external representation make sense? */ 90 if ((export == NULL) 91 || memcmp(export->magic, external_magic, CAP_EXT_MAGIC_SIZE)) { 92 errno = EINVAL; 93 return NULL; 94 } 95 96 /* Obtain a new internal capability set */ 97 if (!(cap_d = cap_init())) 98 return NULL; 99 100 blen = export->length_of_capset; 101 for (set=0; set<NUMBER_OF_CAP_SETS; ++set) { 102 unsigned blk; 103 int bno = 0; 104 for (blk=0; blk<(CAP_SET_SIZE/sizeof(__u32)); ++blk) { 105 __u32 val = 0; 106 107 if (bno != blen) 108 val = export->bytes[bno++][set]; 109 if (bno != blen) 110 val |= export->bytes[bno++][set] << 8; 111 if (bno != blen) 112 val |= export->bytes[bno++][set] << 16; 113 if (bno != blen) 114 val |= export->bytes[bno++][set] << 24; 115 116 cap_d->u[blk].flat[set] = val; 117 } 118 } 119 120 /* all done */ 121 return cap_d; 122 } 123 124