blob: 39475fb455bc0d34dbf94305dd687a76c96ebab3 [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;
168 levdatum = hashtab_search(p->p_levels.table,
Eric Parisac76c05b2010-11-29 15:47:09 -0500169 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
221 * the string `*scontext'. Update `*scontext' to
222 * point to the end of the string representation of
223 * the MLS fields.
224 *
225 * This function modifies the string in place, inserting
226 * NULL characters to terminate the MLS fields.
James Morrisf5c1d5b2005-07-28 01:07:37 -0700227 *
228 * If a def_sid is provided and no MLS field is present,
229 * copy the MLS field of the associated default context.
230 * Used for upgraded to MLS systems where objects may lack
231 * MLS fields.
232 *
233 * Policy read-lock must be held for sidtab lookup.
234 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 */
Stephen Smalley12b29f32008-05-07 13:03:20 -0400236int mls_context_to_sid(struct policydb *pol,
237 char oldc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 char **scontext,
James Morrisf5c1d5b2005-07-28 01:07:37 -0700239 struct context *context,
240 struct sidtab *s,
241 u32 def_sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242{
243
244 char delim;
245 char *scontextp, *p, *rngptr;
246 struct level_datum *levdatum;
247 struct cat_datum *catdatum, *rngdatum;
248 int l, rc = -EINVAL;
249
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100250 if (!pol->mls_enabled) {
Stephen Smalleye517a0c2005-11-08 21:34:32 -0800251 if (def_sid != SECSID_NULL && oldc)
wzt.wzt@gmail.comc1a73682010-04-09 19:30:29 +0800252 *scontext += strlen(*scontext) + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 return 0;
Stephen Smalleye517a0c2005-11-08 21:34:32 -0800254 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
James Morrisf5c1d5b2005-07-28 01:07:37 -0700256 /*
257 * No MLS component to the security context, try and map to
258 * default if provided.
259 */
260 if (!oldc) {
261 struct context *defcon;
262
263 if (def_sid == SECSID_NULL)
264 goto out;
265
266 defcon = sidtab_search(s, def_sid);
267 if (!defcon)
268 goto out;
269
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600270 rc = mls_context_cpy(context, defcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 goto out;
James Morrisf5c1d5b2005-07-28 01:07:37 -0700272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
274 /* Extract low sensitivity. */
275 scontextp = p = *scontext;
276 while (*p && *p != ':' && *p != '-')
277 p++;
278
279 delim = *p;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300280 if (delim != '\0')
281 *p++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
283 for (l = 0; l < 2; l++) {
Stephen Smalley12b29f32008-05-07 13:03:20 -0400284 levdatum = hashtab_search(pol->p_levels.table, scontextp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 if (!levdatum) {
286 rc = -EINVAL;
287 goto out;
288 }
289
290 context->range.level[l].sens = levdatum->level->sens;
291
292 if (delim == ':') {
293 /* Extract category set. */
294 while (1) {
295 scontextp = p;
296 while (*p && *p != ',' && *p != '-')
297 p++;
298 delim = *p;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300299 if (delim != '\0')
300 *p++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
302 /* Separate into range if exists */
Eric Paris1a5e6f82008-04-18 17:38:32 -0400303 rngptr = strchr(scontextp, '.');
304 if (rngptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 /* Remove '.' */
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300306 *rngptr++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 }
308
Stephen Smalley12b29f32008-05-07 13:03:20 -0400309 catdatum = hashtab_search(pol->p_cats.table,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400310 scontextp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 if (!catdatum) {
312 rc = -EINVAL;
313 goto out;
314 }
315
316 rc = ebitmap_set_bit(&context->range.level[l].cat,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400317 catdatum->value - 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 if (rc)
319 goto out;
320
321 /* If range, set all categories in range */
322 if (rngptr) {
323 int i;
324
Stephen Smalley12b29f32008-05-07 13:03:20 -0400325 rngdatum = hashtab_search(pol->p_cats.table, rngptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 if (!rngdatum) {
327 rc = -EINVAL;
328 goto out;
329 }
330
331 if (catdatum->value >= rngdatum->value) {
332 rc = -EINVAL;
333 goto out;
334 }
335
336 for (i = catdatum->value; i < rngdatum->value; i++) {
337 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
338 if (rc)
339 goto out;
340 }
341 }
342
343 if (delim != ',')
344 break;
345 }
346 }
347 if (delim == '-') {
348 /* Extract high sensitivity. */
349 scontextp = p;
350 while (*p && *p != ':')
351 p++;
352
353 delim = *p;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300354 if (delim != '\0')
355 *p++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 } else
357 break;
358 }
359
360 if (l == 0) {
361 context->range.level[1].sens = context->range.level[0].sens;
362 rc = ebitmap_cpy(&context->range.level[1].cat,
363 &context->range.level[0].cat);
364 if (rc)
365 goto out;
366 }
367 *scontext = ++p;
368 rc = 0;
369out:
370 return rc;
371}
372
373/*
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600374 * Set the MLS fields in the security context structure
375 * `context' based on the string representation in
376 * the string `str'. This function will allocate temporary memory with the
377 * given constraints of gfp_mask.
378 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500379int mls_from_string(struct policydb *p, char *str, struct context *context,
380 gfp_t gfp_mask)
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600381{
382 char *tmpstr, *freestr;
383 int rc;
384
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500385 if (!p->mls_enabled)
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600386 return -EINVAL;
387
388 /* we need freestr because mls_context_to_sid will change
389 the value of tmpstr */
390 tmpstr = freestr = kstrdup(str, gfp_mask);
391 if (!tmpstr) {
392 rc = -ENOMEM;
393 } else {
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500394 rc = mls_context_to_sid(p, ':', &tmpstr, context,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400395 NULL, SECSID_NULL);
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600396 kfree(freestr);
397 }
398
399 return rc;
400}
401
402/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 * Copies the MLS range `range' into `context'.
404 */
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100405int mls_range_set(struct context *context,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400406 struct mls_range *range)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407{
408 int l, rc = 0;
409
410 /* Copy the MLS range into the context */
411 for (l = 0; l < 2; l++) {
412 context->range.level[l].sens = range->level[l].sens;
413 rc = ebitmap_cpy(&context->range.level[l].cat,
414 &range->level[l].cat);
415 if (rc)
416 break;
417 }
418
419 return rc;
420}
421
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500422int mls_setup_user_range(struct policydb *p,
423 struct context *fromcon, struct user_datum *user,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400424 struct context *usercon)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500426 if (p->mls_enabled) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
428 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
429 struct mls_level *user_low = &(user->range.level[0]);
430 struct mls_level *user_clr = &(user->range.level[1]);
431 struct mls_level *user_def = &(user->dfltlevel);
432 struct mls_level *usercon_sen = &(usercon->range.level[0]);
433 struct mls_level *usercon_clr = &(usercon->range.level[1]);
434
435 /* Honor the user's default level if we can */
Eric Parisf5269712008-05-14 11:27:45 -0400436 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 *usercon_sen = *user_def;
Eric Parisf5269712008-05-14 11:27:45 -0400438 else if (mls_level_between(fromcon_sen, user_def, user_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 *usercon_sen = *fromcon_sen;
Eric Parisf5269712008-05-14 11:27:45 -0400440 else if (mls_level_between(fromcon_clr, user_low, user_def))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 *usercon_sen = *user_low;
Eric Parisf5269712008-05-14 11:27:45 -0400442 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 return -EINVAL;
444
445 /* Lower the clearance of available contexts
446 if the clearance of "fromcon" is lower than
447 that of the user's default clearance (but
448 only if the "fromcon" clearance dominates
449 the user's computed sensitivity level) */
Eric Paris1a5e6f82008-04-18 17:38:32 -0400450 if (mls_level_dom(user_clr, fromcon_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 *usercon_clr = *fromcon_clr;
Eric Paris1a5e6f82008-04-18 17:38:32 -0400452 else if (mls_level_dom(fromcon_clr, user_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 *usercon_clr = *user_clr;
Eric Paris1a5e6f82008-04-18 17:38:32 -0400454 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 return -EINVAL;
456 }
457
458 return 0;
459}
460
461/*
462 * Convert the MLS fields in the security context
463 * structure `c' from the values specified in the
464 * policy `oldp' to the values specified in the policy `newp'.
465 */
466int mls_convert_context(struct policydb *oldp,
467 struct policydb *newp,
468 struct context *c)
469{
470 struct level_datum *levdatum;
471 struct cat_datum *catdatum;
472 struct ebitmap bitmap;
Stephen Smalley782ebb92005-09-03 15:55:16 -0700473 struct ebitmap_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 int l, i;
475
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500476 if (!oldp->mls_enabled || !newp->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 return 0;
478
479 for (l = 0; l < 2; l++) {
480 levdatum = hashtab_search(newp->p_levels.table,
Eric Parisac76c05b2010-11-29 15:47:09 -0500481 sym_name(oldp, SYM_LEVELS,
482 c->range.level[l].sens - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 if (!levdatum)
485 return -EINVAL;
486 c->range.level[l].sens = levdatum->level->sens;
487
488 ebitmap_init(&bitmap);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900489 ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
490 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900492 catdatum = hashtab_search(newp->p_cats.table,
Eric Parisac76c05b2010-11-29 15:47:09 -0500493 sym_name(oldp, SYM_CATS, i));
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900494 if (!catdatum)
495 return -EINVAL;
496 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
497 if (rc)
498 return rc;
Dave Jones9a591f32014-05-15 15:02:53 -0400499
500 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 }
502 ebitmap_destroy(&c->range.level[l].cat);
503 c->range.level[l].cat = bitmap;
504 }
505
506 return 0;
507}
508
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500509int mls_compute_sid(struct policydb *p,
510 struct context *scontext,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 struct context *tcontext,
512 u16 tclass,
513 u32 specified,
Harry Ciao6f5317e2011-03-02 13:32:33 +0800514 struct context *newcontext,
515 bool sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516{
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500517 struct range_trans rtr;
518 struct mls_range *r;
Eric Parisaa893262012-03-20 14:35:12 -0400519 struct class_datum *cladatum;
520 int default_range = 0;
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700521
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500522 if (!p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 return 0;
524
525 switch (specified) {
526 case AVTAB_TRANSITION:
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700527 /* Look for a range transition rule. */
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500528 rtr.source_type = scontext->type;
529 rtr.target_type = tcontext->type;
530 rtr.target_class = tclass;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500531 r = hashtab_search(p->range_tr, &rtr);
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500532 if (r)
533 return mls_range_set(newcontext, r);
Eric Parisaa893262012-03-20 14:35:12 -0400534
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500535 if (tclass && tclass <= p->p_classes.nprim) {
536 cladatum = p->class_val_to_struct[tclass - 1];
Eric Parisaa893262012-03-20 14:35:12 -0400537 if (cladatum)
538 default_range = cladatum->default_range;
539 }
540
541 switch (default_range) {
542 case DEFAULT_SOURCE_LOW:
543 return mls_context_cpy_low(newcontext, scontext);
544 case DEFAULT_SOURCE_HIGH:
545 return mls_context_cpy_high(newcontext, scontext);
546 case DEFAULT_SOURCE_LOW_HIGH:
547 return mls_context_cpy(newcontext, scontext);
548 case DEFAULT_TARGET_LOW:
549 return mls_context_cpy_low(newcontext, tcontext);
550 case DEFAULT_TARGET_HIGH:
551 return mls_context_cpy_high(newcontext, tcontext);
552 case DEFAULT_TARGET_LOW_HIGH:
553 return mls_context_cpy(newcontext, tcontext);
554 }
555
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 /* Fallthrough */
557 case AVTAB_CHANGE:
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500558 if ((tclass == p->process_class) || (sock == true))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 /* Use the process MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600560 return mls_context_cpy(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 else
562 /* Use the process effective MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600563 return mls_context_cpy_low(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 case AVTAB_MEMBER:
Eamon Walsh2e08c0c2008-01-24 15:30:52 -0500565 /* Use the process effective MLS attributes. */
566 return mls_context_cpy_low(newcontext, scontext);
Amerigo Wang08e3daf2009-12-03 03:48:28 -0500567
568 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 }
570 return -EINVAL;
571}
572
Paul Moore02752762006-11-29 13:18:18 -0500573#ifdef CONFIG_NETLABEL
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700574/**
Paul Moore02752762006-11-29 13:18:18 -0500575 * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700576 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500577 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700578 *
579 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500580 * Given the security context copy the low MLS sensitivity level into the
581 * NetLabel MLS sensitivity level field.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700582 *
583 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500584void mls_export_netlbl_lvl(struct policydb *p,
585 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500586 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700587{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500588 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700589 return;
590
Paul Moore16efd452008-01-29 08:37:59 -0500591 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
Paul Moore02752762006-11-29 13:18:18 -0500592 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700593}
594
595/**
Paul Moore02752762006-11-29 13:18:18 -0500596 * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700597 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500598 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700599 *
600 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500601 * Given the security context and the NetLabel security attributes, copy the
602 * NetLabel MLS sensitivity level into the context.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700603 *
604 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500605void mls_import_netlbl_lvl(struct policydb *p,
606 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500607 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700608{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500609 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700610 return;
611
Paul Moore16efd452008-01-29 08:37:59 -0500612 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
Paul Moore02752762006-11-29 13:18:18 -0500613 context->range.level[1].sens = context->range.level[0].sens;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700614}
615
616/**
Paul Moore02752762006-11-29 13:18:18 -0500617 * mls_export_netlbl_cat - Export the MLS categories to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700618 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500619 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700620 *
621 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500622 * Given the security context copy the low MLS categories into the NetLabel
623 * MLS category field. Returns zero on success, negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700624 *
625 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500626int mls_export_netlbl_cat(struct policydb *p,
627 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500628 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700629{
Paul Moore02752762006-11-29 13:18:18 -0500630 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700631
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500632 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700633 return 0;
634
Paul Moore02752762006-11-29 13:18:18 -0500635 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500636 &secattr->attr.mls.cat);
637 if (rc == 0 && secattr->attr.mls.cat != NULL)
Paul Moore02752762006-11-29 13:18:18 -0500638 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700639
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700640 return rc;
641}
642
643/**
Paul Moore02752762006-11-29 13:18:18 -0500644 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700645 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500646 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700647 *
648 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500649 * Copy the NetLabel security attributes into the SELinux context; since the
650 * NetLabel security attribute only contains a single MLS category use it for
651 * both the low and high categories of the context. Returns zero on success,
652 * negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700653 *
654 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500655int mls_import_netlbl_cat(struct policydb *p,
656 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500657 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700658{
Paul Moore02752762006-11-29 13:18:18 -0500659 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700660
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500661 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700662 return 0;
663
Paul Moore02752762006-11-29 13:18:18 -0500664 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500665 secattr->attr.mls.cat);
Paul Mooreda8026f2015-02-17 15:30:23 -0500666 if (rc)
Paul Moore02752762006-11-29 13:18:18 -0500667 goto import_netlbl_cat_failure;
Paul Mooreda8026f2015-02-17 15:30:23 -0500668 memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
669 sizeof(context->range.level[0].cat));
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700670
671 return 0;
672
Paul Moore02752762006-11-29 13:18:18 -0500673import_netlbl_cat_failure:
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700674 ebitmap_destroy(&context->range.level[0].cat);
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700675 return rc;
676}
Paul Moore02752762006-11-29 13:18:18 -0500677#endif /* CONFIG_NETLABEL */