LCOV - code coverage report
Current view: top level - security/selinux/ss - mls.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 266 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 15 0.0 %
Branches: 0 182 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Implementation of the multi-level security (MLS) policy.
       4                 :            :  *
       5                 :            :  * Author : Stephen Smalley, <sds@tycho.nsa.gov>
       6                 :            :  */
       7                 :            : /*
       8                 :            :  * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
       9                 :            :  *
      10                 :            :  *      Support for enhanced MLS infrastructure.
      11                 :            :  *
      12                 :            :  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
      13                 :            :  */
      14                 :            : /*
      15                 :            :  * Updated: Hewlett-Packard <paul@paul-moore.com>
      16                 :            :  *
      17                 :            :  *      Added support to import/export the MLS label from NetLabel
      18                 :            :  *
      19                 :            :  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <linux/kernel.h>
      23                 :            : #include <linux/slab.h>
      24                 :            : #include <linux/string.h>
      25                 :            : #include <linux/errno.h>
      26                 :            : #include <net/netlabel.h>
      27                 :            : #include "sidtab.h"
      28                 :            : #include "mls.h"
      29                 :            : #include "policydb.h"
      30                 :            : #include "services.h"
      31                 :            : 
      32                 :            : /*
      33                 :            :  * Return the length in bytes for the MLS fields of the
      34                 :            :  * security context string representation of `context'.
      35                 :            :  */
      36                 :          0 : int mls_compute_context_len(struct policydb *p, struct context *context)
      37                 :            : {
      38                 :          0 :         int i, l, len, head, prev;
      39                 :          0 :         char *nm;
      40                 :          0 :         struct ebitmap *e;
      41                 :          0 :         struct ebitmap_node *node;
      42                 :            : 
      43         [ #  # ]:          0 :         if (!p->mls_enabled)
      44                 :            :                 return 0;
      45                 :            : 
      46                 :            :         len = 1; /* for the beginning ":" */
      47         [ #  # ]:          0 :         for (l = 0; l < 2; l++) {
      48                 :          0 :                 int index_sens = context->range.level[l].sens;
      49                 :          0 :                 len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1));
      50                 :            : 
      51                 :            :                 /* categories */
      52                 :          0 :                 head = -2;
      53                 :          0 :                 prev = -2;
      54                 :          0 :                 e = &context->range.level[l].cat;
      55         [ #  # ]:          0 :                 ebitmap_for_each_positive_bit(e, node, i) {
      56         [ #  # ]:          0 :                         if (i - prev > 1) {
      57                 :            :                                 /* one or more negative bits are skipped */
      58         [ #  # ]:          0 :                                 if (head != prev) {
      59                 :          0 :                                         nm = sym_name(p, SYM_CATS, prev);
      60                 :          0 :                                         len += strlen(nm) + 1;
      61                 :            :                                 }
      62                 :          0 :                                 nm = sym_name(p, SYM_CATS, i);
      63                 :          0 :                                 len += strlen(nm) + 1;
      64                 :          0 :                                 head = i;
      65                 :            :                         }
      66                 :          0 :                         prev = i;
      67                 :            :                 }
      68         [ #  # ]:          0 :                 if (prev != head) {
      69                 :          0 :                         nm = sym_name(p, SYM_CATS, prev);
      70                 :          0 :                         len += strlen(nm) + 1;
      71                 :            :                 }
      72         [ #  # ]:          0 :                 if (l == 0) {
      73         [ #  # ]:          0 :                         if (mls_level_eq(&context->range.level[0],
      74                 :            :                                          &context->range.level[1]))
      75                 :            :                                 break;
      76                 :            :                         else
      77                 :          0 :                                 len++;
      78                 :            :                 }
      79                 :            :         }
      80                 :            : 
      81                 :            :         return len;
      82                 :            : }
      83                 :            : 
      84                 :            : /*
      85                 :            :  * Write the security context string representation of
      86                 :            :  * the MLS fields of `context' into the string `*scontext'.
      87                 :            :  * Update `*scontext' to point to the end of the MLS fields.
      88                 :            :  */
      89                 :          0 : void mls_sid_to_context(struct policydb *p,
      90                 :            :                         struct context *context,
      91                 :            :                         char **scontext)
      92                 :            : {
      93                 :          0 :         char *scontextp, *nm;
      94                 :          0 :         int i, l, head, prev;
      95                 :          0 :         struct ebitmap *e;
      96                 :          0 :         struct ebitmap_node *node;
      97                 :            : 
      98         [ #  # ]:          0 :         if (!p->mls_enabled)
      99                 :            :                 return;
     100                 :            : 
     101                 :          0 :         scontextp = *scontext;
     102                 :            : 
     103                 :          0 :         *scontextp = ':';
     104                 :          0 :         scontextp++;
     105                 :            : 
     106         [ #  # ]:          0 :         for (l = 0; l < 2; l++) {
     107                 :          0 :                 strcpy(scontextp, sym_name(p, SYM_LEVELS,
     108                 :          0 :                                            context->range.level[l].sens - 1));
     109                 :          0 :                 scontextp += strlen(scontextp);
     110                 :            : 
     111                 :            :                 /* categories */
     112                 :          0 :                 head = -2;
     113                 :          0 :                 prev = -2;
     114                 :          0 :                 e = &context->range.level[l].cat;
     115         [ #  # ]:          0 :                 ebitmap_for_each_positive_bit(e, node, i) {
     116         [ #  # ]:          0 :                         if (i - prev > 1) {
     117                 :            :                                 /* one or more negative bits are skipped */
     118         [ #  # ]:          0 :                                 if (prev != head) {
     119         [ #  # ]:          0 :                                         if (prev - head > 1)
     120                 :          0 :                                                 *scontextp++ = '.';
     121                 :            :                                         else
     122                 :          0 :                                                 *scontextp++ = ',';
     123                 :          0 :                                         nm = sym_name(p, SYM_CATS, prev);
     124                 :          0 :                                         strcpy(scontextp, nm);
     125                 :          0 :                                         scontextp += strlen(nm);
     126                 :            :                                 }
     127         [ #  # ]:          0 :                                 if (prev < 0)
     128                 :          0 :                                         *scontextp++ = ':';
     129                 :            :                                 else
     130                 :          0 :                                         *scontextp++ = ',';
     131                 :          0 :                                 nm = sym_name(p, SYM_CATS, i);
     132                 :          0 :                                 strcpy(scontextp, nm);
     133                 :          0 :                                 scontextp += strlen(nm);
     134                 :          0 :                                 head = i;
     135                 :            :                         }
     136                 :          0 :                         prev = i;
     137                 :            :                 }
     138                 :            : 
     139         [ #  # ]:          0 :                 if (prev != head) {
     140         [ #  # ]:          0 :                         if (prev - head > 1)
     141                 :          0 :                                 *scontextp++ = '.';
     142                 :            :                         else
     143                 :          0 :                                 *scontextp++ = ',';
     144                 :          0 :                         nm = sym_name(p, SYM_CATS, prev);
     145                 :          0 :                         strcpy(scontextp, nm);
     146                 :          0 :                         scontextp += strlen(nm);
     147                 :            :                 }
     148                 :            : 
     149         [ #  # ]:          0 :                 if (l == 0) {
     150         [ #  # ]:          0 :                         if (mls_level_eq(&context->range.level[0],
     151                 :            :                                          &context->range.level[1]))
     152                 :            :                                 break;
     153                 :            :                         else
     154                 :          0 :                                 *scontextp++ = '-';
     155                 :            :                 }
     156                 :            :         }
     157                 :            : 
     158                 :          0 :         *scontext = scontextp;
     159                 :          0 :         return;
     160                 :            : }
     161                 :            : 
     162                 :          0 : int mls_level_isvalid(struct policydb *p, struct mls_level *l)
     163                 :            : {
     164                 :          0 :         struct level_datum *levdatum;
     165                 :            : 
     166   [ #  #  #  # ]:          0 :         if (!l->sens || l->sens > p->p_levels.nprim)
     167                 :            :                 return 0;
     168                 :          0 :         levdatum = hashtab_search(p->p_levels.table,
     169                 :          0 :                                   sym_name(p, SYM_LEVELS, l->sens - 1));
     170         [ #  # ]:          0 :         if (!levdatum)
     171                 :            :                 return 0;
     172                 :            : 
     173                 :            :         /*
     174                 :            :          * Return 1 iff all the bits set in l->cat are also be set in
     175                 :            :          * levdatum->level->cat and no bit in l->cat is larger than
     176                 :            :          * p->p_cats.nprim.
     177                 :            :          */
     178                 :          0 :         return ebitmap_contains(&levdatum->level->cat, &l->cat,
     179                 :            :                                 p->p_cats.nprim);
     180                 :            : }
     181                 :            : 
     182                 :          0 : int mls_range_isvalid(struct policydb *p, struct mls_range *r)
     183                 :            : {
     184         [ #  # ]:          0 :         return (mls_level_isvalid(p, &r->level[0]) &&
     185         [ #  # ]:          0 :                 mls_level_isvalid(p, &r->level[1]) &&
     186                 :            :                 mls_level_dom(&r->level[1], &r->level[0]));
     187                 :            : }
     188                 :            : 
     189                 :            : /*
     190                 :            :  * Return 1 if the MLS fields in the security context
     191                 :            :  * structure `c' are valid.  Return 0 otherwise.
     192                 :            :  */
     193                 :          0 : int mls_context_isvalid(struct policydb *p, struct context *c)
     194                 :            : {
     195                 :          0 :         struct user_datum *usrdatum;
     196                 :            : 
     197         [ #  # ]:          0 :         if (!p->mls_enabled)
     198                 :            :                 return 1;
     199                 :            : 
     200         [ #  # ]:          0 :         if (!mls_range_isvalid(p, &c->range))
     201                 :            :                 return 0;
     202                 :            : 
     203         [ #  # ]:          0 :         if (c->role == OBJECT_R_VAL)
     204                 :            :                 return 1;
     205                 :            : 
     206                 :            :         /*
     207                 :            :          * User must be authorized for the MLS range.
     208                 :            :          */
     209   [ #  #  #  # ]:          0 :         if (!c->user || c->user > p->p_users.nprim)
     210                 :            :                 return 0;
     211                 :          0 :         usrdatum = p->user_val_to_struct[c->user - 1];
     212         [ #  # ]:          0 :         if (!mls_range_contains(usrdatum->range, c->range))
     213                 :          0 :                 return 0; /* user may not be associated with range */
     214                 :            : 
     215                 :            :         return 1;
     216                 :            : }
     217                 :            : 
     218                 :            : /*
     219                 :            :  * Set the MLS fields in the security context structure
     220                 :            :  * `context' based on the string representation in
     221                 :            :  * the string `scontext'.
     222                 :            :  *
     223                 :            :  * This function modifies the string in place, inserting
     224                 :            :  * NULL characters to terminate the MLS fields.
     225                 :            :  *
     226                 :            :  * If a def_sid is provided and no MLS field is present,
     227                 :            :  * copy the MLS field of the associated default context.
     228                 :            :  * Used for upgraded to MLS systems where objects may lack
     229                 :            :  * MLS fields.
     230                 :            :  *
     231                 :            :  * Policy read-lock must be held for sidtab lookup.
     232                 :            :  *
     233                 :            :  */
     234                 :          0 : int mls_context_to_sid(struct policydb *pol,
     235                 :            :                        char oldc,
     236                 :            :                        char *scontext,
     237                 :            :                        struct context *context,
     238                 :            :                        struct sidtab *s,
     239                 :            :                        u32 def_sid)
     240                 :            : {
     241                 :          0 :         char *sensitivity, *cur_cat, *next_cat, *rngptr;
     242                 :          0 :         struct level_datum *levdatum;
     243                 :          0 :         struct cat_datum *catdatum, *rngdatum;
     244                 :          0 :         int l, rc, i;
     245                 :          0 :         char *rangep[2];
     246                 :            : 
     247         [ #  # ]:          0 :         if (!pol->mls_enabled) {
     248                 :            :                 /*
     249                 :            :                  * With no MLS, only return -EINVAL if there is a MLS field
     250                 :            :                  * and it did not come from an xattr.
     251                 :            :                  */
     252         [ #  # ]:          0 :                 if (oldc && def_sid == SECSID_NULL)
     253                 :            :                         return -EINVAL;
     254                 :          0 :                 return 0;
     255                 :            :         }
     256                 :            : 
     257                 :            :         /*
     258                 :            :          * No MLS component to the security context, try and map to
     259                 :            :          * default if provided.
     260                 :            :          */
     261         [ #  # ]:          0 :         if (!oldc) {
     262                 :          0 :                 struct context *defcon;
     263                 :            : 
     264         [ #  # ]:          0 :                 if (def_sid == SECSID_NULL)
     265                 :            :                         return -EINVAL;
     266                 :            : 
     267                 :          0 :                 defcon = sidtab_search(s, def_sid);
     268         [ #  # ]:          0 :                 if (!defcon)
     269                 :            :                         return -EINVAL;
     270                 :            : 
     271                 :          0 :                 return mls_context_cpy(context, defcon);
     272                 :            :         }
     273                 :            : 
     274                 :            :         /*
     275                 :            :          * If we're dealing with a range, figure out where the two parts
     276                 :            :          * of the range begin.
     277                 :            :          */
     278                 :          0 :         rangep[0] = scontext;
     279                 :          0 :         rangep[1] = strchr(scontext, '-');
     280         [ #  # ]:          0 :         if (rangep[1]) {
     281                 :          0 :                 rangep[1][0] = '\0';
     282                 :          0 :                 rangep[1]++;
     283                 :            :         }
     284                 :            : 
     285                 :            :         /* For each part of the range: */
     286         [ #  # ]:          0 :         for (l = 0; l < 2; l++) {
     287                 :            :                 /* Split sensitivity and category set. */
     288                 :          0 :                 sensitivity = rangep[l];
     289         [ #  # ]:          0 :                 if (sensitivity == NULL)
     290                 :            :                         break;
     291                 :          0 :                 next_cat = strchr(sensitivity, ':');
     292         [ #  # ]:          0 :                 if (next_cat)
     293                 :          0 :                         *(next_cat++) = '\0';
     294                 :            : 
     295                 :            :                 /* Parse sensitivity. */
     296                 :          0 :                 levdatum = hashtab_search(pol->p_levels.table, sensitivity);
     297         [ #  # ]:          0 :                 if (!levdatum)
     298                 :            :                         return -EINVAL;
     299                 :          0 :                 context->range.level[l].sens = levdatum->level->sens;
     300                 :            : 
     301                 :            :                 /* Extract category set. */
     302         [ #  # ]:          0 :                 while (next_cat != NULL) {
     303                 :          0 :                         cur_cat = next_cat;
     304                 :          0 :                         next_cat = strchr(next_cat, ',');
     305         [ #  # ]:          0 :                         if (next_cat != NULL)
     306                 :          0 :                                 *(next_cat++) = '\0';
     307                 :            : 
     308                 :            :                         /* Separate into range if exists */
     309                 :          0 :                         rngptr = strchr(cur_cat, '.');
     310         [ #  # ]:          0 :                         if (rngptr != NULL) {
     311                 :            :                                 /* Remove '.' */
     312                 :          0 :                                 *rngptr++ = '\0';
     313                 :            :                         }
     314                 :            : 
     315                 :          0 :                         catdatum = hashtab_search(pol->p_cats.table, cur_cat);
     316         [ #  # ]:          0 :                         if (!catdatum)
     317                 :            :                                 return -EINVAL;
     318                 :            : 
     319                 :          0 :                         rc = ebitmap_set_bit(&context->range.level[l].cat,
     320                 :          0 :                                              catdatum->value - 1, 1);
     321         [ #  # ]:          0 :                         if (rc)
     322                 :          0 :                                 return rc;
     323                 :            : 
     324                 :            :                         /* If range, set all categories in range */
     325         [ #  # ]:          0 :                         if (rngptr == NULL)
     326                 :          0 :                                 continue;
     327                 :            : 
     328                 :          0 :                         rngdatum = hashtab_search(pol->p_cats.table, rngptr);
     329         [ #  # ]:          0 :                         if (!rngdatum)
     330                 :            :                                 return -EINVAL;
     331                 :            : 
     332         [ #  # ]:          0 :                         if (catdatum->value >= rngdatum->value)
     333                 :            :                                 return -EINVAL;
     334                 :            : 
     335         [ #  # ]:          0 :                         for (i = catdatum->value; i < rngdatum->value; i++) {
     336                 :          0 :                                 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
     337         [ #  # ]:          0 :                                 if (rc)
     338                 :          0 :                                         return rc;
     339                 :            :                         }
     340                 :            :                 }
     341                 :            :         }
     342                 :            : 
     343                 :            :         /* If we didn't see a '-', the range start is also the range end. */
     344         [ #  # ]:          0 :         if (rangep[1] == NULL) {
     345                 :          0 :                 context->range.level[1].sens = context->range.level[0].sens;
     346                 :          0 :                 rc = ebitmap_cpy(&context->range.level[1].cat,
     347                 :            :                                  &context->range.level[0].cat);
     348         [ #  # ]:          0 :                 if (rc)
     349                 :          0 :                         return rc;
     350                 :            :         }
     351                 :            : 
     352                 :            :         return 0;
     353                 :            : }
     354                 :            : 
     355                 :            : /*
     356                 :            :  * Set the MLS fields in the security context structure
     357                 :            :  * `context' based on the string representation in
     358                 :            :  * the string `str'.  This function will allocate temporary memory with the
     359                 :            :  * given constraints of gfp_mask.
     360                 :            :  */
     361                 :          0 : int mls_from_string(struct policydb *p, char *str, struct context *context,
     362                 :            :                     gfp_t gfp_mask)
     363                 :            : {
     364                 :          0 :         char *tmpstr;
     365                 :          0 :         int rc;
     366                 :            : 
     367         [ #  # ]:          0 :         if (!p->mls_enabled)
     368                 :            :                 return -EINVAL;
     369                 :            : 
     370                 :          0 :         tmpstr = kstrdup(str, gfp_mask);
     371         [ #  # ]:          0 :         if (!tmpstr) {
     372                 :            :                 rc = -ENOMEM;
     373                 :            :         } else {
     374                 :          0 :                 rc = mls_context_to_sid(p, ':', tmpstr, context,
     375                 :            :                                         NULL, SECSID_NULL);
     376                 :          0 :                 kfree(tmpstr);
     377                 :            :         }
     378                 :            : 
     379                 :            :         return rc;
     380                 :            : }
     381                 :            : 
     382                 :            : /*
     383                 :            :  * Copies the MLS range `range' into `context'.
     384                 :            :  */
     385                 :          0 : int mls_range_set(struct context *context,
     386                 :            :                                 struct mls_range *range)
     387                 :            : {
     388                 :          0 :         int l, rc = 0;
     389                 :            : 
     390                 :            :         /* Copy the MLS range into the  context */
     391   [ #  #  #  # ]:          0 :         for (l = 0; l < 2; l++) {
     392                 :          0 :                 context->range.level[l].sens = range->level[l].sens;
     393                 :          0 :                 rc = ebitmap_cpy(&context->range.level[l].cat,
     394                 :            :                                  &range->level[l].cat);
     395   [ #  #  #  # ]:          0 :                 if (rc)
     396                 :            :                         break;
     397                 :            :         }
     398                 :            : 
     399                 :          0 :         return rc;
     400                 :            : }
     401                 :            : 
     402                 :          0 : int mls_setup_user_range(struct policydb *p,
     403                 :            :                          struct context *fromcon, struct user_datum *user,
     404                 :            :                          struct context *usercon)
     405                 :            : {
     406         [ #  # ]:          0 :         if (p->mls_enabled) {
     407                 :          0 :                 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
     408                 :          0 :                 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
     409                 :          0 :                 struct mls_level *user_low = &(user->range.level[0]);
     410                 :          0 :                 struct mls_level *user_clr = &(user->range.level[1]);
     411                 :          0 :                 struct mls_level *user_def = &(user->dfltlevel);
     412                 :          0 :                 struct mls_level *usercon_sen = &(usercon->range.level[0]);
     413                 :          0 :                 struct mls_level *usercon_clr = &(usercon->range.level[1]);
     414                 :            : 
     415                 :            :                 /* Honor the user's default level if we can */
     416         [ #  # ]:          0 :                 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
     417                 :          0 :                         *usercon_sen = *user_def;
     418         [ #  # ]:          0 :                 else if (mls_level_between(fromcon_sen, user_def, user_clr))
     419                 :          0 :                         *usercon_sen = *fromcon_sen;
     420         [ #  # ]:          0 :                 else if (mls_level_between(fromcon_clr, user_low, user_def))
     421                 :          0 :                         *usercon_sen = *user_low;
     422                 :            :                 else
     423                 :          0 :                         return -EINVAL;
     424                 :            : 
     425                 :            :                 /* Lower the clearance of available contexts
     426                 :            :                    if the clearance of "fromcon" is lower than
     427                 :            :                    that of the user's default clearance (but
     428                 :            :                    only if the "fromcon" clearance dominates
     429                 :            :                    the user's computed sensitivity level) */
     430         [ #  # ]:          0 :                 if (mls_level_dom(user_clr, fromcon_clr))
     431                 :          0 :                         *usercon_clr = *fromcon_clr;
     432         [ #  # ]:          0 :                 else if (mls_level_dom(fromcon_clr, user_clr))
     433                 :          0 :                         *usercon_clr = *user_clr;
     434                 :            :                 else
     435                 :          0 :                         return -EINVAL;
     436                 :            :         }
     437                 :            : 
     438                 :            :         return 0;
     439                 :            : }
     440                 :            : 
     441                 :            : /*
     442                 :            :  * Convert the MLS fields in the security context
     443                 :            :  * structure `oldc' from the values specified in the
     444                 :            :  * policy `oldp' to the values specified in the policy `newp',
     445                 :            :  * storing the resulting context in `newc'.
     446                 :            :  */
     447                 :          0 : int mls_convert_context(struct policydb *oldp,
     448                 :            :                         struct policydb *newp,
     449                 :            :                         struct context *oldc,
     450                 :            :                         struct context *newc)
     451                 :            : {
     452                 :          0 :         struct level_datum *levdatum;
     453                 :          0 :         struct cat_datum *catdatum;
     454                 :          0 :         struct ebitmap_node *node;
     455                 :          0 :         int l, i;
     456                 :            : 
     457   [ #  #  #  # ]:          0 :         if (!oldp->mls_enabled || !newp->mls_enabled)
     458                 :            :                 return 0;
     459                 :            : 
     460         [ #  # ]:          0 :         for (l = 0; l < 2; l++) {
     461                 :          0 :                 levdatum = hashtab_search(newp->p_levels.table,
     462                 :          0 :                                           sym_name(oldp, SYM_LEVELS,
     463                 :          0 :                                                    oldc->range.level[l].sens - 1));
     464                 :            : 
     465         [ #  # ]:          0 :                 if (!levdatum)
     466                 :            :                         return -EINVAL;
     467                 :          0 :                 newc->range.level[l].sens = levdatum->level->sens;
     468                 :            : 
     469         [ #  # ]:          0 :                 ebitmap_for_each_positive_bit(&oldc->range.level[l].cat,
     470                 :            :                                               node, i) {
     471                 :          0 :                         int rc;
     472                 :            : 
     473                 :          0 :                         catdatum = hashtab_search(newp->p_cats.table,
     474                 :            :                                                   sym_name(oldp, SYM_CATS, i));
     475         [ #  # ]:          0 :                         if (!catdatum)
     476                 :            :                                 return -EINVAL;
     477                 :          0 :                         rc = ebitmap_set_bit(&newc->range.level[l].cat,
     478                 :          0 :                                              catdatum->value - 1, 1);
     479         [ #  # ]:          0 :                         if (rc)
     480                 :          0 :                                 return rc;
     481                 :            :                 }
     482                 :            :         }
     483                 :            : 
     484                 :            :         return 0;
     485                 :            : }
     486                 :            : 
     487                 :          0 : int mls_compute_sid(struct policydb *p,
     488                 :            :                     struct context *scontext,
     489                 :            :                     struct context *tcontext,
     490                 :            :                     u16 tclass,
     491                 :            :                     u32 specified,
     492                 :            :                     struct context *newcontext,
     493                 :            :                     bool sock)
     494                 :            : {
     495                 :          0 :         struct range_trans rtr;
     496                 :          0 :         struct mls_range *r;
     497                 :          0 :         struct class_datum *cladatum;
     498                 :          0 :         int default_range = 0;
     499                 :            : 
     500         [ #  # ]:          0 :         if (!p->mls_enabled)
     501                 :            :                 return 0;
     502                 :            : 
     503   [ #  #  #  # ]:          0 :         switch (specified) {
     504                 :          0 :         case AVTAB_TRANSITION:
     505                 :            :                 /* Look for a range transition rule. */
     506                 :          0 :                 rtr.source_type = scontext->type;
     507                 :          0 :                 rtr.target_type = tcontext->type;
     508                 :          0 :                 rtr.target_class = tclass;
     509                 :          0 :                 r = hashtab_search(p->range_tr, &rtr);
     510         [ #  # ]:          0 :                 if (r)
     511                 :          0 :                         return mls_range_set(newcontext, r);
     512                 :            : 
     513   [ #  #  #  # ]:          0 :                 if (tclass && tclass <= p->p_classes.nprim) {
     514                 :          0 :                         cladatum = p->class_val_to_struct[tclass - 1];
     515         [ #  # ]:          0 :                         if (cladatum)
     516                 :          0 :                                 default_range = cladatum->default_range;
     517                 :            :                 }
     518                 :            : 
     519   [ #  #  #  #  :          0 :                 switch (default_range) {
             #  #  #  # ]
     520                 :          0 :                 case DEFAULT_SOURCE_LOW:
     521                 :          0 :                         return mls_context_cpy_low(newcontext, scontext);
     522                 :          0 :                 case DEFAULT_SOURCE_HIGH:
     523                 :          0 :                         return mls_context_cpy_high(newcontext, scontext);
     524                 :          0 :                 case DEFAULT_SOURCE_LOW_HIGH:
     525                 :          0 :                         return mls_context_cpy(newcontext, scontext);
     526                 :          0 :                 case DEFAULT_TARGET_LOW:
     527                 :          0 :                         return mls_context_cpy_low(newcontext, tcontext);
     528                 :          0 :                 case DEFAULT_TARGET_HIGH:
     529                 :          0 :                         return mls_context_cpy_high(newcontext, tcontext);
     530                 :          0 :                 case DEFAULT_TARGET_LOW_HIGH:
     531                 :          0 :                         return mls_context_cpy(newcontext, tcontext);
     532                 :          0 :                 case DEFAULT_GLBLUB:
     533                 :          0 :                         return mls_context_glblub(newcontext,
     534                 :            :                                                   scontext, tcontext);
     535                 :            :                 }
     536                 :            : 
     537                 :            :                 /* Fallthrough */
     538                 :            :         case AVTAB_CHANGE:
     539   [ #  #  #  # ]:          0 :                 if ((tclass == p->process_class) || (sock == true))
     540                 :            :                         /* Use the process MLS attributes. */
     541                 :          0 :                         return mls_context_cpy(newcontext, scontext);
     542                 :            :                 else
     543                 :            :                         /* Use the process effective MLS attributes. */
     544                 :          0 :                         return mls_context_cpy_low(newcontext, scontext);
     545                 :          0 :         case AVTAB_MEMBER:
     546                 :            :                 /* Use the process effective MLS attributes. */
     547                 :          0 :                 return mls_context_cpy_low(newcontext, scontext);
     548                 :            : 
     549                 :            :         /* fall through */
     550                 :            :         }
     551                 :            :         return -EINVAL;
     552                 :            : }
     553                 :            : 
     554                 :            : #ifdef CONFIG_NETLABEL
     555                 :            : /**
     556                 :            :  * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
     557                 :            :  * @context: the security context
     558                 :            :  * @secattr: the NetLabel security attributes
     559                 :            :  *
     560                 :            :  * Description:
     561                 :            :  * Given the security context copy the low MLS sensitivity level into the
     562                 :            :  * NetLabel MLS sensitivity level field.
     563                 :            :  *
     564                 :            :  */
     565                 :          0 : void mls_export_netlbl_lvl(struct policydb *p,
     566                 :            :                            struct context *context,
     567                 :            :                            struct netlbl_lsm_secattr *secattr)
     568                 :            : {
     569         [ #  # ]:          0 :         if (!p->mls_enabled)
     570                 :            :                 return;
     571                 :            : 
     572                 :          0 :         secattr->attr.mls.lvl = context->range.level[0].sens - 1;
     573                 :          0 :         secattr->flags |= NETLBL_SECATTR_MLS_LVL;
     574                 :            : }
     575                 :            : 
     576                 :            : /**
     577                 :            :  * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
     578                 :            :  * @context: the security context
     579                 :            :  * @secattr: the NetLabel security attributes
     580                 :            :  *
     581                 :            :  * Description:
     582                 :            :  * Given the security context and the NetLabel security attributes, copy the
     583                 :            :  * NetLabel MLS sensitivity level into the context.
     584                 :            :  *
     585                 :            :  */
     586                 :          0 : void mls_import_netlbl_lvl(struct policydb *p,
     587                 :            :                            struct context *context,
     588                 :            :                            struct netlbl_lsm_secattr *secattr)
     589                 :            : {
     590         [ #  # ]:          0 :         if (!p->mls_enabled)
     591                 :            :                 return;
     592                 :            : 
     593                 :          0 :         context->range.level[0].sens = secattr->attr.mls.lvl + 1;
     594                 :          0 :         context->range.level[1].sens = context->range.level[0].sens;
     595                 :            : }
     596                 :            : 
     597                 :            : /**
     598                 :            :  * mls_export_netlbl_cat - Export the MLS categories to NetLabel
     599                 :            :  * @context: the security context
     600                 :            :  * @secattr: the NetLabel security attributes
     601                 :            :  *
     602                 :            :  * Description:
     603                 :            :  * Given the security context copy the low MLS categories into the NetLabel
     604                 :            :  * MLS category field.  Returns zero on success, negative values on failure.
     605                 :            :  *
     606                 :            :  */
     607                 :          0 : int mls_export_netlbl_cat(struct policydb *p,
     608                 :            :                           struct context *context,
     609                 :            :                           struct netlbl_lsm_secattr *secattr)
     610                 :            : {
     611                 :          0 :         int rc;
     612                 :            : 
     613         [ #  # ]:          0 :         if (!p->mls_enabled)
     614                 :            :                 return 0;
     615                 :            : 
     616                 :          0 :         rc = ebitmap_netlbl_export(&context->range.level[0].cat,
     617                 :            :                                    &secattr->attr.mls.cat);
     618   [ #  #  #  # ]:          0 :         if (rc == 0 && secattr->attr.mls.cat != NULL)
     619                 :          0 :                 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
     620                 :            : 
     621                 :            :         return rc;
     622                 :            : }
     623                 :            : 
     624                 :            : /**
     625                 :            :  * mls_import_netlbl_cat - Import the MLS categories from NetLabel
     626                 :            :  * @context: the security context
     627                 :            :  * @secattr: the NetLabel security attributes
     628                 :            :  *
     629                 :            :  * Description:
     630                 :            :  * Copy the NetLabel security attributes into the SELinux context; since the
     631                 :            :  * NetLabel security attribute only contains a single MLS category use it for
     632                 :            :  * both the low and high categories of the context.  Returns zero on success,
     633                 :            :  * negative values on failure.
     634                 :            :  *
     635                 :            :  */
     636                 :          0 : int mls_import_netlbl_cat(struct policydb *p,
     637                 :            :                           struct context *context,
     638                 :            :                           struct netlbl_lsm_secattr *secattr)
     639                 :            : {
     640                 :          0 :         int rc;
     641                 :            : 
     642         [ #  # ]:          0 :         if (!p->mls_enabled)
     643                 :            :                 return 0;
     644                 :            : 
     645                 :          0 :         rc = ebitmap_netlbl_import(&context->range.level[0].cat,
     646                 :            :                                    secattr->attr.mls.cat);
     647         [ #  # ]:          0 :         if (rc)
     648                 :          0 :                 goto import_netlbl_cat_failure;
     649                 :          0 :         memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
     650                 :            :                sizeof(context->range.level[0].cat));
     651                 :            : 
     652                 :          0 :         return 0;
     653                 :            : 
     654                 :            : import_netlbl_cat_failure:
     655                 :          0 :         ebitmap_destroy(&context->range.level[0].cat);
     656                 :          0 :         return rc;
     657                 :            : }
     658                 :            : #endif /* CONFIG_NETLABEL */

Generated by: LCOV version 1.14