1 /*-
2 * Copyright (c) 1999-2002, 2007 Robert N. M. Watson
3 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
4 * Copyright (c) 2005 Tom Rhodes
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.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
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$
37 */
38
39 /*
40 * Developed by the TrustedBSD Project.
41 *
42 * "BSD Extended" MAC policy, allowing the administrator to impose mandatory
43 * firewall-like rules regarding users and file system objects.
44 */
45
46 #include <sys/param.h>
47 #include <sys/acl.h>
48 #include <sys/kernel.h>
49 #include <sys/jail.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/module.h>
53 #include <sys/mount.h>
54 #include <sys/mutex.h>
55 #include <sys/priv.h>
56 #include <sys/systm.h>
57 #include <sys/vnode.h>
58 #include <sys/sysctl.h>
59 #include <sys/syslog.h>
60
61 #include <security/mac/mac_policy.h>
62 #include <security/mac_bsdextended/mac_bsdextended.h>
63
64 static struct mtx ugidfw_mtx;
65
66 SYSCTL_DECL(_security_mac);
67
68 SYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
69 "TrustedBSD extended BSD MAC policy controls");
70
71 static int ugidfw_enabled = 1;
72 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
73 &ugidfw_enabled, 0, "Enforce extended BSD policy");
74 TUNABLE_INT("security.mac.bsdextended.enabled", &ugidfw_enabled);
75
76 MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
77
78 #define MAC_BSDEXTENDED_MAXRULES 250
79 static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
80 static int rule_count = 0;
81 static int rule_slots = 0;
82 static int rule_version = MB_VERSION;
83
84 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
85 &rule_count, 0, "Number of defined rules\n");
86 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
87 &rule_slots, 0, "Number of used rule slots\n");
88 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD,
89 &rule_version, 0, "Version number for API\n");
90
91 /*
92 * This is just used for logging purposes, eventually we would like to log
93 * much more then failed requests.
94 */
95 static int ugidfw_logging;
96 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
97 &ugidfw_logging, 0, "Log failed authorization requests");
98
99 /*
100 * This tunable is here for compatibility. It will allow the user to switch
101 * between the new mode (first rule matches) and the old functionality (all
102 * rules match).
103 */
104 static int ugidfw_firstmatch_enabled;
105 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
106 CTLFLAG_RW, &ugidfw_firstmatch_enabled, 1,
107 "Disable/enable match first rule functionality");
108
109 static int
110 ugidfw_rule_valid(struct mac_bsdextended_rule *rule)
111 {
112
113 if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
114 return (EINVAL);
115 if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
116 return (EINVAL);
117 if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
118 return (EINVAL);
119 if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
120 return (EINVAL);
121 if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) &&
122 (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE)
123 return (EINVAL);
124 if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
125 return (EINVAL);
126 return (0);
127 }
128
129 static int
130 sysctl_rule(SYSCTL_HANDLER_ARGS)
131 {
132 struct mac_bsdextended_rule temprule, *ruleptr;
133 u_int namelen;
134 int error, index, *name;
135
136 error = 0;
137 name = (int *)arg1;
138 namelen = arg2;
139 if (namelen != 1)
140 return (EINVAL);
141 index = name[0];
142 if (index >= MAC_BSDEXTENDED_MAXRULES)
143 return (ENOENT);
144
145 ruleptr = NULL;
146 if (req->newptr && req->newlen != 0) {
147 error = SYSCTL_IN(req, &temprule, sizeof(temprule));
148 if (error)
149 return (error);
150 MALLOC(ruleptr, struct mac_bsdextended_rule *,
151 sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO);
152 }
153
154 mtx_lock(&ugidfw_mtx);
155 if (req->oldptr) {
156 if (index < 0 || index > rule_slots + 1) {
157 error = ENOENT;
158 goto out;
159 }
160 if (rules[index] == NULL) {
161 error = ENOENT;
162 goto out;
163 }
164 temprule = *rules[index];
165 }
166 if (req->newptr && req->newlen == 0) {
167 KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL"));
168 ruleptr = rules[index];
169 if (ruleptr == NULL) {
170 error = ENOENT;
171 goto out;
172 }
173 rule_count--;
174 rules[index] = NULL;
175 } else if (req->newptr) {
176 error = ugidfw_rule_valid(&temprule);
177 if (error)
178 goto out;
179 if (rules[index] == NULL) {
180 *ruleptr = temprule;
181 rules[index] = ruleptr;
182 ruleptr = NULL;
183 if (index + 1 > rule_slots)
184 rule_slots = index + 1;
185 rule_count++;
186 } else
187 *rules[index] = temprule;
188 }
189 out:
190 mtx_unlock(&ugidfw_mtx);
191 if (ruleptr != NULL)
192 FREE(ruleptr, M_MACBSDEXTENDED);
193 if (req->oldptr && error == 0)
194 error = SYSCTL_OUT(req, &temprule, sizeof(temprule));
195 return (error);
196 }
197
198 SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, CTLFLAG_RW,
199 sysctl_rule, "BSD extended MAC rules");
200
201 static void
202 ugidfw_init(struct mac_policy_conf *mpc)
203 {
204
205 mtx_init(&ugidfw_mtx, "mac_bsdextended lock", NULL, MTX_DEF);
206 }
207
208 static void
209 ugidfw_destroy(struct mac_policy_conf *mpc)
210 {
211 int i;
212
213 for (i = 0; i < MAC_BSDEXTENDED_MAXRULES; i++) {
214 if (rules[i] != NULL)
215 free(rules[i], M_MACBSDEXTENDED);
216 }
217 mtx_destroy(&ugidfw_mtx);
218 }
219
220 static int
221 ugidfw_rulecheck(struct mac_bsdextended_rule *rule,
222 struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode)
223 {
224 int match;
225 int i;
226
227 /*
228 * Is there a subject match?
229 */
230 mtx_assert(&ugidfw_mtx, MA_OWNED);
231 if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) {
232 match = ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max &&
233 cred->cr_uid >= rule->mbr_subject.mbs_uid_min) ||
234 (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max &&
235 cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) ||
236 (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max &&
237 cred->cr_svuid >= rule->mbr_subject.mbs_uid_min));
238 if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED)
239 match = !match;
240 if (!match)
241 return (0);
242 }
243
244 if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) {
245 match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max &&
246 cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) ||
247 (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max &&
248 cred->cr_svgid >= rule->mbr_subject.mbs_gid_min));
249 if (!match) {
250 for (i = 0; i < cred->cr_ngroups; i++) {
251 if (cred->cr_groups[i]
252 <= rule->mbr_subject.mbs_gid_max &&
253 cred->cr_groups[i]
254 >= rule->mbr_subject.mbs_gid_min) {
255 match = 1;
256 break;
257 }
258 }
259 }
260 if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED)
261 match = !match;
262 if (!match)
263 return (0);
264 }
265
266 if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
267 match = (cred->cr_prison != NULL &&
268 cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison);
269 if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)
270 match = !match;
271 if (!match)
272 return (0);
273 }
274
275 /*
276 * Is there an object match?
277 */
278 if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
279 match = (vap->va_uid <= rule->mbr_object.mbo_uid_max &&
280 vap->va_uid >= rule->mbr_object.mbo_uid_min);
281 if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)
282 match = !match;
283 if (!match)
284 return (0);
285 }
286
287 if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
288 match = (vap->va_gid <= rule->mbr_object.mbo_gid_max &&
289 vap->va_gid >= rule->mbr_object.mbo_gid_min);
290 if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)
291 match = !match;
292 if (!match)
293 return (0);
294 }
295
296 if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
297 match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid),
298 &(rule->mbr_object.mbo_fsid),
299 sizeof(rule->mbr_object.mbo_fsid)) == 0);
300 if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)
301 match = !match;
302 if (!match)
303 return (0);
304 }
305
306 if (rule->mbr_object.mbo_flags & MBO_SUID) {
307 match = (vap->va_mode & VSUID);
308 if (rule->mbr_object.mbo_neg & MBO_SUID)
309 match = !match;
310 if (!match)
311 return (0);
312 }
313
314 if (rule->mbr_object.mbo_flags & MBO_SGID) {
315 match = (vap->va_mode & VSGID);
316 if (rule->mbr_object.mbo_neg & MBO_SGID)
317 match = !match;
318 if (!match)
319 return (0);
320 }
321
322 if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
323 match = (vap->va_uid == cred->cr_uid ||
324 vap->va_uid == cred->cr_ruid ||
325 vap->va_uid == cred->cr_svuid);
326 if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)
327 match = !match;
328 if (!match)
329 return (0);
330 }
331
332 if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
333 match = (groupmember(vap->va_gid, cred) ||
334 vap->va_gid == cred->cr_rgid ||
335 vap->va_gid == cred->cr_svgid);
336 if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)
337 match = !match;
338 if (!match)
339 return (0);
340 }
341
342 if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
343 switch (vap->va_type) {
344 case VREG:
345 match = (rule->mbr_object.mbo_type & MBO_TYPE_REG);
346 break;
347 case VDIR:
348 match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR);
349 break;
350 case VBLK:
351 match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK);
352 break;
353 case VCHR:
354 match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR);
355 break;
356 case VLNK:
357 match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK);
358 break;
359 case VSOCK:
360 match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK);
361 break;
362 case VFIFO:
363 match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO);
364 break;
365 default:
366 match = 0;
367 }
368 if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)
369 match = !match;
370 if (!match)
371 return (0);
372 }
373
374 /*
375 * Is the access permitted?
376 */
377 if ((rule->mbr_mode & acc_mode) != acc_mode) {
378 if (ugidfw_logging)
379 log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
380 " on %d:%d failed. \n", cred->cr_ruid,
381 cred->cr_rgid, acc_mode, vap->va_uid,
382 vap->va_gid);
383 return (EACCES);
384 }
385
386 /*
387 * If the rule matched, permits access, and first match is enabled,
388 * return success.
389 */
390 if (ugidfw_firstmatch_enabled)
391 return (EJUSTRETURN);
392 else
393 return (0);
394 }
395
396 static int
397 ugidfw_check(struct ucred *cred, struct vnode *vp, struct vattr *vap,
398 int acc_mode)
399 {
400 int error, i;
401
402 /*
403 * XXXRW: More specific privilege selection needed.
404 */
405 if (suser_cred(cred, 0) == 0)
406 return (0);
407
408 /*
409 * Since we do not separately handle append, map append to write.
410 */
411 if (acc_mode & MBI_APPEND) {
412 acc_mode &= ~MBI_APPEND;
413 acc_mode |= MBI_WRITE;
414 }
415 mtx_lock(&ugidfw_mtx);
416 for (i = 0; i < rule_slots; i++) {
417 if (rules[i] == NULL)
418 continue;
419 error = ugidfw_rulecheck(rules[i], cred,
420 vp, vap, acc_mode);
421 if (error == EJUSTRETURN)
422 break;
423 if (error) {
424 mtx_unlock(&ugidfw_mtx);
425 return (error);
426 }
427 }
428 mtx_unlock(&ugidfw_mtx);
429 return (0);
430 }
431
432 static int
433 ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode)
434 {
435 int error;
436 struct vattr vap;
437
438 if (!ugidfw_enabled)
439 return (0);
440 error = VOP_GETATTR(vp, &vap, cred, curthread);
441 if (error)
442 return (error);
443 return (ugidfw_check(cred, vp, &vap, acc_mode));
444 }
445
446 static int
447 ugidfw_check_system_acct(struct ucred *cred, struct vnode *vp,
448 struct label *vplabel)
449 {
450
451 if (vp != NULL)
452 return (ugidfw_check_vp(cred, vp, MBI_WRITE));
453 else
454 return (0);
455 }
456
457 static int
458 ugidfw_check_system_auditctl(struct ucred *cred, struct vnode *vp,
459 struct label *vplabel)
460 {
461
462 if (vp != NULL)
463 return (ugidfw_check_vp(cred, vp, MBI_WRITE));
464 else
465 return (0);
466 }
467
468 static int
469 ugidfw_check_system_swapon(struct ucred *cred, struct vnode *vp,
470 struct label *vplabel)
471 {
472
473 return (ugidfw_check_vp(cred, vp, MBI_WRITE));
474 }
475
476 static int
477 ugidfw_check_vnode_access(struct ucred *cred, struct vnode *vp,
478 struct label *vplabel, int acc_mode)
479 {
480
481 return (ugidfw_check_vp(cred, vp, acc_mode));
482 }
483
484 static int
485 ugidfw_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
486 struct label *dvplabel)
487 {
488
489 return (ugidfw_check_vp(cred, dvp, MBI_EXEC));
490 }
491
492 static int
493 ugidfw_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
494 struct label *dvplabel)
495 {
496
497 return (ugidfw_check_vp(cred, dvp, MBI_EXEC));
498 }
499
500 static int
501 ugidfw_check_create_vnode(struct ucred *cred, struct vnode *dvp,
502 struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
503 {
504
505 return (ugidfw_check_vp(cred, dvp, MBI_WRITE));
506 }
507
508 static int
509 ugidfw_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
510 struct label *vplabel, acl_type_t type)
511 {
512
513 return (ugidfw_check_vp(cred, vp, MBI_ADMIN));
514 }
515
516 static int
517 ugidfw_check_vnode_deleteextattr(struct ucred *cred,
518 struct vnode *vp, struct label *vplabel, int attrnamespace,
519 const char *name)
520 {
521
522 return (ugidfw_check_vp(cred, vp, MBI_WRITE));
523 }
524
525 static int
526 ugidfw_check_vnode_exec(struct ucred *cred, struct vnode *vp,
527 struct label *vplabel, struct image_params *imgp,
528 struct label *execlabel)
529 {
530
531 return (ugidfw_check_vp(cred, vp, MBI_READ|MBI_EXEC));
532 }
533
534 static int
535 ugidfw_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
536 struct label *vplabel, acl_type_t type)
537 {
538
539 return (ugidfw_check_vp(cred, vp, MBI_STAT));
540 }
541
542 static int
543 ugidfw_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
544 struct label *vplabel, int attrnamespace, const char *name,
545 struct uio *uio)
546 {
547
548 return (ugidfw_check_vp(cred, vp, MBI_READ));
549 }
550
551 static int
552 ugidfw_check_vnode_link(struct ucred *cred, struct vnode *dvp,
553 struct label *dvplabel, struct vnode *vp, struct label *label,
554 struct componentname *cnp)
555 {
556 int error;
557
558 error = ugidfw_check_vp(cred, dvp, MBI_WRITE);
559 if (error)
560 return (error);
561 error = ugidfw_check_vp(cred, vp, MBI_WRITE);
562 if (error)
563 return (error);
564 return (0);
565 }
566
567 static int
568 ugidfw_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
569 struct label *vplabel, int attrnamespace)
570 {
571
572 return (ugidfw_check_vp(cred, vp, MBI_READ));
573 }
574
575 static int
576 ugidfw_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
577 struct label *dvplabel, struct componentname *cnp)
578 {
579
580 return (ugidfw_check_vp(cred, dvp, MBI_EXEC));
581 }
582
583 static int
584 ugidfw_check_vnode_open(struct ucred *cred, struct vnode *vp,
585 struct label *vplabel, int acc_mode)
586 {
587
588 return (ugidfw_check_vp(cred, vp, acc_mode));
589 }
590
591 static int
592 ugidfw_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
593 struct label *dvplabel)
594 {
595
596 return (ugidfw_check_vp(cred, dvp, MBI_READ));
597 }
598
599 static int
600 ugidfw_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
601 struct label *vplabel)
602 {
603
604 return (ugidfw_check_vp(cred, vp, MBI_READ));
605 }
606
607 static int
608 ugidfw_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
609 struct label *dvplabel, struct vnode *vp, struct label *vplabel,
610 struct componentname *cnp)
611 {
612 int error;
613
614 error = ugidfw_check_vp(cred, dvp, MBI_WRITE);
615 if (error)
616 return (error);
617 return (ugidfw_check_vp(cred, vp, MBI_WRITE));
618 }
619
620 static int
621 ugidfw_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
622 struct label *dvplabel, struct vnode *vp, struct label *vplabel,
623 int samedir, struct componentname *cnp)
624 {
625 int error;
626
627 error = ugidfw_check_vp(cred, dvp, MBI_WRITE);
628 if (error)
629 return (error);
630 if (vp != NULL)
631 error = ugidfw_check_vp(cred, vp, MBI_WRITE);
632 return (error);
633 }
634
635 static int
636 ugidfw_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
637 struct label *vplabel)
638 {
639
640 return (ugidfw_check_vp(cred, vp, MBI_ADMIN));
641 }
642
643 static int
644 ugidfw_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
645 struct label *vplabel, acl_type_t type, struct acl *acl)
646 {
647
648 return (ugidfw_check_vp(cred, vp, MBI_ADMIN));
649 }
650
651 static int
652 ugidfw_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
653 struct label *vplabel, int attrnamespace, const char *name,
654 struct uio *uio)
655 {
656
657 return (ugidfw_check_vp(cred, vp, MBI_WRITE));
658 }
659
660 static int
661 ugidfw_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
662 struct label *vplabel, u_long flags)
663 {
664
665 return (ugidfw_check_vp(cred, vp, MBI_ADMIN));
666 }
667
668 static int
669 ugidfw_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
670 struct label *vplabel, mode_t mode)
671 {
672
673 return (ugidfw_check_vp(cred, vp, MBI_ADMIN));
674 }
675
676 static int
677 ugidfw_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
678 struct label *vplabel, uid_t uid, gid_t gid)
679 {
680
681 return (ugidfw_check_vp(cred, vp, MBI_ADMIN));
682 }
683
684 static int
685 ugidfw_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
686 struct label *vplabel, struct timespec atime, struct timespec utime)
687 {
688
689 return (ugidfw_check_vp(cred, vp, MBI_ADMIN));
690 }
691
692 static int
693 ugidfw_check_vnode_stat(struct ucred *active_cred,
694 struct ucred *file_cred, struct vnode *vp, struct label *vplabel)
695 {
696
697 return (ugidfw_check_vp(active_cred, vp, MBI_STAT));
698 }
699
700 static int
701 ugidfw_check_vnode_unlink(struct ucred *cred, struct vnode *dvp,
702 struct label *dvplabel, struct vnode *vp, struct label *vplabel,
703 struct componentname *cnp)
704 {
705 int error;
706
707 error = ugidfw_check_vp(cred, dvp, MBI_WRITE);
708 if (error)
709 return (error);
710 return (ugidfw_check_vp(cred, vp, MBI_WRITE));
711 }
712
713 static struct mac_policy_ops ugidfw_ops =
714 {
715 .mpo_destroy = ugidfw_destroy,
716 .mpo_init = ugidfw_init,
717 .mpo_check_system_acct = ugidfw_check_system_acct,
718 .mpo_check_system_auditctl = ugidfw_check_system_auditctl,
719 .mpo_check_system_swapon = ugidfw_check_system_swapon,
720 .mpo_check_vnode_access = ugidfw_check_vnode_access,
721 .mpo_check_vnode_chdir = ugidfw_check_vnode_chdir,
722 .mpo_check_vnode_chroot = ugidfw_check_vnode_chroot,
723 .mpo_check_vnode_create = ugidfw_check_create_vnode,
724 .mpo_check_vnode_deleteacl = ugidfw_check_vnode_deleteacl,
725 .mpo_check_vnode_deleteextattr = ugidfw_check_vnode_deleteextattr,
726 .mpo_check_vnode_exec = ugidfw_check_vnode_exec,
727 .mpo_check_vnode_getacl = ugidfw_check_vnode_getacl,
728 .mpo_check_vnode_getextattr = ugidfw_check_vnode_getextattr,
729 .mpo_check_vnode_link = ugidfw_check_vnode_link,
730 .mpo_check_vnode_listextattr = ugidfw_check_vnode_listextattr,
731 .mpo_check_vnode_lookup = ugidfw_check_vnode_lookup,
732 .mpo_check_vnode_open = ugidfw_check_vnode_open,
733 .mpo_check_vnode_readdir = ugidfw_check_vnode_readdir,
734 .mpo_check_vnode_readlink = ugidfw_check_vnode_readdlink,
735 .mpo_check_vnode_rename_from = ugidfw_check_vnode_rename_from,
736 .mpo_check_vnode_rename_to = ugidfw_check_vnode_rename_to,
737 .mpo_check_vnode_revoke = ugidfw_check_vnode_revoke,
738 .mpo_check_vnode_setacl = ugidfw_check_setacl_vnode,
739 .mpo_check_vnode_setextattr = ugidfw_check_vnode_setextattr,
740 .mpo_check_vnode_setflags = ugidfw_check_vnode_setflags,
741 .mpo_check_vnode_setmode = ugidfw_check_vnode_setmode,
742 .mpo_check_vnode_setowner = ugidfw_check_vnode_setowner,
743 .mpo_check_vnode_setutimes = ugidfw_check_vnode_setutimes,
744 .mpo_check_vnode_stat = ugidfw_check_vnode_stat,
745 .mpo_check_vnode_unlink = ugidfw_check_vnode_unlink,
746 };
747
748 MAC_POLICY_SET(&ugidfw_ops, mac_bsdextended, "TrustedBSD MAC/BSD Extended",
749 MPC_LOADTIME_FLAG_UNLOADOK, NULL);
Cache object: 7096e892719eccbf90842a6ce61c466c
|