blob: e1088842232c6aefd334c2bf96c51549d8a55363 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Implementation of the multi-level security (MLS) policy.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6/*
7 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
8 *
9 * Support for enhanced MLS infrastructure.
10 *
Darrel Goeddel376bd9c2006-02-24 15:44:05 -060011 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 */
Venkat Yekkirala7420ed22006-08-04 23:17:57 -070013/*
Paul Moore82c21bf2011-08-01 11:10:33 +000014 * Updated: Hewlett-Packard <paul@paul-moore.com>
Venkat Yekkirala7420ed22006-08-04 23:17:57 -070015 *
Paul Moore02752762006-11-29 13:18:18 -050016 * Added support to import/export the MLS label from NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -070017 *
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
21#include <linux/kernel.h>
22#include <linux/slab.h>
23#include <linux/string.h>
24#include <linux/errno.h>
Paul Moore02752762006-11-29 13:18:18 -050025#include <net/netlabel.h>
James Morrisf5c1d5b2005-07-28 01:07:37 -070026#include "sidtab.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include "mls.h"
28#include "policydb.h"
29#include "services.h"
30
31/*
32 * Return the length in bytes for the MLS fields of the
33 * security context string representation of `context'.
34 */
Eric Paris1a5e6f82008-04-18 17:38:32 -040035int mls_compute_context_len(struct context *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -070036{
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090037 int i, l, len, head, prev;
38 char *nm;
39 struct ebitmap *e;
Stephen Smalley782ebb92005-09-03 15:55:16 -070040 struct ebitmap_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Guido Trentalancia0719aaf2010-02-03 16:40:20 +010042 if (!policydb.mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 return 0;
44
45 len = 1; /* for the beginning ":" */
46 for (l = 0; l < 2; l++) {
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090047 int index_sens = context->range.level[l].sens;
Eric Parisac76c052010-11-29 15:47:09 -050048 len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090050 /* categories */
51 head = -2;
52 prev = -2;
53 e = &context->range.level[l].cat;
54 ebitmap_for_each_positive_bit(e, node, i) {
55 if (i - prev > 1) {
56 /* one or more negative bits are skipped */
57 if (head != prev) {
Eric Parisac76c052010-11-29 15:47:09 -050058 nm = sym_name(&policydb, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090059 len += strlen(nm) + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 }
Eric Parisac76c052010-11-29 15:47:09 -050061 nm = sym_name(&policydb, SYM_CATS, i);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090062 len += strlen(nm) + 1;
63 head = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090065 prev = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090067 if (prev != head) {
Eric Parisac76c052010-11-29 15:47:09 -050068 nm = sym_name(&policydb, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090069 len += strlen(nm) + 1;
70 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 if (l == 0) {
72 if (mls_level_eq(&context->range.level[0],
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090073 &context->range.level[1]))
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 break;
75 else
76 len++;
77 }
78 }
79
80 return len;
81}
82
83/*
84 * Write the security context string representation of
85 * the MLS fields of `context' into the string `*scontext'.
86 * Update `*scontext' to point to the end of the MLS fields.
87 */
88void mls_sid_to_context(struct context *context,
Eric Paris1a5e6f82008-04-18 17:38:32 -040089 char **scontext)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090{
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +090091 char *scontextp, *nm;
92 int i, l, head, prev;
93 struct ebitmap *e;
Stephen Smalley782ebb92005-09-03 15:55:16 -070094 struct ebitmap_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Guido Trentalancia0719aaf2010-02-03 16:40:20 +010096 if (!policydb.mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 return;
98
99 scontextp = *scontext;
100
101 *scontextp = ':';
102 scontextp++;
103
104 for (l = 0; l < 2; l++) {
Eric Parisac76c052010-11-29 15:47:09 -0500105 strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
106 context->range.level[l].sens - 1));
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900107 scontextp += strlen(scontextp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 /* categories */
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900110 head = -2;
111 prev = -2;
112 e = &context->range.level[l].cat;
113 ebitmap_for_each_positive_bit(e, node, i) {
114 if (i - prev > 1) {
115 /* one or more negative bits are skipped */
116 if (prev != head) {
117 if (prev - head > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 *scontextp++ = '.';
119 else
120 *scontextp++ = ',';
Eric Parisac76c052010-11-29 15:47:09 -0500121 nm = sym_name(&policydb, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900122 strcpy(scontextp, nm);
123 scontextp += strlen(nm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900125 if (prev < 0)
126 *scontextp++ = ':';
127 else
128 *scontextp++ = ',';
Eric Parisac76c052010-11-29 15:47:09 -0500129 nm = sym_name(&policydb, SYM_CATS, i);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900130 strcpy(scontextp, nm);
131 scontextp += strlen(nm);
132 head = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 }
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900134 prev = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 }
136
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900137 if (prev != head) {
138 if (prev - head > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 *scontextp++ = '.';
140 else
141 *scontextp++ = ',';
Eric Parisac76c052010-11-29 15:47:09 -0500142 nm = sym_name(&policydb, SYM_CATS, prev);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900143 strcpy(scontextp, nm);
144 scontextp += strlen(nm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 }
146
147 if (l == 0) {
148 if (mls_level_eq(&context->range.level[0],
Eric Paris1a5e6f82008-04-18 17:38:32 -0400149 &context->range.level[1]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 break;
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900151 else
152 *scontextp++ = '-';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 }
154 }
155
156 *scontext = scontextp;
157 return;
158}
159
Stephen Smalley45e54212007-11-07 10:08:00 -0500160int mls_level_isvalid(struct policydb *p, struct mls_level *l)
161{
162 struct level_datum *levdatum;
Stephen Smalley45e54212007-11-07 10:08:00 -0500163
164 if (!l->sens || l->sens > p->p_levels.nprim)
165 return 0;
166 levdatum = hashtab_search(p->p_levels.table,
Eric Parisac76c052010-11-29 15:47:09 -0500167 sym_name(p, SYM_LEVELS, l->sens - 1));
Stephen Smalley45e54212007-11-07 10:08:00 -0500168 if (!levdatum)
169 return 0;
170
Waiman Longfee71142013-07-23 17:38:41 -0400171 /*
172 * Return 1 iff all the bits set in l->cat are also be set in
173 * levdatum->level->cat and no bit in l->cat is larger than
174 * p->p_cats.nprim.
175 */
176 return ebitmap_contains(&levdatum->level->cat, &l->cat,
177 p->p_cats.nprim);
Stephen Smalley45e54212007-11-07 10:08:00 -0500178}
179
180int mls_range_isvalid(struct policydb *p, struct mls_range *r)
181{
182 return (mls_level_isvalid(p, &r->level[0]) &&
183 mls_level_isvalid(p, &r->level[1]) &&
184 mls_level_dom(&r->level[1], &r->level[0]));
185}
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187/*
188 * Return 1 if the MLS fields in the security context
189 * structure `c' are valid. Return 0 otherwise.
190 */
191int mls_context_isvalid(struct policydb *p, struct context *c)
192{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 struct user_datum *usrdatum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100195 if (!p->mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 return 1;
197
Stephen Smalley45e54212007-11-07 10:08:00 -0500198 if (!mls_range_isvalid(p, &c->range))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 return 0;
200
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 if (c->role == OBJECT_R_VAL)
202 return 1;
203
204 /*
205 * User must be authorized for the MLS range.
206 */
207 if (!c->user || c->user > p->p_users.nprim)
208 return 0;
209 usrdatum = p->user_val_to_struct[c->user - 1];
210 if (!mls_range_contains(usrdatum->range, c->range))
211 return 0; /* user may not be associated with range */
212
213 return 1;
214}
215
216/*
217 * Set the MLS fields in the security context structure
218 * `context' based on the string representation in
219 * the string `*scontext'. Update `*scontext' to
220 * point to the end of the string representation of
221 * the MLS fields.
222 *
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,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 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{
241
242 char delim;
243 char *scontextp, *p, *rngptr;
244 struct level_datum *levdatum;
245 struct cat_datum *catdatum, *rngdatum;
246 int l, rc = -EINVAL;
247
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100248 if (!pol->mls_enabled) {
Stephen Smalleye517a0c2005-11-08 21:34:32 -0800249 if (def_sid != SECSID_NULL && oldc)
wzt.wzt@gmail.comc1a73682010-04-09 19:30:29 +0800250 *scontext += strlen(*scontext) + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 return 0;
Stephen Smalleye517a0c2005-11-08 21:34:32 -0800252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
James Morrisf5c1d5b2005-07-28 01:07:37 -0700254 /*
255 * No MLS component to the security context, try and map to
256 * default if provided.
257 */
258 if (!oldc) {
259 struct context *defcon;
260
261 if (def_sid == SECSID_NULL)
262 goto out;
263
264 defcon = sidtab_search(s, def_sid);
265 if (!defcon)
266 goto out;
267
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600268 rc = mls_context_cpy(context, defcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 goto out;
James Morrisf5c1d5b2005-07-28 01:07:37 -0700270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272 /* Extract low sensitivity. */
273 scontextp = p = *scontext;
274 while (*p && *p != ':' && *p != '-')
275 p++;
276
277 delim = *p;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300278 if (delim != '\0')
279 *p++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281 for (l = 0; l < 2; l++) {
Stephen Smalley12b29f32008-05-07 13:03:20 -0400282 levdatum = hashtab_search(pol->p_levels.table, scontextp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 if (!levdatum) {
284 rc = -EINVAL;
285 goto out;
286 }
287
288 context->range.level[l].sens = levdatum->level->sens;
289
290 if (delim == ':') {
291 /* Extract category set. */
292 while (1) {
293 scontextp = p;
294 while (*p && *p != ',' && *p != '-')
295 p++;
296 delim = *p;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300297 if (delim != '\0')
298 *p++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 /* Separate into range if exists */
Eric Paris1a5e6f82008-04-18 17:38:32 -0400301 rngptr = strchr(scontextp, '.');
302 if (rngptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 /* Remove '.' */
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300304 *rngptr++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 }
306
Stephen Smalley12b29f32008-05-07 13:03:20 -0400307 catdatum = hashtab_search(pol->p_cats.table,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400308 scontextp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 if (!catdatum) {
310 rc = -EINVAL;
311 goto out;
312 }
313
314 rc = ebitmap_set_bit(&context->range.level[l].cat,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400315 catdatum->value - 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 if (rc)
317 goto out;
318
319 /* If range, set all categories in range */
320 if (rngptr) {
321 int i;
322
Stephen Smalley12b29f32008-05-07 13:03:20 -0400323 rngdatum = hashtab_search(pol->p_cats.table, rngptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 if (!rngdatum) {
325 rc = -EINVAL;
326 goto out;
327 }
328
329 if (catdatum->value >= rngdatum->value) {
330 rc = -EINVAL;
331 goto out;
332 }
333
334 for (i = catdatum->value; i < rngdatum->value; i++) {
335 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
336 if (rc)
337 goto out;
338 }
339 }
340
341 if (delim != ',')
342 break;
343 }
344 }
345 if (delim == '-') {
346 /* Extract high sensitivity. */
347 scontextp = p;
348 while (*p && *p != ':')
349 p++;
350
351 delim = *p;
Vesa-Matti J Karidf4ea862008-07-20 23:57:01 +0300352 if (delim != '\0')
353 *p++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 } else
355 break;
356 }
357
358 if (l == 0) {
359 context->range.level[1].sens = context->range.level[0].sens;
360 rc = ebitmap_cpy(&context->range.level[1].cat,
361 &context->range.level[0].cat);
362 if (rc)
363 goto out;
364 }
365 *scontext = ++p;
366 rc = 0;
367out:
368 return rc;
369}
370
371/*
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600372 * Set the MLS fields in the security context structure
373 * `context' based on the string representation in
374 * the string `str'. This function will allocate temporary memory with the
375 * given constraints of gfp_mask.
376 */
377int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
378{
379 char *tmpstr, *freestr;
380 int rc;
381
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100382 if (!policydb.mls_enabled)
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600383 return -EINVAL;
384
385 /* we need freestr because mls_context_to_sid will change
386 the value of tmpstr */
387 tmpstr = freestr = kstrdup(str, gfp_mask);
388 if (!tmpstr) {
389 rc = -ENOMEM;
390 } else {
Stephen Smalley12b29f32008-05-07 13:03:20 -0400391 rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400392 NULL, SECSID_NULL);
Darrel Goeddel376bd9c2006-02-24 15:44:05 -0600393 kfree(freestr);
394 }
395
396 return rc;
397}
398
399/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 * Copies the MLS range `range' into `context'.
401 */
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100402int mls_range_set(struct context *context,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400403 struct mls_range *range)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404{
405 int l, rc = 0;
406
407 /* Copy the MLS range into the context */
408 for (l = 0; l < 2; l++) {
409 context->range.level[l].sens = range->level[l].sens;
410 rc = ebitmap_cpy(&context->range.level[l].cat,
411 &range->level[l].cat);
412 if (rc)
413 break;
414 }
415
416 return rc;
417}
418
419int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
Eric Paris1a5e6f82008-04-18 17:38:32 -0400420 struct context *usercon)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421{
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100422 if (policydb.mls_enabled) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
424 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
425 struct mls_level *user_low = &(user->range.level[0]);
426 struct mls_level *user_clr = &(user->range.level[1]);
427 struct mls_level *user_def = &(user->dfltlevel);
428 struct mls_level *usercon_sen = &(usercon->range.level[0]);
429 struct mls_level *usercon_clr = &(usercon->range.level[1]);
430
431 /* Honor the user's default level if we can */
Eric Parisf5269712008-05-14 11:27:45 -0400432 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 *usercon_sen = *user_def;
Eric Parisf5269712008-05-14 11:27:45 -0400434 else if (mls_level_between(fromcon_sen, user_def, user_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 *usercon_sen = *fromcon_sen;
Eric Parisf5269712008-05-14 11:27:45 -0400436 else if (mls_level_between(fromcon_clr, user_low, user_def))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 *usercon_sen = *user_low;
Eric Parisf5269712008-05-14 11:27:45 -0400438 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 return -EINVAL;
440
441 /* Lower the clearance of available contexts
442 if the clearance of "fromcon" is lower than
443 that of the user's default clearance (but
444 only if the "fromcon" clearance dominates
445 the user's computed sensitivity level) */
Eric Paris1a5e6f82008-04-18 17:38:32 -0400446 if (mls_level_dom(user_clr, fromcon_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 *usercon_clr = *fromcon_clr;
Eric Paris1a5e6f82008-04-18 17:38:32 -0400448 else if (mls_level_dom(fromcon_clr, user_clr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 *usercon_clr = *user_clr;
Eric Paris1a5e6f82008-04-18 17:38:32 -0400450 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 return -EINVAL;
452 }
453
454 return 0;
455}
456
457/*
458 * Convert the MLS fields in the security context
459 * structure `c' from the values specified in the
460 * policy `oldp' to the values specified in the policy `newp'.
461 */
462int mls_convert_context(struct policydb *oldp,
463 struct policydb *newp,
464 struct context *c)
465{
466 struct level_datum *levdatum;
467 struct cat_datum *catdatum;
468 struct ebitmap bitmap;
Stephen Smalley782ebb92005-09-03 15:55:16 -0700469 struct ebitmap_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 int l, i;
471
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100472 if (!policydb.mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 return 0;
474
475 for (l = 0; l < 2; l++) {
476 levdatum = hashtab_search(newp->p_levels.table,
Eric Parisac76c052010-11-29 15:47:09 -0500477 sym_name(oldp, SYM_LEVELS,
478 c->range.level[l].sens - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
480 if (!levdatum)
481 return -EINVAL;
482 c->range.level[l].sens = levdatum->level->sens;
483
484 ebitmap_init(&bitmap);
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900485 ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
486 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900488 catdatum = hashtab_search(newp->p_cats.table,
Eric Parisac76c052010-11-29 15:47:09 -0500489 sym_name(oldp, SYM_CATS, i));
KaiGai Kohei9fe79ad2007-09-29 02:20:55 +0900490 if (!catdatum)
491 return -EINVAL;
492 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
493 if (rc)
494 return rc;
Dave Jones9a591f32014-05-15 15:02:53 -0400495
496 cond_resched();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 }
498 ebitmap_destroy(&c->range.level[l].cat);
499 c->range.level[l].cat = bitmap;
500 }
501
502 return 0;
503}
504
505int mls_compute_sid(struct context *scontext,
506 struct context *tcontext,
507 u16 tclass,
508 u32 specified,
Harry Ciao6f5317e2011-03-02 13:32:33 +0800509 struct context *newcontext,
510 bool sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511{
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500512 struct range_trans rtr;
513 struct mls_range *r;
Eric Parisaa893262012-03-20 14:35:12 -0400514 struct class_datum *cladatum;
515 int default_range = 0;
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700516
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100517 if (!policydb.mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 return 0;
519
520 switch (specified) {
521 case AVTAB_TRANSITION:
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700522 /* Look for a range transition rule. */
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500523 rtr.source_type = scontext->type;
524 rtr.target_type = tcontext->type;
525 rtr.target_class = tclass;
526 r = hashtab_search(policydb.range_tr, &rtr);
527 if (r)
528 return mls_range_set(newcontext, r);
Eric Parisaa893262012-03-20 14:35:12 -0400529
530 if (tclass && tclass <= policydb.p_classes.nprim) {
531 cladatum = policydb.class_val_to_struct[tclass - 1];
532 if (cladatum)
533 default_range = cladatum->default_range;
534 }
535
536 switch (default_range) {
537 case DEFAULT_SOURCE_LOW:
538 return mls_context_cpy_low(newcontext, scontext);
539 case DEFAULT_SOURCE_HIGH:
540 return mls_context_cpy_high(newcontext, scontext);
541 case DEFAULT_SOURCE_LOW_HIGH:
542 return mls_context_cpy(newcontext, scontext);
543 case DEFAULT_TARGET_LOW:
544 return mls_context_cpy_low(newcontext, tcontext);
545 case DEFAULT_TARGET_HIGH:
546 return mls_context_cpy_high(newcontext, tcontext);
547 case DEFAULT_TARGET_LOW_HIGH:
548 return mls_context_cpy(newcontext, tcontext);
549 }
550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 /* Fallthrough */
552 case AVTAB_CHANGE:
Harry Ciao6f5317e2011-03-02 13:32:33 +0800553 if ((tclass == policydb.process_class) || (sock == true))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 /* Use the process MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600555 return mls_context_cpy(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 else
557 /* Use the process effective MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600558 return mls_context_cpy_low(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 case AVTAB_MEMBER:
Eamon Walsh2e08c0c2008-01-24 15:30:52 -0500560 /* Use the process effective MLS attributes. */
561 return mls_context_cpy_low(newcontext, scontext);
Amerigo Wang08e3daf2009-12-03 03:48:28 -0500562
563 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 }
565 return -EINVAL;
566}
567
Paul Moore02752762006-11-29 13:18:18 -0500568#ifdef CONFIG_NETLABEL
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700569/**
Paul Moore02752762006-11-29 13:18:18 -0500570 * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700571 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500572 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700573 *
574 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500575 * Given the security context copy the low MLS sensitivity level into the
576 * NetLabel MLS sensitivity level field.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700577 *
578 */
Paul Moore02752762006-11-29 13:18:18 -0500579void mls_export_netlbl_lvl(struct context *context,
580 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700581{
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100582 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700583 return;
584
Paul Moore16efd452008-01-29 08:37:59 -0500585 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
Paul Moore02752762006-11-29 13:18:18 -0500586 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700587}
588
589/**
Paul Moore02752762006-11-29 13:18:18 -0500590 * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700591 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500592 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700593 *
594 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500595 * Given the security context and the NetLabel security attributes, copy the
596 * NetLabel MLS sensitivity level into the context.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700597 *
598 */
Paul Moore02752762006-11-29 13:18:18 -0500599void mls_import_netlbl_lvl(struct context *context,
600 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700601{
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100602 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700603 return;
604
Paul Moore16efd452008-01-29 08:37:59 -0500605 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
Paul Moore02752762006-11-29 13:18:18 -0500606 context->range.level[1].sens = context->range.level[0].sens;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700607}
608
609/**
Paul Moore02752762006-11-29 13:18:18 -0500610 * mls_export_netlbl_cat - Export the MLS categories to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700611 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500612 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700613 *
614 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500615 * Given the security context copy the low MLS categories into the NetLabel
616 * MLS category field. Returns zero on success, negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700617 *
618 */
Paul Moore02752762006-11-29 13:18:18 -0500619int mls_export_netlbl_cat(struct context *context,
620 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700621{
Paul Moore02752762006-11-29 13:18:18 -0500622 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700623
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100624 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700625 return 0;
626
Paul Moore02752762006-11-29 13:18:18 -0500627 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500628 &secattr->attr.mls.cat);
629 if (rc == 0 && secattr->attr.mls.cat != NULL)
Paul Moore02752762006-11-29 13:18:18 -0500630 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700631
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700632 return rc;
633}
634
635/**
Paul Moore02752762006-11-29 13:18:18 -0500636 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700637 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500638 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700639 *
640 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500641 * Copy the NetLabel security attributes into the SELinux context; since the
642 * NetLabel security attribute only contains a single MLS category use it for
643 * both the low and high categories of the context. Returns zero on success,
644 * negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700645 *
646 */
Paul Moore02752762006-11-29 13:18:18 -0500647int mls_import_netlbl_cat(struct context *context,
648 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700649{
Paul Moore02752762006-11-29 13:18:18 -0500650 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700651
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100652 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700653 return 0;
654
Paul Moore02752762006-11-29 13:18:18 -0500655 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500656 secattr->attr.mls.cat);
Paul Mooreda8026f2015-02-17 15:30:23 -0500657 if (rc)
Paul Moore02752762006-11-29 13:18:18 -0500658 goto import_netlbl_cat_failure;
Paul Mooreda8026f2015-02-17 15:30:23 -0500659 memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
660 sizeof(context->range.level[0].cat));
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700661
662 return 0;
663
Paul Moore02752762006-11-29 13:18:18 -0500664import_netlbl_cat_failure:
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700665 ebitmap_destroy(&context->range.level[0].cat);
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700666 return rc;
667}
Paul Moore02752762006-11-29 13:18:18 -0500668#endif /* CONFIG_NETLABEL */