blob: d338962fb0c48427d80088579978289aa5618aa7 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Implementation of the multi-level security (MLS) policy.
4 *
Stephen Smalley7efbb602017-08-17 13:32:36 -04005 * Author : Stephen Smalley, <sds@tycho.nsa.gov>
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7/*
8 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
9 *
10 * Support for enhanced MLS infrastructure.
11 *
Darrel Goeddel376bd9c2006-02-24 15:44:05 -060012 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 */
Venkat Yekkirala7420ed22006-08-04 23:17:57 -070014/*
Paul Moore82c21bf2011-08-01 11:10:33 +000015 * Updated: Hewlett-Packard <paul@paul-moore.com>
Venkat Yekkirala7420ed22006-08-04 23:17:57 -070016 *
Paul Moore02752762006-11-29 13:18:18 -050017 * Added support to import/export the MLS label from NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -070018 *
19 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
20 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/string.h>
25#include <linux/errno.h>
Paul Moore02752762006-11-29 13:18:18 -050026#include <net/netlabel.h>
James Morrisf5c1d5b2005-07-28 01:07:37 -070027#include "sidtab.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#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 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050036int mls_compute_context_len(struct policydb *p, struct context *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -070037{
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090038 int i, l, len, head, prev;
39 char *nm;
40 struct ebitmap *e;
Stephen Smalley782ebb92005-09-03 15:55:16 -070041 struct ebitmap_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050043 if (!p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 return 0;
45
46 len = 1; /* for the beginning ":" */
47 for (l = 0; l < 2; l++) {
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090048 int index_sens = context->range.level[l].sens;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050049 len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090051 /* categories */
52 head = -2;
53 prev = -2;
54 e = &context->range.level[l].cat;
55 ebitmap_for_each_positive_bit(e, node, i) {
56 if (i - prev > 1) {
57 /* one or more negative bits are skipped */
58 if (head != prev) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050059 nm = sym_name(p, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090060 len += strlen(nm) + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 }
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050062 nm = sym_name(p, SYM_CATS, i);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090063 len += strlen(nm) + 1;
64 head = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090066 prev = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090068 if (prev != head) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050069 nm = sym_name(p, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090070 len += strlen(nm) + 1;
71 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 if (l == 0) {
73 if (mls_level_eq(&context->range.level[0],
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090074 &context->range.level[1]))
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 break;
76 else
77 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 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050089void mls_sid_to_context(struct policydb *p,
90 struct context *context,
Eric Paris1a5e6f82008-04-18 17:38:32 -040091 char **scontext)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092{
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090093 char *scontextp, *nm;
94 int i, l, head, prev;
95 struct ebitmap *e;
Stephen Smalley782ebb92005-09-03 15:55:16 -070096 struct ebitmap_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Stephen Smalleyaa8e7122018-03-01 18:48:02 -050098 if (!p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 return;
100
101 scontextp = *scontext;
102
103 *scontextp = ':';
104 scontextp++;
105
106 for (l = 0; l < 2; l++) {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500107 strcpy(scontextp, sym_name(p, SYM_LEVELS,
Eric Parisac76c05b2010-11-29 15:47:09 -0500108 context->range.level[l].sens - 1));
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900109 scontextp += strlen(scontextp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111 /* categories */
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900112 head = -2;
113 prev = -2;
114 e = &context->range.level[l].cat;
115 ebitmap_for_each_positive_bit(e, node, i) {
116 if (i - prev > 1) {
117 /* one or more negative bits are skipped */
118 if (prev != head) {
119 if (prev - head > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 *scontextp++ = '.';
121 else
122 *scontextp++ = ',';
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500123 nm = sym_name(p, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900124 strcpy(scontextp, nm);
125 scontextp += strlen(nm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900127 if (prev < 0)
128 *scontextp++ = ':';
129 else
130 *scontextp++ = ',';
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500131 nm = sym_name(p, SYM_CATS, i);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900132 strcpy(scontextp, nm);
133 scontextp += strlen(nm);
134 head = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900136 prev = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 }
138
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900139 if (prev != head) {
140 if (prev - head > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 *scontextp++ = '.';
142 else
143 *scontextp++ = ',';
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500144 nm = sym_name(p, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900145 strcpy(scontextp, nm);
146 scontextp += strlen(nm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 }
148
149 if (l == 0) {
150 if (mls_level_eq(&context->range.level[0],
Eric Paris1a5e6f82008-04-18 17:38:32 -0400151 &context->range.level[1]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 break;
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900153 else
154 *scontextp++ = '-';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 }
156 }
157
158 *scontext = scontextp;
159 return;
160}
161
Stephen Smalley45e54212007-11-07 10:08:00 -0500162int mls_level_isvalid(struct policydb *p, struct mls_level *l)
163{
164 struct level_datum *levdatum;
Stephen Smalley45e54212007-11-07 10:08:00 -0500165
166 if (!l->sens || l->sens > p->p_levels.nprim)
167 return 0;
Ondrej Mosnacek237389e2020-07-08 13:24:45 +0200168 levdatum = symtab_search(&p->p_levels,
169 sym_name(p, SYM_LEVELS, l->sens - 1));
Stephen Smalley45e54212007-11-07 10:08:00 -0500170 if (!levdatum)
171 return 0;
172
Waiman Longfee71142013-07-23 17:38:41 -0400173 /*
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 return ebitmap_contains(&levdatum->level->cat, &l->cat,
179 p->p_cats.nprim);
Stephen Smalley45e54212007-11-07 10:08:00 -0500180}
181
182int mls_range_isvalid(struct policydb *p, struct mls_range *r)
183{
184 return (mls_level_isvalid(p, &r->level[0]) &&
185 mls_level_isvalid(p, &r->level[1]) &&
186 mls_level_dom(&r->level[1], &r->level[0]));
187}
188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189/*
190 * Return 1 if the MLS fields in the security context
191 * structure `c' are valid. Return 0 otherwise.
192 */
193int mls_context_isvalid(struct policydb *p, struct context *c)
194{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 struct user_datum *usrdatum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100197 if (!p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 return 1;
199
Stephen Smalley45e54212007-11-07 10:08:00 -0500200 if (!mls_range_isvalid(p, &c->range))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 return 0;
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 if (c->role == OBJECT_R_VAL)
204 return 1;
205
206 /*
207 * User must be authorized for the MLS range.
208 */
209 if (!c->user || c->user > p->p_users.nprim)
210 return 0;
211 usrdatum = p->user_val_to_struct[c->user - 1];
212 if (!mls_range_contains(usrdatum->range, c->range))
213 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
Jann Horn95ffe192018-08-06 23:19:32 +0200221 * the string `scontext'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 *
223 * This function modifies the string in place, inserting
224 * NULL characters to terminate the MLS fields.
James Morrisf5c1d5b2005-07-28 01:07:37 -0700225 *
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 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 */
Stephen Smalley12b29f32008-05-07 13:03:20 -0400234int mls_context_to_sid(struct policydb *pol,
235 char oldc,
Jann Horn95ffe192018-08-06 23:19:32 +0200236 char *scontext,
James Morrisf5c1d5b2005-07-28 01:07:37 -0700237 struct context *context,
238 struct sidtab *s,
239 u32 def_sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
Jann Horn95ffe192018-08-06 23:19:32 +0200241 char *sensitivity, *cur_cat, *next_cat, *rngptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 struct level_datum *levdatum;
243 struct cat_datum *catdatum, *rngdatum;
Jann Horn95ffe192018-08-06 23:19:32 +0200244 int l, rc, i;
245 char *rangep[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100247 if (!pol->mls_enabled) {
Paul Moore877181a2018-11-13 21:44:33 -0500248 /*
249 * With no MLS, only return -EINVAL if there is a MLS field
250 * and it did not come from an xattr.
251 */
252 if (oldc && def_sid == SECSID_NULL)
253 return -EINVAL;
254 return 0;
Stephen Smalleye517a0c2005-11-08 21:34:32 -0800255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
James Morrisf5c1d5b2005-07-28 01:07:37 -0700257 /*
258 * No MLS component to the security context, try and map to
259 * default if provided.
260 */
261 if (!oldc) {
262 struct context *defcon;
263
264 if (def_sid == SECSID_NULL)
Jann Horn95ffe192018-08-06 23:19:32 +0200265 return -EINVAL;
James Morrisf5c1d5b2005-07-28 01:07:37 -0700266
267 defcon = sidtab_search(s, def_sid);
268 if (!defcon)
Jann Horn95ffe192018-08-06 23:19:32 +0200269 return -EINVAL;
James Morrisf5c1d5b2005-07-28 01:07:37 -0700270
Jann Horn95ffe192018-08-06 23:19:32 +0200271 return mls_context_cpy(context, defcon);
James Morrisf5c1d5b2005-07-28 01:07:37 -0700272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
Jann Horn95ffe192018-08-06 23:19:32 +0200274 /*
275 * If we're dealing with a range, figure out where the two parts
276 * of the range begin.
277 */
278 rangep[0] = scontext;
279 rangep[1] = strchr(scontext, '-');
280 if (rangep[1]) {
281 rangep[1][0] = '\0';
282 rangep[1]++;
283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Jann Horn95ffe192018-08-06 23:19:32 +0200285 /* For each part of the range: */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 for (l = 0; l < 2; l++) {
Jann Horn95ffe192018-08-06 23:19:32 +0200287 /* Split sensitivity and category set. */
288 sensitivity = rangep[l];
289 if (sensitivity == NULL)
290 break;
291 next_cat = strchr(sensitivity, ':');
292 if (next_cat)
293 *(next_cat++) = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Jann Horn95ffe192018-08-06 23:19:32 +0200295 /* Parse sensitivity. */
Ondrej Mosnacek237389e2020-07-08 13:24:45 +0200296 levdatum = symtab_search(&pol->p_levels, sensitivity);
Jann Horn95ffe192018-08-06 23:19:32 +0200297 if (!levdatum)
298 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 context->range.level[l].sens = levdatum->level->sens;
300
Jann Horn95ffe192018-08-06 23:19:32 +0200301 /* Extract category set. */
302 while (next_cat != NULL) {
303 cur_cat = next_cat;
304 next_cat = strchr(next_cat, ',');
305 if (next_cat != NULL)
306 *(next_cat++) = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Jann Horn95ffe192018-08-06 23:19:32 +0200308 /* Separate into range if exists */
309 rngptr = strchr(cur_cat, '.');
310 if (rngptr != NULL) {
311 /* Remove '.' */
312 *rngptr++ = '\0';
313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
Ondrej Mosnacek237389e2020-07-08 13:24:45 +0200315 catdatum = symtab_search(&pol->p_cats, cur_cat);
Jann Horn95ffe192018-08-06 23:19:32 +0200316 if (!catdatum)
317 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Jann Horn95ffe192018-08-06 23:19:32 +0200319 rc = ebitmap_set_bit(&context->range.level[l].cat,
320 catdatum->value - 1, 1);
321 if (rc)
322 return rc;
323
324 /* If range, set all categories in range */
325 if (rngptr == NULL)
326 continue;
327
Ondrej Mosnacek237389e2020-07-08 13:24:45 +0200328 rngdatum = symtab_search(&pol->p_cats, rngptr);
Jann Horn95ffe192018-08-06 23:19:32 +0200329 if (!rngdatum)
330 return -EINVAL;
331
332 if (catdatum->value >= rngdatum->value)
333 return -EINVAL;
334
335 for (i = catdatum->value; i < rngdatum->value; i++) {
336 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 if (rc)
Jann Horn95ffe192018-08-06 23:19:32 +0200338 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 }
340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 }
342
Jann Horn95ffe192018-08-06 23:19:32 +0200343 /* If we didn't see a '-', the range start is also the range end. */
344 if (rangep[1] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 context->range.level[1].sens = context->range.level[0].sens;
346 rc = ebitmap_cpy(&context->range.level[1].cat,
347 &context->range.level[0].cat);
348 if (rc)
Jann Horn95ffe192018-08-06 23:19:32 +0200349 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 }
Jann Horn95ffe192018-08-06 23:19:32 +0200351
352 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
354
355/*
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600356 * 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 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500361int mls_from_string(struct policydb *p, char *str, struct context *context,
362 gfp_t gfp_mask)
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600363{
Jann Horn95ffe192018-08-06 23:19:32 +0200364 char *tmpstr;
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600365 int rc;
366
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500367 if (!p->mls_enabled)
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600368 return -EINVAL;
369
Jann Horn95ffe192018-08-06 23:19:32 +0200370 tmpstr = kstrdup(str, gfp_mask);
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600371 if (!tmpstr) {
372 rc = -ENOMEM;
373 } else {
Jann Horn95ffe192018-08-06 23:19:32 +0200374 rc = mls_context_to_sid(p, ':', tmpstr, context,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400375 NULL, SECSID_NULL);
Jann Horn95ffe192018-08-06 23:19:32 +0200376 kfree(tmpstr);
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600377 }
378
379 return rc;
380}
381
382/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 * Copies the MLS range `range' into `context'.
384 */
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100385int mls_range_set(struct context *context,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400386 struct mls_range *range)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
388 int l, rc = 0;
389
390 /* Copy the MLS range into the context */
391 for (l = 0; l < 2; l++) {
392 context->range.level[l].sens = range->level[l].sens;
393 rc = ebitmap_cpy(&context->range.level[l].cat,
394 &range->level[l].cat);
395 if (rc)
396 break;
397 }
398
399 return rc;
400}
401
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500402int mls_setup_user_range(struct policydb *p,
403 struct context *fromcon, struct user_datum *user,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400404 struct context *usercon)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500406 if (p->mls_enabled) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
408 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
409 struct mls_level *user_low = &(user->range.level[0]);
410 struct mls_level *user_clr = &(user->range.level[1]);
411 struct mls_level *user_def = &(user->dfltlevel);
412 struct mls_level *usercon_sen = &(usercon->range.level[0]);
413 struct mls_level *usercon_clr = &(usercon->range.level[1]);
414
415 /* Honor the user's default level if we can */
Eric Parisf5269712008-05-14 11:27:45 -0400416 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 *usercon_sen = *user_def;
Eric Parisf5269712008-05-14 11:27:45 -0400418 else if (mls_level_between(fromcon_sen, user_def, user_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 *usercon_sen = *fromcon_sen;
Eric Parisf5269712008-05-14 11:27:45 -0400420 else if (mls_level_between(fromcon_clr, user_low, user_def))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 *usercon_sen = *user_low;
Eric Parisf5269712008-05-14 11:27:45 -0400422 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 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) */
Eric Paris1a5e6f82008-04-18 17:38:32 -0400430 if (mls_level_dom(user_clr, fromcon_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 *usercon_clr = *fromcon_clr;
Eric Paris1a5e6f82008-04-18 17:38:32 -0400432 else if (mls_level_dom(fromcon_clr, user_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 *usercon_clr = *user_clr;
Eric Paris1a5e6f82008-04-18 17:38:32 -0400434 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 return -EINVAL;
436 }
437
438 return 0;
439}
440
441/*
442 * Convert the MLS fields in the security context
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100443 * 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'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 */
447int mls_convert_context(struct policydb *oldp,
448 struct policydb *newp,
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100449 struct context *oldc,
450 struct context *newc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
452 struct level_datum *levdatum;
453 struct cat_datum *catdatum;
Stephen Smalley782ebb92005-09-03 15:55:16 -0700454 struct ebitmap_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 int l, i;
456
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500457 if (!oldp->mls_enabled || !newp->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 return 0;
459
460 for (l = 0; l < 2; l++) {
Ondrej Mosnacek237389e2020-07-08 13:24:45 +0200461 char *name = sym_name(oldp, SYM_LEVELS,
462 oldc->range.level[l].sens - 1);
463
464 levdatum = symtab_search(&newp->p_levels, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
466 if (!levdatum)
467 return -EINVAL;
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100468 newc->range.level[l].sens = levdatum->level->sens;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100470 ebitmap_for_each_positive_bit(&oldc->range.level[l].cat,
471 node, i) {
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900472 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
Ondrej Mosnacek237389e2020-07-08 13:24:45 +0200474 catdatum = symtab_search(&newp->p_cats,
475 sym_name(oldp, SYM_CATS, i));
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900476 if (!catdatum)
477 return -EINVAL;
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100478 rc = ebitmap_set_bit(&newc->range.level[l].cat,
479 catdatum->value - 1, 1);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900480 if (rc)
481 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
484
485 return 0;
486}
487
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500488int mls_compute_sid(struct policydb *p,
489 struct context *scontext,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 struct context *tcontext,
491 u16 tclass,
492 u32 specified,
Harry Ciao6f5317e2011-03-02 13:32:33 +0800493 struct context *newcontext,
494 bool sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500496 struct range_trans rtr;
497 struct mls_range *r;
Eric Parisaa893262012-03-20 14:35:12 -0400498 struct class_datum *cladatum;
499 int default_range = 0;
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700500
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500501 if (!p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 return 0;
503
504 switch (specified) {
505 case AVTAB_TRANSITION:
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700506 /* Look for a range transition rule. */
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500507 rtr.source_type = scontext->type;
508 rtr.target_type = tcontext->type;
509 rtr.target_class = tclass;
Ondrej Mosnacek24def7b2020-07-09 21:19:51 +0200510 r = policydb_rangetr_search(p, &rtr);
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500511 if (r)
512 return mls_range_set(newcontext, r);
Eric Parisaa893262012-03-20 14:35:12 -0400513
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500514 if (tclass && tclass <= p->p_classes.nprim) {
515 cladatum = p->class_val_to_struct[tclass - 1];
Eric Parisaa893262012-03-20 14:35:12 -0400516 if (cladatum)
517 default_range = cladatum->default_range;
518 }
519
520 switch (default_range) {
521 case DEFAULT_SOURCE_LOW:
522 return mls_context_cpy_low(newcontext, scontext);
523 case DEFAULT_SOURCE_HIGH:
524 return mls_context_cpy_high(newcontext, scontext);
525 case DEFAULT_SOURCE_LOW_HIGH:
526 return mls_context_cpy(newcontext, scontext);
527 case DEFAULT_TARGET_LOW:
528 return mls_context_cpy_low(newcontext, tcontext);
529 case DEFAULT_TARGET_HIGH:
530 return mls_context_cpy_high(newcontext, tcontext);
531 case DEFAULT_TARGET_LOW_HIGH:
532 return mls_context_cpy(newcontext, tcontext);
Joshua Brindle42345b62019-09-04 14:03:23 -0700533 case DEFAULT_GLBLUB:
534 return mls_context_glblub(newcontext,
535 scontext, tcontext);
Eric Parisaa893262012-03-20 14:35:12 -0400536 }
537
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -0500538 fallthrough;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 case AVTAB_CHANGE:
Zou Wei4b850392020-04-14 16:18:07 +0800540 if ((tclass == p->process_class) || sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 /* Use the process MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600542 return mls_context_cpy(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 else
544 /* Use the process effective MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600545 return mls_context_cpy_low(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 case AVTAB_MEMBER:
Eamon Walsh2e08c0c2008-01-24 15:30:52 -0500547 /* Use the process effective MLS attributes. */
548 return mls_context_cpy_low(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 }
550 return -EINVAL;
551}
552
Paul Moore02752762006-11-29 13:18:18 -0500553#ifdef CONFIG_NETLABEL
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700554/**
Paul Moore02752762006-11-29 13:18:18 -0500555 * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700556 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500557 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700558 *
559 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500560 * Given the security context copy the low MLS sensitivity level into the
561 * NetLabel MLS sensitivity level field.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700562 *
563 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500564void mls_export_netlbl_lvl(struct policydb *p,
565 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500566 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700567{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500568 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700569 return;
570
Paul Moore16efd452008-01-29 08:37:59 -0500571 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
Paul Moore02752762006-11-29 13:18:18 -0500572 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700573}
574
575/**
Paul Moore02752762006-11-29 13:18:18 -0500576 * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700577 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500578 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700579 *
580 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500581 * Given the security context and the NetLabel security attributes, copy the
582 * NetLabel MLS sensitivity level into the context.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700583 *
584 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500585void mls_import_netlbl_lvl(struct policydb *p,
586 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500587 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700588{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500589 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700590 return;
591
Paul Moore16efd452008-01-29 08:37:59 -0500592 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
Paul Moore02752762006-11-29 13:18:18 -0500593 context->range.level[1].sens = context->range.level[0].sens;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700594}
595
596/**
Paul Moore02752762006-11-29 13:18:18 -0500597 * mls_export_netlbl_cat - Export the MLS categories to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700598 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500599 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700600 *
601 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500602 * Given the security context copy the low MLS categories into the NetLabel
603 * MLS category field. Returns zero on success, negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700604 *
605 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500606int mls_export_netlbl_cat(struct policydb *p,
607 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500608 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700609{
Paul Moore02752762006-11-29 13:18:18 -0500610 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700611
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500612 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700613 return 0;
614
Paul Moore02752762006-11-29 13:18:18 -0500615 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500616 &secattr->attr.mls.cat);
617 if (rc == 0 && secattr->attr.mls.cat != NULL)
Paul Moore02752762006-11-29 13:18:18 -0500618 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700619
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700620 return rc;
621}
622
623/**
Paul Moore02752762006-11-29 13:18:18 -0500624 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700625 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500626 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700627 *
628 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500629 * Copy the NetLabel security attributes into the SELinux context; since the
630 * NetLabel security attribute only contains a single MLS category use it for
631 * both the low and high categories of the context. Returns zero on success,
632 * negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700633 *
634 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500635int mls_import_netlbl_cat(struct policydb *p,
636 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500637 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700638{
Paul Moore02752762006-11-29 13:18:18 -0500639 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700640
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500641 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700642 return 0;
643
Paul Moore02752762006-11-29 13:18:18 -0500644 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500645 secattr->attr.mls.cat);
Paul Mooreda8026f2015-02-17 15:30:23 -0500646 if (rc)
Paul Moore02752762006-11-29 13:18:18 -0500647 goto import_netlbl_cat_failure;
Paul Mooreda8026f2015-02-17 15:30:23 -0500648 memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
649 sizeof(context->range.level[0].cat));
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700650
651 return 0;
652
Paul Moore02752762006-11-29 13:18:18 -0500653import_netlbl_cat_failure:
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700654 ebitmap_destroy(&context->range.level[0].cat);
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700655 return rc;
656}
Paul Moore02752762006-11-29 13:18:18 -0500657#endif /* CONFIG_NETLABEL */