xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xselinux_label.c (9926B)


      1 /************************************************************
      2 
      3 Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 this permission notice appear in supporting documentation.  This permission
      8 notice shall be included in all copies or substantial portions of the
      9 Software.
     10 
     11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     14 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     17 
     18 ********************************************************/
     19 
     20 #ifdef HAVE_DIX_CONFIG_H
     21 #include <dix-config.h>
     22 #endif
     23 
     24 #include <selinux/label.h>
     25 
     26 #include "registry.h"
     27 #include "xselinuxint.h"
     28 
     29 /* selection and property atom cache */
     30 typedef struct {
     31     SELinuxObjectRec prp;
     32     SELinuxObjectRec sel;
     33 } SELinuxAtomRec;
     34 
     35 /* dynamic array */
     36 typedef struct {
     37     unsigned size;
     38     void **array;
     39 } SELinuxArrayRec;
     40 
     41 /* labeling handle */
     42 static struct selabel_handle *label_hnd;
     43 
     44 /* Array of object classes indexed by resource type */
     45 SELinuxArrayRec arr_types;
     46 
     47 /* Array of event SIDs indexed by event type */
     48 SELinuxArrayRec arr_events;
     49 
     50 /* Array of property and selection SID structures */
     51 SELinuxArrayRec arr_atoms;
     52 
     53 /*
     54  * Dynamic array helpers
     55  */
     56 static void *
     57 SELinuxArrayGet(SELinuxArrayRec * rec, unsigned key)
     58 {
     59     return (rec->size > key) ? rec->array[key] : 0;
     60 }
     61 
     62 static int
     63 SELinuxArraySet(SELinuxArrayRec * rec, unsigned key, void *val)
     64 {
     65     if (key >= rec->size) {
     66         /* Need to increase size of array */
     67         rec->array = reallocarray(rec->array, key + 1, sizeof(val));
     68         if (!rec->array)
     69             return FALSE;
     70         memset(rec->array + rec->size, 0, (key - rec->size + 1) * sizeof(val));
     71         rec->size = key + 1;
     72     }
     73 
     74     rec->array[key] = val;
     75     return TRUE;
     76 }
     77 
     78 static void
     79 SELinuxArrayFree(SELinuxArrayRec * rec, int free_elements)
     80 {
     81     if (free_elements) {
     82         unsigned i = rec->size;
     83 
     84         while (i)
     85             free(rec->array[--i]);
     86     }
     87 
     88     free(rec->array);
     89     rec->size = 0;
     90     rec->array = NULL;
     91 }
     92 
     93 /*
     94  * Looks up a name in the selection or property mappings
     95  */
     96 static int
     97 SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec * obj, int map, int polymap)
     98 {
     99     const char *name = NameForAtom(atom);
    100     char *ctx;
    101     int rc = Success;
    102 
    103     obj->poly = 1;
    104 
    105     /* Look in the mappings of names to contexts */
    106     if (selabel_lookup_raw(label_hnd, &ctx, name, map) == 0) {
    107         obj->poly = 0;
    108     }
    109     else if (errno != ENOENT) {
    110         ErrorF("SELinux: a property label lookup failed!\n");
    111         return BadValue;
    112     }
    113     else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) {
    114         ErrorF("SELinux: a property label lookup failed!\n");
    115         return BadValue;
    116     }
    117 
    118     /* Get a SID for context */
    119     if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) {
    120         ErrorF("SELinux: a context_to_SID_raw call failed!\n");
    121         rc = BadAlloc;
    122     }
    123 
    124     freecon(ctx);
    125     return rc;
    126 }
    127 
    128 /*
    129  * Looks up the SID corresponding to the given property or selection atom
    130  */
    131 int
    132 SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec ** obj_rtn)
    133 {
    134     SELinuxAtomRec *rec;
    135     SELinuxObjectRec *obj;
    136     int rc, map, polymap;
    137 
    138     rec = SELinuxArrayGet(&arr_atoms, atom);
    139     if (!rec) {
    140         rec = calloc(1, sizeof(SELinuxAtomRec));
    141         if (!rec || !SELinuxArraySet(&arr_atoms, atom, rec))
    142             return BadAlloc;
    143     }
    144 
    145     if (prop) {
    146         obj = &rec->prp;
    147         map = SELABEL_X_PROP;
    148         polymap = SELABEL_X_POLYPROP;
    149     }
    150     else {
    151         obj = &rec->sel;
    152         map = SELABEL_X_SELN;
    153         polymap = SELABEL_X_POLYSELN;
    154     }
    155 
    156     if (!obj->sid) {
    157         rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap);
    158         if (rc != Success)
    159             goto out;
    160     }
    161 
    162     *obj_rtn = obj;
    163     rc = Success;
    164  out:
    165     return rc;
    166 }
    167 
    168 /*
    169  * Looks up a SID for a selection/subject pair
    170  */
    171 int
    172 SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec * subj,
    173                       security_id_t * sid_rtn, int *poly_rtn)
    174 {
    175     int rc;
    176     SELinuxObjectRec *obj;
    177     security_id_t tsid;
    178 
    179     /* Get the default context and polyinstantiation bit */
    180     rc = SELinuxAtomToSID(selection, 0, &obj);
    181     if (rc != Success)
    182         return rc;
    183 
    184     /* Check for an override context next */
    185     if (subj->sel_use_sid) {
    186         tsid = subj->sel_use_sid;
    187         goto out;
    188     }
    189 
    190     tsid = obj->sid;
    191 
    192     /* Polyinstantiate if necessary to obtain the final SID */
    193     if (obj->poly && avc_compute_member(subj->sid, obj->sid,
    194                                         SECCLASS_X_SELECTION, &tsid) < 0) {
    195         ErrorF("SELinux: a compute_member call failed!\n");
    196         return BadValue;
    197     }
    198  out:
    199     *sid_rtn = tsid;
    200     if (poly_rtn)
    201         *poly_rtn = obj->poly;
    202     return Success;
    203 }
    204 
    205 /*
    206  * Looks up a SID for a property/subject pair
    207  */
    208 int
    209 SELinuxPropertyToSID(Atom property, SELinuxSubjectRec * subj,
    210                      security_id_t * sid_rtn, int *poly_rtn)
    211 {
    212     int rc;
    213     SELinuxObjectRec *obj;
    214     security_id_t tsid, tsid2;
    215 
    216     /* Get the default context and polyinstantiation bit */
    217     rc = SELinuxAtomToSID(property, 1, &obj);
    218     if (rc != Success)
    219         return rc;
    220 
    221     /* Check for an override context next */
    222     if (subj->prp_use_sid) {
    223         tsid = subj->prp_use_sid;
    224         goto out;
    225     }
    226 
    227     /* Perform a transition */
    228     if (avc_compute_create(subj->sid, obj->sid, SECCLASS_X_PROPERTY, &tsid) < 0) {
    229         ErrorF("SELinux: a compute_create call failed!\n");
    230         return BadValue;
    231     }
    232 
    233     /* Polyinstantiate if necessary to obtain the final SID */
    234     if (obj->poly) {
    235         tsid2 = tsid;
    236         if (avc_compute_member(subj->sid, tsid2,
    237                                SECCLASS_X_PROPERTY, &tsid) < 0) {
    238             ErrorF("SELinux: a compute_member call failed!\n");
    239             return BadValue;
    240         }
    241     }
    242  out:
    243     *sid_rtn = tsid;
    244     if (poly_rtn)
    245         *poly_rtn = obj->poly;
    246     return Success;
    247 }
    248 
    249 /*
    250  * Looks up the SID corresponding to the given event type
    251  */
    252 int
    253 SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
    254                   SELinuxObjectRec * sid_return)
    255 {
    256     const char *name = LookupEventName(type);
    257     security_id_t sid;
    258     char *ctx;
    259 
    260     type &= 127;
    261 
    262     sid = SELinuxArrayGet(&arr_events, type);
    263     if (!sid) {
    264         /* Look in the mappings of event names to contexts */
    265         if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) {
    266             ErrorF("SELinux: an event label lookup failed!\n");
    267             return BadValue;
    268         }
    269         /* Get a SID for context */
    270         if (avc_context_to_sid_raw(ctx, &sid) < 0) {
    271             ErrorF("SELinux: a context_to_SID_raw call failed!\n");
    272             freecon(ctx);
    273             return BadAlloc;
    274         }
    275         freecon(ctx);
    276         /* Cache the SID value */
    277         if (!SELinuxArraySet(&arr_events, type, sid))
    278             return BadAlloc;
    279     }
    280 
    281     /* Perform a transition to obtain the final SID */
    282     if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT,
    283                            &sid_return->sid) < 0) {
    284         ErrorF("SELinux: a compute_create call failed!\n");
    285         return BadValue;
    286     }
    287 
    288     return Success;
    289 }
    290 
    291 int
    292 SELinuxExtensionToSID(const char *name, security_id_t * sid_rtn)
    293 {
    294     char *ctx;
    295 
    296     /* Look in the mappings of extension names to contexts */
    297     if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) {
    298         ErrorF("SELinux: a property label lookup failed!\n");
    299         return BadValue;
    300     }
    301     /* Get a SID for context */
    302     if (avc_context_to_sid_raw(ctx, sid_rtn) < 0) {
    303         ErrorF("SELinux: a context_to_SID_raw call failed!\n");
    304         freecon(ctx);
    305         return BadAlloc;
    306     }
    307     freecon(ctx);
    308     return Success;
    309 }
    310 
    311 /*
    312  * Returns the object class corresponding to the given resource type.
    313  */
    314 security_class_t
    315 SELinuxTypeToClass(RESTYPE type)
    316 {
    317     void *tmp;
    318 
    319     tmp = SELinuxArrayGet(&arr_types, type & TypeMask);
    320     if (!tmp) {
    321         unsigned long class = SECCLASS_X_RESOURCE;
    322 
    323         if (type & RC_DRAWABLE)
    324             class = SECCLASS_X_DRAWABLE;
    325         else if (type == RT_GC)
    326             class = SECCLASS_X_GC;
    327         else if (type == RT_FONT)
    328             class = SECCLASS_X_FONT;
    329         else if (type == RT_CURSOR)
    330             class = SECCLASS_X_CURSOR;
    331         else if (type == RT_COLORMAP)
    332             class = SECCLASS_X_COLORMAP;
    333         else {
    334             /* Need to do a string lookup */
    335             const char *str = LookupResourceName(type);
    336 
    337             if (!strcmp(str, "PICTURE"))
    338                 class = SECCLASS_X_DRAWABLE;
    339             else if (!strcmp(str, "GLYPHSET"))
    340                 class = SECCLASS_X_FONT;
    341         }
    342 
    343         tmp = (void *) class;
    344         SELinuxArraySet(&arr_types, type & TypeMask, tmp);
    345     }
    346 
    347     return (security_class_t) (unsigned long) tmp;
    348 }
    349 
    350 char *
    351 SELinuxDefaultClientLabel(void)
    352 {
    353     char *ctx;
    354 
    355     if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0)
    356         FatalError("SELinux: failed to look up remote-client context\n");
    357 
    358     return ctx;
    359 }
    360 
    361 void
    362 SELinuxLabelInit(void)
    363 {
    364     struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *) 1 };
    365 
    366     label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1);
    367     if (!label_hnd)
    368         FatalError("SELinux: Failed to open x_contexts mapping in policy\n");
    369 }
    370 
    371 void
    372 SELinuxLabelReset(void)
    373 {
    374     selabel_close(label_hnd);
    375     label_hnd = NULL;
    376 
    377     /* Free local state */
    378     SELinuxArrayFree(&arr_types, 0);
    379     SELinuxArrayFree(&arr_events, 0);
    380     SELinuxArrayFree(&arr_atoms, 1);
    381 }