blob: ec5e3d1da9ace26653f9dea94ffa15654800d300 [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
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. */
296 levdatum = hashtab_search(pol->p_levels.table, sensitivity);
297 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
Jann Horn95ffe192018-08-06 23:19:32 +0200315 catdatum = hashtab_search(pol->p_cats.table, cur_cat);
316 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
328 rngdatum = hashtab_search(pol->p_cats.table, rngptr);
329 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++) {
461 levdatum = hashtab_search(newp->p_levels.table,
Eric Parisac76c05b2010-11-29 15:47:09 -0500462 sym_name(oldp, SYM_LEVELS,
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100463 oldc->range.level[l].sens - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
465 if (!levdatum)
466 return -EINVAL;
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100467 newc->range.level[l].sens = levdatum->level->sens;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100469 ebitmap_for_each_positive_bit(&oldc->range.level[l].cat,
470 node, i) {
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900471 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900473 catdatum = hashtab_search(newp->p_cats.table,
Eric Parisac76c05b2010-11-29 15:47:09 -0500474 sym_name(oldp, SYM_CATS, i));
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900475 if (!catdatum)
476 return -EINVAL;
Ondrej Mosnacekee1a84f2018-11-30 16:24:08 +0100477 rc = ebitmap_set_bit(&newc->range.level[l].cat,
478 catdatum->value - 1, 1);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900479 if (rc)
480 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 }
483
484 return 0;
485}
486
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500487int mls_compute_sid(struct policydb *p,
488 struct context *scontext,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 struct context *tcontext,
490 u16 tclass,
491 u32 specified,
Harry Ciao6f5317e2011-03-02 13:32:33 +0800492 struct context *newcontext,
493 bool sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494{
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500495 struct range_trans rtr;
496 struct mls_range *r;
Eric Parisaa893262012-03-20 14:35:12 -0400497 struct class_datum *cladatum;
498 int default_range = 0;
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700499
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500500 if (!p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 return 0;
502
503 switch (specified) {
504 case AVTAB_TRANSITION:
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700505 /* Look for a range transition rule. */
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500506 rtr.source_type = scontext->type;
507 rtr.target_type = tcontext->type;
508 rtr.target_class = tclass;
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500509 r = hashtab_search(p->range_tr, &rtr);
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500510 if (r)
511 return mls_range_set(newcontext, r);
Eric Parisaa893262012-03-20 14:35:12 -0400512
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500513 if (tclass && tclass <= p->p_classes.nprim) {
514 cladatum = p->class_val_to_struct[tclass - 1];
Eric Parisaa893262012-03-20 14:35:12 -0400515 if (cladatum)
516 default_range = cladatum->default_range;
517 }
518
519 switch (default_range) {
520 case DEFAULT_SOURCE_LOW:
521 return mls_context_cpy_low(newcontext, scontext);
522 case DEFAULT_SOURCE_HIGH:
523 return mls_context_cpy_high(newcontext, scontext);
524 case DEFAULT_SOURCE_LOW_HIGH:
525 return mls_context_cpy(newcontext, scontext);
526 case DEFAULT_TARGET_LOW:
527 return mls_context_cpy_low(newcontext, tcontext);
528 case DEFAULT_TARGET_HIGH:
529 return mls_context_cpy_high(newcontext, tcontext);
530 case DEFAULT_TARGET_LOW_HIGH:
531 return mls_context_cpy(newcontext, tcontext);
Joshua Brindle42345b62019-09-04 14:03:23 -0700532 case DEFAULT_GLBLUB:
533 return mls_context_glblub(newcontext,
534 scontext, tcontext);
Eric Parisaa893262012-03-20 14:35:12 -0400535 }
536
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 /* Fallthrough */
538 case AVTAB_CHANGE:
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500539 if ((tclass == p->process_class) || (sock == true))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 /* Use the process MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600541 return mls_context_cpy(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 else
543 /* Use the process effective MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600544 return mls_context_cpy_low(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 case AVTAB_MEMBER:
Eamon Walsh2e08c0c2008-01-24 15:30:52 -0500546 /* Use the process effective MLS attributes. */
547 return mls_context_cpy_low(newcontext, scontext);
Amerigo Wang08e3daf2009-12-03 03:48:28 -0500548
549 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 }
551 return -EINVAL;
552}
553
Paul Moore02752762006-11-29 13:18:18 -0500554#ifdef CONFIG_NETLABEL
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700555/**
Paul Moore02752762006-11-29 13:18:18 -0500556 * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700557 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500558 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700559 *
560 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500561 * Given the security context copy the low MLS sensitivity level into the
562 * NetLabel MLS sensitivity level field.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700563 *
564 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500565void mls_export_netlbl_lvl(struct policydb *p,
566 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500567 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700568{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500569 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700570 return;
571
Paul Moore16efd452008-01-29 08:37:59 -0500572 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
Paul Moore02752762006-11-29 13:18:18 -0500573 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700574}
575
576/**
Paul Moore02752762006-11-29 13:18:18 -0500577 * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700578 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500579 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700580 *
581 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500582 * Given the security context and the NetLabel security attributes, copy the
583 * NetLabel MLS sensitivity level into the context.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700584 *
585 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500586void mls_import_netlbl_lvl(struct policydb *p,
587 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500588 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700589{
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500590 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700591 return;
592
Paul Moore16efd452008-01-29 08:37:59 -0500593 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
Paul Moore02752762006-11-29 13:18:18 -0500594 context->range.level[1].sens = context->range.level[0].sens;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700595}
596
597/**
Paul Moore02752762006-11-29 13:18:18 -0500598 * mls_export_netlbl_cat - Export the MLS categories to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700599 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500600 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700601 *
602 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500603 * Given the security context copy the low MLS categories into the NetLabel
604 * MLS category field. Returns zero on success, negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700605 *
606 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500607int mls_export_netlbl_cat(struct policydb *p,
608 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500609 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700610{
Paul Moore02752762006-11-29 13:18:18 -0500611 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700612
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500613 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700614 return 0;
615
Paul Moore02752762006-11-29 13:18:18 -0500616 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500617 &secattr->attr.mls.cat);
618 if (rc == 0 && secattr->attr.mls.cat != NULL)
Paul Moore02752762006-11-29 13:18:18 -0500619 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700620
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700621 return rc;
622}
623
624/**
Paul Moore02752762006-11-29 13:18:18 -0500625 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700626 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500627 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700628 *
629 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500630 * 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.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700634 *
635 */
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500636int mls_import_netlbl_cat(struct policydb *p,
637 struct context *context,
Paul Moore02752762006-11-29 13:18:18 -0500638 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700639{
Paul Moore02752762006-11-29 13:18:18 -0500640 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700641
Stephen Smalleyaa8e7122018-03-01 18:48:02 -0500642 if (!p->mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700643 return 0;
644
Paul Moore02752762006-11-29 13:18:18 -0500645 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500646 secattr->attr.mls.cat);
Paul Mooreda8026f2015-02-17 15:30:23 -0500647 if (rc)
Paul Moore02752762006-11-29 13:18:18 -0500648 goto import_netlbl_cat_failure;
Paul Mooreda8026f2015-02-17 15:30:23 -0500649 memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
650 sizeof(context->range.level[0].cat));
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700651
652 return 0;
653
Paul Moore02752762006-11-29 13:18:18 -0500654import_netlbl_cat_failure:
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700655 ebitmap_destroy(&context->range.level[0].cat);
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700656 return rc;
657}
Paul Moore02752762006-11-29 13:18:18 -0500658#endif /* CONFIG_NETLABEL */