Deleted Added
full compact
mac_bsdextended.c (156300) mac_bsdextended.c (157986)
1/*-
2 * Copyright (c) 2005 Tom Rhodes
3 * Copyright (c) 1999-2002 Robert N. M. Watson
4 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 * It was later enhanced by Tom Rhodes for the TrustedBSD Project.

--- 19 unchanged lines hidden (view full) ---

28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
1/*-
2 * Copyright (c) 2005 Tom Rhodes
3 * Copyright (c) 1999-2002 Robert N. M. Watson
4 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 * It was later enhanced by Tom Rhodes for the TrustedBSD Project.

--- 19 unchanged lines hidden (view full) ---

28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 156300 2006-03-04 20:47:19Z dwmalone $
36 * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 157986 2006-04-23 17:06:18Z dwmalone $
37 */
38
39/*
40 * Developed by the TrustedBSD Project.
41 * "BSD Extended" MAC policy, allowing the administrator to impose
42 * mandatory rules regarding users and some system objects.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/acl.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
37 */
38
39/*
40 * Developed by the TrustedBSD Project.
41 * "BSD Extended" MAC policy, allowing the administrator to impose
42 * mandatory rules regarding users and some system objects.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/acl.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <sys/jail.h>
50#include <sys/lock.h>
51#include <sys/mac.h>
52#include <sys/malloc.h>
53#include <sys/mount.h>
54#include <sys/mutex.h>
55#include <sys/proc.h>
56#include <sys/systm.h>
57#include <sys/sysproto.h>
58#include <sys/sysent.h>
59#include <sys/vnode.h>
60#include <sys/file.h>
61#include <sys/socket.h>
62#include <sys/socketvar.h>
63#include <sys/sysctl.h>
64#include <sys/syslog.h>
51#include <sys/lock.h>
52#include <sys/mac.h>
53#include <sys/malloc.h>
54#include <sys/mount.h>
55#include <sys/mutex.h>
56#include <sys/proc.h>
57#include <sys/systm.h>
58#include <sys/sysproto.h>
59#include <sys/sysent.h>
60#include <sys/vnode.h>
61#include <sys/file.h>
62#include <sys/socket.h>
63#include <sys/socketvar.h>
64#include <sys/sysctl.h>
65#include <sys/syslog.h>
66#include <sys/ucred.h>
65
66#include <net/bpfdesc.h>
67#include <net/if.h>
68#include <net/if_types.h>
69#include <net/if_var.h>
70
71#include <vm/vm.h>
72

--- 14 unchanged lines hidden (view full) ---

87TUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
88
89MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
90
91#define MAC_BSDEXTENDED_MAXRULES 250
92static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
93static int rule_count = 0;
94static int rule_slots = 0;
67
68#include <net/bpfdesc.h>
69#include <net/if.h>
70#include <net/if_types.h>
71#include <net/if_var.h>
72
73#include <vm/vm.h>
74

--- 14 unchanged lines hidden (view full) ---

89TUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
90
91MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
92
93#define MAC_BSDEXTENDED_MAXRULES 250
94static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
95static int rule_count = 0;
96static int rule_slots = 0;
97static int rule_version = MB_VERSION;
95
96SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
97 &rule_count, 0, "Number of defined rules\n");
98SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
99 &rule_slots, 0, "Number of used rule slots\n");
98
99SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
100 &rule_count, 0, "Number of defined rules\n");
101SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
102 &rule_slots, 0, "Number of used rule slots\n");
103SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD,
104 &rule_version, 0, "Version number for API\n");
100
101/*
102 * This is just used for logging purposes, eventually we would like
103 * to log much more then failed requests.
104 */
105static int mac_bsdextended_logging;
106SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
107 &mac_bsdextended_logging, 0, "Log failed authorization requests");

--- 8 unchanged lines hidden (view full) ---

116SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
117 CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
118 "Disable/enable match first rule functionality");
119
120static int
121mac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
122{
123
105
106/*
107 * This is just used for logging purposes, eventually we would like
108 * to log much more then failed requests.
109 */
110static int mac_bsdextended_logging;
111SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
112 &mac_bsdextended_logging, 0, "Log failed authorization requests");

--- 8 unchanged lines hidden (view full) ---

121SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
122 CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
123 "Disable/enable match first rule functionality");
124
125static int
126mac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
127{
128
124 if ((rule->mbr_subject.mbi_flags | MBI_BITS) != MBI_BITS)
129 if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
125 return (EINVAL);
126
130 return (EINVAL);
131
127 if ((rule->mbr_object.mbi_flags | MBI_BITS) != MBI_BITS)
132 if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
128 return (EINVAL);
129
133 return (EINVAL);
134
135 if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
136 return (EINVAL);
137
138 if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
139 return (EINVAL);
140
141 if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) &&
142 (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE)
143 return (EINVAL);
144
130 if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
131 return (EINVAL);
132
133 return (0);
134}
135
136static int
137sysctl_rule(SYSCTL_HANDLER_ARGS)

--- 97 unchanged lines hidden (view full) ---

235 /* Destroy ruleset lock. */
236 mtx_destroy(&mac_bsdextended_mtx);
237
238 /* Tear down sysctls. */
239}
240
241static int
242mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
145 if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
146 return (EINVAL);
147
148 return (0);
149}
150
151static int
152sysctl_rule(SYSCTL_HANDLER_ARGS)

--- 97 unchanged lines hidden (view full) ---

250 /* Destroy ruleset lock. */
251 mtx_destroy(&mac_bsdextended_mtx);
252
253 /* Tear down sysctls. */
254}
255
256static int
257mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
243 struct ucred *cred, uid_t object_uid, gid_t object_gid, int acc_mode)
258 struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode)
244{
245 int match;
259{
260 int match;
261 int i;
246
247 /*
248 * Is there a subject match?
249 */
250 mtx_assert(&mac_bsdextended_mtx, MA_OWNED);
262
263 /*
264 * Is there a subject match?
265 */
266 mtx_assert(&mac_bsdextended_mtx, MA_OWNED);
251 if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) {
252 match = (rule->mbr_subject.mbi_uid == cred->cr_uid ||
253 rule->mbr_subject.mbi_uid == cred->cr_ruid ||
254 rule->mbr_subject.mbi_uid == cred->cr_svuid);
267 if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) {
268 match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max &&
269 cred->cr_uid >= rule->mbr_subject.mbs_uid_min) ||
270 (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max &&
271 cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) ||
272 (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max &&
273 cred->cr_svuid >= rule->mbr_subject.mbs_uid_min));
255
274
256 if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
275 if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED)
257 match = !match;
258
259 if (!match)
260 return (0);
261 }
262
276 match = !match;
277
278 if (!match)
279 return (0);
280 }
281
263 if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) {
264 match = (groupmember(rule->mbr_subject.mbi_gid, cred) ||
265 rule->mbr_subject.mbi_gid == cred->cr_rgid ||
266 rule->mbr_subject.mbi_gid == cred->cr_svgid);
282 if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) {
283 match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max &&
284 cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) ||
285 (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max &&
286 cred->cr_svgid >= rule->mbr_subject.mbs_gid_min));
267
287
268 if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
288 if (!match) {
289 for (i = 0; i < cred->cr_ngroups; i++)
290 if (cred->cr_groups[i]
291 <= rule->mbr_subject.mbs_gid_max &&
292 cred->cr_groups[i]
293 >= rule->mbr_subject.mbs_gid_min) {
294 match = 1;
295 break;
296 }
297 }
298
299 if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED)
269 match = !match;
270
271 if (!match)
272 return (0);
273 }
274
300 match = !match;
301
302 if (!match)
303 return (0);
304 }
305
306 if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
307 match = (cred->cr_prison != NULL &&
308 cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison);
309
310 if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)
311 match = !match;
312
313 if (!match)
314 return (0);
315 }
316
275 /*
276 * Is there an object match?
277 */
317 /*
318 * Is there an object match?
319 */
278 if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) {
279 match = (rule->mbr_object.mbi_uid == object_uid);
320 if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
321 match = (vap->va_uid <= rule->mbr_object.mbo_uid_max &&
322 vap->va_uid >= rule->mbr_object.mbo_uid_min);
280
323
281 if (rule->mbr_object.mbi_flags & MBI_NEGATED)
324 if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)
282 match = !match;
283
284 if (!match)
285 return (0);
286 }
287
325 match = !match;
326
327 if (!match)
328 return (0);
329 }
330
288 if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) {
289 match = (rule->mbr_object.mbi_gid == object_gid);
331 if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
332 match = (vap->va_gid <= rule->mbr_object.mbo_gid_max &&
333 vap->va_gid >= rule->mbr_object.mbo_gid_min);
290
334
291 if (rule->mbr_object.mbi_flags & MBI_NEGATED)
335 if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)
292 match = !match;
293
294 if (!match)
295 return (0);
296 }
297
336 match = !match;
337
338 if (!match)
339 return (0);
340 }
341
342 if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
343 match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid),
344 &(rule->mbr_object.mbo_fsid),
345 sizeof(rule->mbr_object.mbo_fsid)) == 0);
346
347 if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)
348 match = !match;
349
350 if (!match)
351 return 0;
352 }
353
354 if (rule->mbr_object.mbo_flags & MBO_SUID) {
355 match = (vap->va_mode & VSUID);
356
357 if (rule->mbr_object.mbo_neg & MBO_SUID)
358 match = !match;
359
360 if (!match)
361 return 0;
362 }
363
364 if (rule->mbr_object.mbo_flags & MBO_SGID) {
365 match = (vap->va_mode & VSGID);
366
367 if (rule->mbr_object.mbo_neg & MBO_SGID)
368 match = !match;
369
370 if (!match)
371 return 0;
372 }
373
374 if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
375 match = (vap->va_uid == cred->cr_uid ||
376 vap->va_uid == cred->cr_ruid ||
377 vap->va_uid == cred->cr_svuid);
378
379 if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)
380 match = !match;
381
382 if (!match)
383 return 0;
384 }
385
386 if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
387 match = (groupmember(vap->va_gid, cred) ||
388 vap->va_gid == cred->cr_rgid ||
389 vap->va_gid == cred->cr_svgid);
390
391 if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)
392 match = !match;
393
394 if (!match)
395 return 0;
396 }
397
398 if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
399 switch (vap->va_type) {
400 case VREG:
401 match = (rule->mbr_object.mbo_type & MBO_TYPE_REG);
402 break;
403 case VDIR:
404 match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR);
405 break;
406 case VBLK:
407 match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK);
408 break;
409 case VCHR:
410 match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR);
411 break;
412 case VLNK:
413 match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK);
414 break;
415 case VSOCK:
416 match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK);
417 break;
418 case VFIFO:
419 match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO);
420 break;
421 default:
422 match = 0;
423 }
424
425 if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)
426 match = !match;
427
428 if (!match)
429 return 0;
430 }
431
298 /*
299 * Is the access permitted?
300 */
301 if ((rule->mbr_mode & acc_mode) != acc_mode) {
302 if (mac_bsdextended_logging)
303 log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
304 " on %d:%d failed. \n", cred->cr_ruid,
432 /*
433 * Is the access permitted?
434 */
435 if ((rule->mbr_mode & acc_mode) != acc_mode) {
436 if (mac_bsdextended_logging)
437 log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
438 " on %d:%d failed. \n", cred->cr_ruid,
305 cred->cr_rgid, acc_mode, object_uid, object_gid);
439 cred->cr_rgid, acc_mode, vap->va_uid, vap->va_gid);
306 return (EACCES); /* Matching rule denies access */
307 }
308
309 /*
310 * If the rule matched, permits access, and first match is enabled,
311 * return success.
312 */
313 if (mac_bsdextended_firstmatch_enabled)
314 return (EJUSTRETURN);
315 else
316 return(0);
317}
318
319static int
440 return (EACCES); /* Matching rule denies access */
441 }
442
443 /*
444 * If the rule matched, permits access, and first match is enabled,
445 * return success.
446 */
447 if (mac_bsdextended_firstmatch_enabled)
448 return (EJUSTRETURN);
449 else
450 return(0);
451}
452
453static int
320mac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
454mac_bsdextended_check(struct ucred *cred, struct vnode *vp, struct vattr *vap,
321 int acc_mode)
322{
323 int error, i;
324
325 if (suser_cred(cred, 0) == 0)
326 return (0);
327
328 mtx_lock(&mac_bsdextended_mtx);

--- 5 unchanged lines hidden (view full) ---

334 * Since we do not separately handle append, map append to
335 * write.
336 */
337 if (acc_mode & MBI_APPEND) {
338 acc_mode &= ~MBI_APPEND;
339 acc_mode |= MBI_WRITE;
340 }
341
455 int acc_mode)
456{
457 int error, i;
458
459 if (suser_cred(cred, 0) == 0)
460 return (0);
461
462 mtx_lock(&mac_bsdextended_mtx);

--- 5 unchanged lines hidden (view full) ---

468 * Since we do not separately handle append, map append to
469 * write.
470 */
471 if (acc_mode & MBI_APPEND) {
472 acc_mode &= ~MBI_APPEND;
473 acc_mode |= MBI_WRITE;
474 }
475
342 error = mac_bsdextended_rulecheck(rules[i], cred, object_uid,
343 object_gid, acc_mode);
476 error = mac_bsdextended_rulecheck(rules[i], cred,
477 vp, vap, acc_mode);
344 if (error == EJUSTRETURN)
345 break;
346 if (error) {
347 mtx_unlock(&mac_bsdextended_mtx);
348 return (error);
349 }
350 }
351 mtx_unlock(&mac_bsdextended_mtx);

--- 8 unchanged lines hidden (view full) ---

360
361 if (!mac_bsdextended_enabled)
362 return (0);
363
364 error = VOP_GETATTR(vp, &vap, cred, curthread);
365 if (error)
366 return (error);
367
478 if (error == EJUSTRETURN)
479 break;
480 if (error) {
481 mtx_unlock(&mac_bsdextended_mtx);
482 return (error);
483 }
484 }
485 mtx_unlock(&mac_bsdextended_mtx);

--- 8 unchanged lines hidden (view full) ---

494
495 if (!mac_bsdextended_enabled)
496 return (0);
497
498 error = VOP_GETATTR(vp, &vap, cred, curthread);
499 if (error)
500 return (error);
501
368 return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
369 acc_mode));
502 return (mac_bsdextended_check(cred, vp, &vap, acc_mode));
370}
371
372static int
373mac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
374 struct label *label)
375{
376
377 return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));

--- 277 unchanged lines hidden ---
503}
504
505static int
506mac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
507 struct label *label)
508{
509
510 return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));

--- 277 unchanged lines hidden ---