blob: c85bc1ec040c0c58f93772004361cbcd04861575 [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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 }
496 ebitmap_destroy(&c->range.level[l].cat);
497 c->range.level[l].cat = bitmap;
498 }
499
500 return 0;
501}
502
503int mls_compute_sid(struct context *scontext,
504 struct context *tcontext,
505 u16 tclass,
506 u32 specified,
Harry Ciao6f5317e2011-03-02 13:32:33 +0800507 struct context *newcontext,
508 bool sock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509{
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500510 struct range_trans rtr;
511 struct mls_range *r;
Eric Parisaa893262012-03-20 14:35:12 -0400512 struct class_datum *cladatum;
513 int default_range = 0;
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700514
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100515 if (!policydb.mls_enabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 return 0;
517
518 switch (specified) {
519 case AVTAB_TRANSITION:
Darrel Goeddelf3f87712006-09-25 23:31:59 -0700520 /* Look for a range transition rule. */
Stephen Smalley2f3e82d2010-01-07 15:55:16 -0500521 rtr.source_type = scontext->type;
522 rtr.target_type = tcontext->type;
523 rtr.target_class = tclass;
524 r = hashtab_search(policydb.range_tr, &rtr);
525 if (r)
526 return mls_range_set(newcontext, r);
Eric Parisaa893262012-03-20 14:35:12 -0400527
528 if (tclass && tclass <= policydb.p_classes.nprim) {
529 cladatum = policydb.class_val_to_struct[tclass - 1];
530 if (cladatum)
531 default_range = cladatum->default_range;
532 }
533
534 switch (default_range) {
535 case DEFAULT_SOURCE_LOW:
536 return mls_context_cpy_low(newcontext, scontext);
537 case DEFAULT_SOURCE_HIGH:
538 return mls_context_cpy_high(newcontext, scontext);
539 case DEFAULT_SOURCE_LOW_HIGH:
540 return mls_context_cpy(newcontext, scontext);
541 case DEFAULT_TARGET_LOW:
542 return mls_context_cpy_low(newcontext, tcontext);
543 case DEFAULT_TARGET_HIGH:
544 return mls_context_cpy_high(newcontext, tcontext);
545 case DEFAULT_TARGET_LOW_HIGH:
546 return mls_context_cpy(newcontext, tcontext);
547 }
548
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 /* Fallthrough */
550 case AVTAB_CHANGE:
Harry Ciao6f5317e2011-03-02 13:32:33 +0800551 if ((tclass == policydb.process_class) || (sock == true))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 /* Use the process MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600553 return mls_context_cpy(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 else
555 /* Use the process effective MLS attributes. */
Venkat Yekkirala0efc61e2006-12-12 13:02:41 -0600556 return mls_context_cpy_low(newcontext, scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 case AVTAB_MEMBER:
Eamon Walsh2e08c0c2008-01-24 15:30:52 -0500558 /* Use the process effective MLS attributes. */
559 return mls_context_cpy_low(newcontext, scontext);
Amerigo Wang08e3daf2009-12-03 03:48:28 -0500560
561 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 }
563 return -EINVAL;
564}
565
Paul Moore02752762006-11-29 13:18:18 -0500566#ifdef CONFIG_NETLABEL
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700567/**
Paul Moore02752762006-11-29 13:18:18 -0500568 * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700569 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500570 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700571 *
572 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500573 * Given the security context copy the low MLS sensitivity level into the
574 * NetLabel MLS sensitivity level field.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700575 *
576 */
Paul Moore02752762006-11-29 13:18:18 -0500577void mls_export_netlbl_lvl(struct context *context,
578 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700579{
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100580 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700581 return;
582
Paul Moore16efd452008-01-29 08:37:59 -0500583 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
Paul Moore02752762006-11-29 13:18:18 -0500584 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700585}
586
587/**
Paul Moore02752762006-11-29 13:18:18 -0500588 * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700589 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500590 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700591 *
592 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500593 * Given the security context and the NetLabel security attributes, copy the
594 * NetLabel MLS sensitivity level into the context.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700595 *
596 */
Paul Moore02752762006-11-29 13:18:18 -0500597void mls_import_netlbl_lvl(struct context *context,
598 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700599{
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100600 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700601 return;
602
Paul Moore16efd452008-01-29 08:37:59 -0500603 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
Paul Moore02752762006-11-29 13:18:18 -0500604 context->range.level[1].sens = context->range.level[0].sens;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700605}
606
607/**
Paul Moore02752762006-11-29 13:18:18 -0500608 * mls_export_netlbl_cat - Export the MLS categories to NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700609 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500610 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700611 *
612 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500613 * Given the security context copy the low MLS categories into the NetLabel
614 * MLS category field. Returns zero on success, negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700615 *
616 */
Paul Moore02752762006-11-29 13:18:18 -0500617int mls_export_netlbl_cat(struct context *context,
618 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700619{
Paul Moore02752762006-11-29 13:18:18 -0500620 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700621
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100622 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700623 return 0;
624
Paul Moore02752762006-11-29 13:18:18 -0500625 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500626 &secattr->attr.mls.cat);
627 if (rc == 0 && secattr->attr.mls.cat != NULL)
Paul Moore02752762006-11-29 13:18:18 -0500628 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700629
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700630 return rc;
631}
632
633/**
Paul Moore02752762006-11-29 13:18:18 -0500634 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700635 * @context: the security context
Paul Moore02752762006-11-29 13:18:18 -0500636 * @secattr: the NetLabel security attributes
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700637 *
638 * Description:
Paul Moore02752762006-11-29 13:18:18 -0500639 * Copy the NetLabel security attributes into the SELinux context; since the
640 * NetLabel security attribute only contains a single MLS category use it for
641 * both the low and high categories of the context. Returns zero on success,
642 * negative values on failure.
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700643 *
644 */
Paul Moore02752762006-11-29 13:18:18 -0500645int mls_import_netlbl_cat(struct context *context,
646 struct netlbl_lsm_secattr *secattr)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700647{
Paul Moore02752762006-11-29 13:18:18 -0500648 int rc;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700649
Guido Trentalancia0719aaf2010-02-03 16:40:20 +0100650 if (!policydb.mls_enabled)
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700651 return 0;
652
Paul Moore02752762006-11-29 13:18:18 -0500653 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
Paul Moore16efd452008-01-29 08:37:59 -0500654 secattr->attr.mls.cat);
Paul Moore02752762006-11-29 13:18:18 -0500655 if (rc != 0)
656 goto import_netlbl_cat_failure;
657
658 rc = ebitmap_cpy(&context->range.level[1].cat,
659 &context->range.level[0].cat);
660 if (rc != 0)
661 goto import_netlbl_cat_failure;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700662
663 return 0;
664
Paul Moore02752762006-11-29 13:18:18 -0500665import_netlbl_cat_failure:
Venkat Yekkirala7420ed22006-08-04 23:17:57 -0700666 ebitmap_destroy(&context->range.level[0].cat);
667 ebitmap_destroy(&context->range.level[1].cat);
668 return rc;
669}
Paul Moore02752762006-11-29 13:18:18 -0500670#endif /* CONFIG_NETLABEL */