Home | History | Annotate | Download | only in libcap
      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