diff options
Diffstat (limited to 'security/selinux')
45 files changed, 4358 insertions, 3782 deletions
diff --git a/security/selinux/.gitignore b/security/selinux/.gitignore new file mode 100644 index 00000000000..2e5040a3d48 --- /dev/null +++ b/security/selinux/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | av_permissions.h | ||
2 | flask.h | ||
diff --git a/security/selinux/Makefile b/security/selinux/Makefile index d47fc5e545e..ad5cd76ec23 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile | |||
@@ -2,21 +2,24 @@ | |||
2 | # Makefile for building the SELinux module as part of the kernel tree. | 2 | # Makefile for building the SELinux module as part of the kernel tree. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ | 5 | obj-$(CONFIG_SECURITY_SELINUX) := selinux.o |
6 | 6 | ||
7 | selinux-y := avc.o \ | 7 | selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \ |
8 | hooks.o \ | 8 | netnode.o netport.o exports.o \ |
9 | selinuxfs.o \ | 9 | ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \ |
10 | netlink.o \ | 10 | ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o |
11 | nlmsgtab.o \ | ||
12 | netif.o \ | ||
13 | netnode.o \ | ||
14 | netport.o \ | ||
15 | exports.o | ||
16 | 11 | ||
17 | selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o | 12 | selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o |
18 | 13 | ||
19 | selinux-$(CONFIG_NETLABEL) += netlabel.o | 14 | selinux-$(CONFIG_NETLABEL) += netlabel.o |
20 | 15 | ||
21 | EXTRA_CFLAGS += -Isecurity/selinux/include | 16 | ccflags-y := -Isecurity/selinux -Isecurity/selinux/include |
17 | |||
18 | $(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h | ||
19 | |||
20 | quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h | ||
21 | cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h | ||
22 | 22 | ||
23 | targets += flask.h av_permissions.h | ||
24 | $(obj)/flask.h: $(src)/include/classmap.h FORCE | ||
25 | $(call if_changed,flask) | ||
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b2ab6085983..9da6420e205 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -31,43 +31,7 @@ | |||
31 | #include <net/ipv6.h> | 31 | #include <net/ipv6.h> |
32 | #include "avc.h" | 32 | #include "avc.h" |
33 | #include "avc_ss.h" | 33 | #include "avc_ss.h" |
34 | 34 | #include "classmap.h" | |
35 | static const struct av_perm_to_string av_perm_to_string[] = { | ||
36 | #define S_(c, v, s) { c, v, s }, | ||
37 | #include "av_perm_to_string.h" | ||
38 | #undef S_ | ||
39 | }; | ||
40 | |||
41 | static const char *class_to_string[] = { | ||
42 | #define S_(s) s, | ||
43 | #include "class_to_string.h" | ||
44 | #undef S_ | ||
45 | }; | ||
46 | |||
47 | #define TB_(s) static const char *s[] = { | ||
48 | #define TE_(s) }; | ||
49 | #define S_(s) s, | ||
50 | #include "common_perm_to_string.h" | ||
51 | #undef TB_ | ||
52 | #undef TE_ | ||
53 | #undef S_ | ||
54 | |||
55 | static const struct av_inherit av_inherit[] = { | ||
56 | #define S_(c, i, b) { .tclass = c,\ | ||
57 | .common_pts = common_##i##_perm_to_string,\ | ||
58 | .common_base = b }, | ||
59 | #include "av_inherit.h" | ||
60 | #undef S_ | ||
61 | }; | ||
62 | |||
63 | const struct selinux_class_perm selinux_class_perm = { | ||
64 | .av_perm_to_string = av_perm_to_string, | ||
65 | .av_pts_len = ARRAY_SIZE(av_perm_to_string), | ||
66 | .class_to_string = class_to_string, | ||
67 | .cts_len = ARRAY_SIZE(class_to_string), | ||
68 | .av_inherit = av_inherit, | ||
69 | .av_inherit_len = ARRAY_SIZE(av_inherit) | ||
70 | }; | ||
71 | 35 | ||
72 | #define AVC_CACHE_SLOTS 512 | 36 | #define AVC_CACHE_SLOTS 512 |
73 | #define AVC_DEF_CACHE_THRESHOLD 512 | 37 | #define AVC_DEF_CACHE_THRESHOLD 512 |
@@ -137,54 +101,30 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) | |||
137 | * @tclass: target security class | 101 | * @tclass: target security class |
138 | * @av: access vector | 102 | * @av: access vector |
139 | */ | 103 | */ |
140 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) | 104 | static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) |
141 | { | 105 | { |
142 | const char **common_pts = NULL; | 106 | const char **perms; |
143 | u32 common_base = 0; | 107 | int i, perm; |
144 | int i, i2, perm; | ||
145 | 108 | ||
146 | if (av == 0) { | 109 | if (av == 0) { |
147 | audit_log_format(ab, " null"); | 110 | audit_log_format(ab, " null"); |
148 | return; | 111 | return; |
149 | } | 112 | } |
150 | 113 | ||
151 | for (i = 0; i < ARRAY_SIZE(av_inherit); i++) { | 114 | perms = secclass_map[tclass-1].perms; |
152 | if (av_inherit[i].tclass == tclass) { | ||
153 | common_pts = av_inherit[i].common_pts; | ||
154 | common_base = av_inherit[i].common_base; | ||
155 | break; | ||
156 | } | ||
157 | } | ||
158 | 115 | ||
159 | audit_log_format(ab, " {"); | 116 | audit_log_format(ab, " {"); |
160 | i = 0; | 117 | i = 0; |
161 | perm = 1; | 118 | perm = 1; |
162 | while (perm < common_base) { | 119 | while (i < (sizeof(av) * 8)) { |
163 | if (perm & av) { | 120 | if ((perm & av) && perms[i]) { |
164 | audit_log_format(ab, " %s", common_pts[i]); | 121 | audit_log_format(ab, " %s", perms[i]); |
165 | av &= ~perm; | 122 | av &= ~perm; |
166 | } | 123 | } |
167 | i++; | 124 | i++; |
168 | perm <<= 1; | 125 | perm <<= 1; |
169 | } | 126 | } |
170 | 127 | ||
171 | while (i < sizeof(av) * 8) { | ||
172 | if (perm & av) { | ||
173 | for (i2 = 0; i2 < ARRAY_SIZE(av_perm_to_string); i2++) { | ||
174 | if ((av_perm_to_string[i2].tclass == tclass) && | ||
175 | (av_perm_to_string[i2].value == perm)) | ||
176 | break; | ||
177 | } | ||
178 | if (i2 < ARRAY_SIZE(av_perm_to_string)) { | ||
179 | audit_log_format(ab, " %s", | ||
180 | av_perm_to_string[i2].name); | ||
181 | av &= ~perm; | ||
182 | } | ||
183 | } | ||
184 | i++; | ||
185 | perm <<= 1; | ||
186 | } | ||
187 | |||
188 | if (av) | 128 | if (av) |
189 | audit_log_format(ab, " 0x%x", av); | 129 | audit_log_format(ab, " 0x%x", av); |
190 | 130 | ||
@@ -219,8 +159,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla | |||
219 | kfree(scontext); | 159 | kfree(scontext); |
220 | } | 160 | } |
221 | 161 | ||
222 | BUG_ON(tclass >= ARRAY_SIZE(class_to_string) || !class_to_string[tclass]); | 162 | BUG_ON(tclass >= ARRAY_SIZE(secclass_map)); |
223 | audit_log_format(ab, " tclass=%s", class_to_string[tclass]); | 163 | audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name); |
224 | } | 164 | } |
225 | 165 | ||
226 | /** | 166 | /** |
@@ -348,7 +288,6 @@ static struct avc_node *avc_alloc_node(void) | |||
348 | if (!node) | 288 | if (!node) |
349 | goto out; | 289 | goto out; |
350 | 290 | ||
351 | INIT_RCU_HEAD(&node->rhead); | ||
352 | INIT_HLIST_NODE(&node->list); | 291 | INIT_HLIST_NODE(&node->list); |
353 | avc_cache_stats_incr(allocations); | 292 | avc_cache_stats_incr(allocations); |
354 | 293 | ||
@@ -397,7 +336,7 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) | |||
397 | * Look up an AVC entry that is valid for the | 336 | * Look up an AVC entry that is valid for the |
398 | * (@ssid, @tsid), interpreting the permissions | 337 | * (@ssid, @tsid), interpreting the permissions |
399 | * based on @tclass. If a valid AVC entry exists, | 338 | * based on @tclass. If a valid AVC entry exists, |
400 | * then this function return the avc_node. | 339 | * then this function returns the avc_node. |
401 | * Otherwise, this function returns NULL. | 340 | * Otherwise, this function returns NULL. |
402 | */ | 341 | */ |
403 | static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) | 342 | static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) |
@@ -492,23 +431,35 @@ out: | |||
492 | return node; | 431 | return node; |
493 | } | 432 | } |
494 | 433 | ||
495 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 434 | /** |
496 | struct in6_addr *addr, __be16 port, | 435 | * avc_audit_pre_callback - SELinux specific information |
497 | char *name1, char *name2) | 436 | * will be called by generic audit code |
437 | * @ab: the audit buffer | ||
438 | * @a: audit_data | ||
439 | */ | ||
440 | static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | ||
498 | { | 441 | { |
499 | if (!ipv6_addr_any(addr)) | 442 | struct common_audit_data *ad = a; |
500 | audit_log_format(ab, " %s=%pI6", name1, addr); | 443 | audit_log_format(ab, "avc: %s ", |
501 | if (port) | 444 | ad->selinux_audit_data.denied ? "denied" : "granted"); |
502 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 445 | avc_dump_av(ab, ad->selinux_audit_data.tclass, |
446 | ad->selinux_audit_data.audited); | ||
447 | audit_log_format(ab, " for "); | ||
503 | } | 448 | } |
504 | 449 | ||
505 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | 450 | /** |
506 | __be16 port, char *name1, char *name2) | 451 | * avc_audit_post_callback - SELinux specific information |
452 | * will be called by generic audit code | ||
453 | * @ab: the audit buffer | ||
454 | * @a: audit_data | ||
455 | */ | ||
456 | static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||
507 | { | 457 | { |
508 | if (addr) | 458 | struct common_audit_data *ad = a; |
509 | audit_log_format(ab, " %s=%pI4", name1, &addr); | 459 | audit_log_format(ab, " "); |
510 | if (port) | 460 | avc_dump_query(ab, ad->selinux_audit_data.ssid, |
511 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 461 | ad->selinux_audit_data.tsid, |
462 | ad->selinux_audit_data.tclass); | ||
512 | } | 463 | } |
513 | 464 | ||
514 | /** | 465 | /** |
@@ -532,163 +483,52 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | |||
532 | */ | 483 | */ |
533 | void avc_audit(u32 ssid, u32 tsid, | 484 | void avc_audit(u32 ssid, u32 tsid, |
534 | u16 tclass, u32 requested, | 485 | u16 tclass, u32 requested, |
535 | struct av_decision *avd, int result, struct avc_audit_data *a) | 486 | struct av_decision *avd, int result, struct common_audit_data *a) |
536 | { | 487 | { |
537 | struct task_struct *tsk = current; | 488 | struct common_audit_data stack_data; |
538 | struct inode *inode = NULL; | ||
539 | u32 denied, audited; | 489 | u32 denied, audited; |
540 | struct audit_buffer *ab; | ||
541 | |||
542 | denied = requested & ~avd->allowed; | 490 | denied = requested & ~avd->allowed; |
543 | if (denied) { | 491 | if (denied) { |
544 | audited = denied; | 492 | audited = denied & avd->auditdeny; |
545 | if (!(audited & avd->auditdeny)) | 493 | /* |
546 | return; | 494 | * a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in |
547 | } else if (result) { | 495 | * this field means that ANY denials should NOT be audited if |
496 | * the policy contains an explicit dontaudit rule for that | ||
497 | * permission. Take notice that this is unrelated to the | ||
498 | * actual permissions that were denied. As an example lets | ||
499 | * assume: | ||
500 | * | ||
501 | * denied == READ | ||
502 | * avd.auditdeny & ACCESS == 0 (not set means explicit rule) | ||
503 | * selinux_audit_data.auditdeny & ACCESS == 1 | ||
504 | * | ||
505 | * We will NOT audit the denial even though the denied | ||
506 | * permission was READ and the auditdeny checks were for | ||
507 | * ACCESS | ||
508 | */ | ||
509 | if (a && | ||
510 | a->selinux_audit_data.auditdeny && | ||
511 | !(a->selinux_audit_data.auditdeny & avd->auditdeny)) | ||
512 | audited = 0; | ||
513 | } else if (result) | ||
548 | audited = denied = requested; | 514 | audited = denied = requested; |
549 | } else { | 515 | else |
550 | audited = requested; | 516 | audited = requested & avd->auditallow; |
551 | if (!(audited & avd->auditallow)) | 517 | if (!audited) |
552 | return; | 518 | return; |
553 | } | 519 | if (!a) { |
554 | 520 | a = &stack_data; | |
555 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | 521 | COMMON_AUDIT_DATA_INIT(a, NONE); |
556 | if (!ab) | ||
557 | return; /* audit_panic has been called */ | ||
558 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); | ||
559 | avc_dump_av(ab, tclass, audited); | ||
560 | audit_log_format(ab, " for "); | ||
561 | if (a && a->tsk) | ||
562 | tsk = a->tsk; | ||
563 | if (tsk && tsk->pid) { | ||
564 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | ||
565 | audit_log_untrustedstring(ab, tsk->comm); | ||
566 | } | ||
567 | if (a) { | ||
568 | switch (a->type) { | ||
569 | case AVC_AUDIT_DATA_IPC: | ||
570 | audit_log_format(ab, " key=%d", a->u.ipc_id); | ||
571 | break; | ||
572 | case AVC_AUDIT_DATA_CAP: | ||
573 | audit_log_format(ab, " capability=%d", a->u.cap); | ||
574 | break; | ||
575 | case AVC_AUDIT_DATA_FS: | ||
576 | if (a->u.fs.path.dentry) { | ||
577 | struct dentry *dentry = a->u.fs.path.dentry; | ||
578 | if (a->u.fs.path.mnt) { | ||
579 | audit_log_d_path(ab, "path=", | ||
580 | &a->u.fs.path); | ||
581 | } else { | ||
582 | audit_log_format(ab, " name="); | ||
583 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
584 | } | ||
585 | inode = dentry->d_inode; | ||
586 | } else if (a->u.fs.inode) { | ||
587 | struct dentry *dentry; | ||
588 | inode = a->u.fs.inode; | ||
589 | dentry = d_find_alias(inode); | ||
590 | if (dentry) { | ||
591 | audit_log_format(ab, " name="); | ||
592 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
593 | dput(dentry); | ||
594 | } | ||
595 | } | ||
596 | if (inode) | ||
597 | audit_log_format(ab, " dev=%s ino=%lu", | ||
598 | inode->i_sb->s_id, | ||
599 | inode->i_ino); | ||
600 | break; | ||
601 | case AVC_AUDIT_DATA_NET: | ||
602 | if (a->u.net.sk) { | ||
603 | struct sock *sk = a->u.net.sk; | ||
604 | struct unix_sock *u; | ||
605 | int len = 0; | ||
606 | char *p = NULL; | ||
607 | |||
608 | switch (sk->sk_family) { | ||
609 | case AF_INET: { | ||
610 | struct inet_sock *inet = inet_sk(sk); | ||
611 | |||
612 | avc_print_ipv4_addr(ab, inet->rcv_saddr, | ||
613 | inet->sport, | ||
614 | "laddr", "lport"); | ||
615 | avc_print_ipv4_addr(ab, inet->daddr, | ||
616 | inet->dport, | ||
617 | "faddr", "fport"); | ||
618 | break; | ||
619 | } | ||
620 | case AF_INET6: { | ||
621 | struct inet_sock *inet = inet_sk(sk); | ||
622 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | ||
623 | |||
624 | avc_print_ipv6_addr(ab, &inet6->rcv_saddr, | ||
625 | inet->sport, | ||
626 | "laddr", "lport"); | ||
627 | avc_print_ipv6_addr(ab, &inet6->daddr, | ||
628 | inet->dport, | ||
629 | "faddr", "fport"); | ||
630 | break; | ||
631 | } | ||
632 | case AF_UNIX: | ||
633 | u = unix_sk(sk); | ||
634 | if (u->dentry) { | ||
635 | struct path path = { | ||
636 | .dentry = u->dentry, | ||
637 | .mnt = u->mnt | ||
638 | }; | ||
639 | audit_log_d_path(ab, "path=", | ||
640 | &path); | ||
641 | break; | ||
642 | } | ||
643 | if (!u->addr) | ||
644 | break; | ||
645 | len = u->addr->len-sizeof(short); | ||
646 | p = &u->addr->name->sun_path[0]; | ||
647 | audit_log_format(ab, " path="); | ||
648 | if (*p) | ||
649 | audit_log_untrustedstring(ab, p); | ||
650 | else | ||
651 | audit_log_n_hex(ab, p, len); | ||
652 | break; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | switch (a->u.net.family) { | ||
657 | case AF_INET: | ||
658 | avc_print_ipv4_addr(ab, a->u.net.v4info.saddr, | ||
659 | a->u.net.sport, | ||
660 | "saddr", "src"); | ||
661 | avc_print_ipv4_addr(ab, a->u.net.v4info.daddr, | ||
662 | a->u.net.dport, | ||
663 | "daddr", "dest"); | ||
664 | break; | ||
665 | case AF_INET6: | ||
666 | avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr, | ||
667 | a->u.net.sport, | ||
668 | "saddr", "src"); | ||
669 | avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr, | ||
670 | a->u.net.dport, | ||
671 | "daddr", "dest"); | ||
672 | break; | ||
673 | } | ||
674 | if (a->u.net.netif > 0) { | ||
675 | struct net_device *dev; | ||
676 | |||
677 | /* NOTE: we always use init's namespace */ | ||
678 | dev = dev_get_by_index(&init_net, | ||
679 | a->u.net.netif); | ||
680 | if (dev) { | ||
681 | audit_log_format(ab, " netif=%s", | ||
682 | dev->name); | ||
683 | dev_put(dev); | ||
684 | } | ||
685 | } | ||
686 | break; | ||
687 | } | ||
688 | } | 522 | } |
689 | audit_log_format(ab, " "); | 523 | a->selinux_audit_data.tclass = tclass; |
690 | avc_dump_query(ab, ssid, tsid, tclass); | 524 | a->selinux_audit_data.requested = requested; |
691 | audit_log_end(ab); | 525 | a->selinux_audit_data.ssid = ssid; |
526 | a->selinux_audit_data.tsid = tsid; | ||
527 | a->selinux_audit_data.audited = audited; | ||
528 | a->selinux_audit_data.denied = denied; | ||
529 | a->lsm_pre_audit = avc_audit_pre_callback; | ||
530 | a->lsm_post_audit = avc_audit_post_callback; | ||
531 | common_lsm_audit(a); | ||
692 | } | 532 | } |
693 | 533 | ||
694 | /** | 534 | /** |
@@ -701,7 +541,7 @@ void avc_audit(u32 ssid, u32 tsid, | |||
701 | * @perms: permissions | 541 | * @perms: permissions |
702 | * | 542 | * |
703 | * Register a callback function for events in the set @events | 543 | * Register a callback function for events in the set @events |
704 | * related to the SID pair (@ssid, @tsid) and | 544 | * related to the SID pair (@ssid, @tsid) |
705 | * and the permissions @perms, interpreting | 545 | * and the permissions @perms, interpreting |
706 | * @perms based on @tclass. Returns %0 on success or | 546 | * @perms based on @tclass. Returns %0 on success or |
707 | * -%ENOMEM if insufficient memory exists to add the callback. | 547 | * -%ENOMEM if insufficient memory exists to add the callback. |
@@ -746,7 +586,7 @@ static inline int avc_sidcmp(u32 x, u32 y) | |||
746 | * | 586 | * |
747 | * if a valid AVC entry doesn't exist,this function returns -ENOENT. | 587 | * if a valid AVC entry doesn't exist,this function returns -ENOENT. |
748 | * if kmalloc() called internal returns NULL, this function returns -ENOMEM. | 588 | * if kmalloc() called internal returns NULL, this function returns -ENOMEM. |
749 | * otherwise, this function update the AVC entry. The original AVC-entry object | 589 | * otherwise, this function updates the AVC entry. The original AVC-entry object |
750 | * will release later by RCU. | 590 | * will release later by RCU. |
751 | */ | 591 | */ |
752 | static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, | 592 | static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, |
@@ -824,18 +664,16 @@ out: | |||
824 | } | 664 | } |
825 | 665 | ||
826 | /** | 666 | /** |
827 | * avc_ss_reset - Flush the cache and revalidate migrated permissions. | 667 | * avc_flush - Flush the cache |
828 | * @seqno: policy sequence number | ||
829 | */ | 668 | */ |
830 | int avc_ss_reset(u32 seqno) | 669 | static void avc_flush(void) |
831 | { | 670 | { |
832 | struct avc_callback_node *c; | ||
833 | int i, rc = 0, tmprc; | ||
834 | unsigned long flag; | ||
835 | struct avc_node *node; | ||
836 | struct hlist_head *head; | 671 | struct hlist_head *head; |
837 | struct hlist_node *next; | 672 | struct hlist_node *next; |
673 | struct avc_node *node; | ||
838 | spinlock_t *lock; | 674 | spinlock_t *lock; |
675 | unsigned long flag; | ||
676 | int i; | ||
839 | 677 | ||
840 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { | 678 | for (i = 0; i < AVC_CACHE_SLOTS; i++) { |
841 | head = &avc_cache.slots[i]; | 679 | head = &avc_cache.slots[i]; |
@@ -852,6 +690,18 @@ int avc_ss_reset(u32 seqno) | |||
852 | rcu_read_unlock(); | 690 | rcu_read_unlock(); |
853 | spin_unlock_irqrestore(lock, flag); | 691 | spin_unlock_irqrestore(lock, flag); |
854 | } | 692 | } |
693 | } | ||
694 | |||
695 | /** | ||
696 | * avc_ss_reset - Flush the cache and revalidate migrated permissions. | ||
697 | * @seqno: policy sequence number | ||
698 | */ | ||
699 | int avc_ss_reset(u32 seqno) | ||
700 | { | ||
701 | struct avc_callback_node *c; | ||
702 | int rc = 0, tmprc; | ||
703 | |||
704 | avc_flush(); | ||
855 | 705 | ||
856 | for (c = avc_callbacks; c; c = c->next) { | 706 | for (c = avc_callbacks; c; c = c->next) { |
857 | if (c->events & AVC_CALLBACK_RESET) { | 707 | if (c->events & AVC_CALLBACK_RESET) { |
@@ -911,9 +761,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
911 | else | 761 | else |
912 | avd = &avd_entry; | 762 | avd = &avd_entry; |
913 | 763 | ||
914 | rc = security_compute_av(ssid, tsid, tclass, requested, avd); | 764 | security_compute_av(ssid, tsid, tclass, avd); |
915 | if (rc) | ||
916 | goto out; | ||
917 | rcu_read_lock(); | 765 | rcu_read_lock(); |
918 | node = avc_insert(ssid, tsid, tclass, avd); | 766 | node = avc_insert(ssid, tsid, tclass, avd); |
919 | } else { | 767 | } else { |
@@ -935,7 +783,6 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
935 | } | 783 | } |
936 | 784 | ||
937 | rcu_read_unlock(); | 785 | rcu_read_unlock(); |
938 | out: | ||
939 | return rc; | 786 | return rc; |
940 | } | 787 | } |
941 | 788 | ||
@@ -956,7 +803,7 @@ out: | |||
956 | * another -errno upon other errors. | 803 | * another -errno upon other errors. |
957 | */ | 804 | */ |
958 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, | 805 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, |
959 | u32 requested, struct avc_audit_data *auditdata) | 806 | u32 requested, struct common_audit_data *auditdata) |
960 | { | 807 | { |
961 | struct av_decision avd; | 808 | struct av_decision avd; |
962 | int rc; | 809 | int rc; |
@@ -970,3 +817,22 @@ u32 avc_policy_seqno(void) | |||
970 | { | 817 | { |
971 | return avc_cache.latest_notif; | 818 | return avc_cache.latest_notif; |
972 | } | 819 | } |
820 | |||
821 | void avc_disable(void) | ||
822 | { | ||
823 | /* | ||
824 | * If you are looking at this because you have realized that we are | ||
825 | * not destroying the avc_node_cachep it might be easy to fix, but | ||
826 | * I don't know the memory barrier semantics well enough to know. It's | ||
827 | * possible that some other task dereferenced security_ops when | ||
828 | * it still pointed to selinux operations. If that is the case it's | ||
829 | * possible that it is about to use the avc and is about to need the | ||
830 | * avc_node_cachep. I know I could wrap the security.c security_ops call | ||
831 | * in an rcu_lock, but seriously, it's not worth it. Instead I just flush | ||
832 | * the cache and get that memory back. | ||
833 | */ | ||
834 | if (avc_node_cachep) { | ||
835 | avc_flush(); | ||
836 | /* kmem_cache_destroy(avc_node_cachep); */ | ||
837 | } | ||
838 | } | ||
diff --git a/security/selinux/exports.c b/security/selinux/exports.c index c73aeaa008e..90664385dea 100644 --- a/security/selinux/exports.c +++ b/security/selinux/exports.c | |||
@@ -11,55 +11,12 @@ | |||
11 | * it under the terms of the GNU General Public License version 2, | 11 | * it under the terms of the GNU General Public License version 2, |
12 | * as published by the Free Software Foundation. | 12 | * as published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | 14 | #include <linux/module.h> |
17 | #include <linux/selinux.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/ipc.h> | ||
20 | #include <asm/atomic.h> | ||
21 | 15 | ||
22 | #include "security.h" | 16 | #include "security.h" |
23 | #include "objsec.h" | ||
24 | 17 | ||
25 | /* SECMARK reference count */ | 18 | bool selinux_is_enabled(void) |
26 | extern atomic_t selinux_secmark_refcount; | ||
27 | |||
28 | int selinux_string_to_sid(char *str, u32 *sid) | ||
29 | { | ||
30 | if (selinux_enabled) | ||
31 | return security_context_to_sid(str, strlen(str), sid); | ||
32 | else { | ||
33 | *sid = 0; | ||
34 | return 0; | ||
35 | } | ||
36 | } | ||
37 | EXPORT_SYMBOL_GPL(selinux_string_to_sid); | ||
38 | |||
39 | int selinux_secmark_relabel_packet_permission(u32 sid) | ||
40 | { | ||
41 | if (selinux_enabled) { | ||
42 | const struct task_security_struct *__tsec; | ||
43 | u32 tsid; | ||
44 | |||
45 | __tsec = current_security(); | ||
46 | tsid = __tsec->sid; | ||
47 | |||
48 | return avc_has_perm(tsid, sid, SECCLASS_PACKET, | ||
49 | PACKET__RELABELTO, NULL); | ||
50 | } | ||
51 | return 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(selinux_secmark_relabel_packet_permission); | ||
54 | |||
55 | void selinux_secmark_refcount_inc(void) | ||
56 | { | ||
57 | atomic_inc(&selinux_secmark_refcount); | ||
58 | } | ||
59 | EXPORT_SYMBOL_GPL(selinux_secmark_refcount_inc); | ||
60 | |||
61 | void selinux_secmark_refcount_dec(void) | ||
62 | { | 19 | { |
63 | atomic_dec(&selinux_secmark_refcount); | 20 | return selinux_enabled; |
64 | } | 21 | } |
65 | EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec); | 22 | EXPORT_SYMBOL_GPL(selinux_is_enabled); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8d8b69c5664..e276eb46853 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -13,8 +13,8 @@ | |||
13 | * Eric Paris <eparis@redhat.com> | 13 | * Eric Paris <eparis@redhat.com> |
14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
15 | * <dgoeddel@trustedcs.com> | 15 | * <dgoeddel@trustedcs.com> |
16 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 16 | * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P. |
17 | * Paul Moore <paul.moore@hp.com> | 17 | * Paul Moore <paul.moore@hp.com> |
18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. | 18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. |
19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> | 19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> |
20 | * | 20 | * |
@@ -76,6 +76,7 @@ | |||
76 | #include <linux/selinux.h> | 76 | #include <linux/selinux.h> |
77 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
78 | #include <linux/posix-timers.h> | 78 | #include <linux/posix-timers.h> |
79 | #include <linux/syslog.h> | ||
79 | 80 | ||
80 | #include "avc.h" | 81 | #include "avc.h" |
81 | #include "objsec.h" | 82 | #include "objsec.h" |
@@ -86,12 +87,8 @@ | |||
86 | #include "netlabel.h" | 87 | #include "netlabel.h" |
87 | #include "audit.h" | 88 | #include "audit.h" |
88 | 89 | ||
89 | #define XATTR_SELINUX_SUFFIX "selinux" | ||
90 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX | ||
91 | |||
92 | #define NUM_SEL_MNT_OPTS 5 | 90 | #define NUM_SEL_MNT_OPTS 5 |
93 | 91 | ||
94 | extern unsigned int policydb_loaded_version; | ||
95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 92 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
96 | extern struct security_operations *security_ops; | 93 | extern struct security_operations *security_ops; |
97 | 94 | ||
@@ -126,18 +123,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
126 | int selinux_enabled = 1; | 123 | int selinux_enabled = 1; |
127 | #endif | 124 | #endif |
128 | 125 | ||
129 | |||
130 | /* | ||
131 | * Minimal support for a secondary security module, | ||
132 | * just to allow the use of the capability module. | ||
133 | */ | ||
134 | static struct security_operations *secondary_ops; | ||
135 | |||
136 | /* Lists of inode and superblock security structures initialized | ||
137 | before the policy was loaded. */ | ||
138 | static LIST_HEAD(superblock_security_head); | ||
139 | static DEFINE_SPINLOCK(sb_security_lock); | ||
140 | |||
141 | static struct kmem_cache *sel_inode_cache; | 126 | static struct kmem_cache *sel_inode_cache; |
142 | 127 | ||
143 | /** | 128 | /** |
@@ -200,7 +185,7 @@ static inline u32 task_sid(const struct task_struct *task) | |||
200 | */ | 185 | */ |
201 | static inline u32 current_sid(void) | 186 | static inline u32 current_sid(void) |
202 | { | 187 | { |
203 | const struct task_security_struct *tsec = current_cred()->security; | 188 | const struct task_security_struct *tsec = current_security(); |
204 | 189 | ||
205 | return tsec->sid; | 190 | return tsec->sid; |
206 | } | 191 | } |
@@ -273,7 +258,6 @@ static int superblock_alloc_security(struct super_block *sb) | |||
273 | return -ENOMEM; | 258 | return -ENOMEM; |
274 | 259 | ||
275 | mutex_init(&sbsec->lock); | 260 | mutex_init(&sbsec->lock); |
276 | INIT_LIST_HEAD(&sbsec->list); | ||
277 | INIT_LIST_HEAD(&sbsec->isec_head); | 261 | INIT_LIST_HEAD(&sbsec->isec_head); |
278 | spin_lock_init(&sbsec->isec_lock); | 262 | spin_lock_init(&sbsec->isec_lock); |
279 | sbsec->sb = sb; | 263 | sbsec->sb = sb; |
@@ -288,49 +272,17 @@ static int superblock_alloc_security(struct super_block *sb) | |||
288 | static void superblock_free_security(struct super_block *sb) | 272 | static void superblock_free_security(struct super_block *sb) |
289 | { | 273 | { |
290 | struct superblock_security_struct *sbsec = sb->s_security; | 274 | struct superblock_security_struct *sbsec = sb->s_security; |
291 | |||
292 | spin_lock(&sb_security_lock); | ||
293 | if (!list_empty(&sbsec->list)) | ||
294 | list_del_init(&sbsec->list); | ||
295 | spin_unlock(&sb_security_lock); | ||
296 | |||
297 | sb->s_security = NULL; | 275 | sb->s_security = NULL; |
298 | kfree(sbsec); | 276 | kfree(sbsec); |
299 | } | 277 | } |
300 | 278 | ||
301 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | ||
302 | { | ||
303 | struct sk_security_struct *ssec; | ||
304 | |||
305 | ssec = kzalloc(sizeof(*ssec), priority); | ||
306 | if (!ssec) | ||
307 | return -ENOMEM; | ||
308 | |||
309 | ssec->peer_sid = SECINITSID_UNLABELED; | ||
310 | ssec->sid = SECINITSID_UNLABELED; | ||
311 | sk->sk_security = ssec; | ||
312 | |||
313 | selinux_netlbl_sk_security_reset(ssec); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static void sk_free_security(struct sock *sk) | ||
319 | { | ||
320 | struct sk_security_struct *ssec = sk->sk_security; | ||
321 | |||
322 | sk->sk_security = NULL; | ||
323 | selinux_netlbl_sk_security_free(ssec); | ||
324 | kfree(ssec); | ||
325 | } | ||
326 | |||
327 | /* The security server must be initialized before | 279 | /* The security server must be initialized before |
328 | any labeling or access decisions can be provided. */ | 280 | any labeling or access decisions can be provided. */ |
329 | extern int ss_initialized; | 281 | extern int ss_initialized; |
330 | 282 | ||
331 | /* The file system's label must be initialized prior to use. */ | 283 | /* The file system's label must be initialized prior to use. */ |
332 | 284 | ||
333 | static char *labeling_behaviors[6] = { | 285 | static const char *labeling_behaviors[6] = { |
334 | "uses xattr", | 286 | "uses xattr", |
335 | "uses transition SIDs", | 287 | "uses transition SIDs", |
336 | "uses task SIDs", | 288 | "uses task SIDs", |
@@ -448,6 +400,10 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 400 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
449 | sbsec->flags &= ~SE_SBLABELSUPP; | 401 | sbsec->flags &= ~SE_SBLABELSUPP; |
450 | 402 | ||
403 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ | ||
404 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) | ||
405 | sbsec->flags |= SE_SBLABELSUPP; | ||
406 | |||
451 | /* Initialize the root inode. */ | 407 | /* Initialize the root inode. */ |
452 | rc = inode_doinit_with_dentry(root_inode, root); | 408 | rc = inode_doinit_with_dentry(root_inode, root); |
453 | 409 | ||
@@ -615,10 +571,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
615 | /* Defer initialization until selinux_complete_init, | 571 | /* Defer initialization until selinux_complete_init, |
616 | after the initial policy is loaded and the security | 572 | after the initial policy is loaded and the security |
617 | server is ready to handle calls. */ | 573 | server is ready to handle calls. */ |
618 | spin_lock(&sb_security_lock); | ||
619 | if (list_empty(&sbsec->list)) | ||
620 | list_add(&sbsec->list, &superblock_security_head); | ||
621 | spin_unlock(&sb_security_lock); | ||
622 | goto out; | 574 | goto out; |
623 | } | 575 | } |
624 | rc = -EINVAL; | 576 | rc = -EINVAL; |
@@ -809,16 +761,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
809 | 761 | ||
810 | /* | 762 | /* |
811 | * if the parent was able to be mounted it clearly had no special lsm | 763 | * if the parent was able to be mounted it clearly had no special lsm |
812 | * mount options. thus we can safely put this sb on the list and deal | 764 | * mount options. thus we can safely deal with this superblock later |
813 | * with it later | ||
814 | */ | 765 | */ |
815 | if (!ss_initialized) { | 766 | if (!ss_initialized) |
816 | spin_lock(&sb_security_lock); | ||
817 | if (list_empty(&newsbsec->list)) | ||
818 | list_add(&newsbsec->list, &superblock_security_head); | ||
819 | spin_unlock(&sb_security_lock); | ||
820 | return; | 767 | return; |
821 | } | ||
822 | 768 | ||
823 | /* how can we clone if the old one wasn't set up?? */ | 769 | /* how can we clone if the old one wasn't set up?? */ |
824 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 770 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
@@ -1479,14 +1425,14 @@ static int task_has_capability(struct task_struct *tsk, | |||
1479 | const struct cred *cred, | 1425 | const struct cred *cred, |
1480 | int cap, int audit) | 1426 | int cap, int audit) |
1481 | { | 1427 | { |
1482 | struct avc_audit_data ad; | 1428 | struct common_audit_data ad; |
1483 | struct av_decision avd; | 1429 | struct av_decision avd; |
1484 | u16 sclass; | 1430 | u16 sclass; |
1485 | u32 sid = cred_sid(cred); | 1431 | u32 sid = cred_sid(cred); |
1486 | u32 av = CAP_TO_MASK(cap); | 1432 | u32 av = CAP_TO_MASK(cap); |
1487 | int rc; | 1433 | int rc; |
1488 | 1434 | ||
1489 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 1435 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
1490 | ad.tsk = tsk; | 1436 | ad.tsk = tsk; |
1491 | ad.u.cap = cap; | 1437 | ad.u.cap = cap; |
1492 | 1438 | ||
@@ -1525,12 +1471,14 @@ static int task_has_system(struct task_struct *tsk, | |||
1525 | static int inode_has_perm(const struct cred *cred, | 1471 | static int inode_has_perm(const struct cred *cred, |
1526 | struct inode *inode, | 1472 | struct inode *inode, |
1527 | u32 perms, | 1473 | u32 perms, |
1528 | struct avc_audit_data *adp) | 1474 | struct common_audit_data *adp) |
1529 | { | 1475 | { |
1530 | struct inode_security_struct *isec; | 1476 | struct inode_security_struct *isec; |
1531 | struct avc_audit_data ad; | 1477 | struct common_audit_data ad; |
1532 | u32 sid; | 1478 | u32 sid; |
1533 | 1479 | ||
1480 | validate_creds(cred); | ||
1481 | |||
1534 | if (unlikely(IS_PRIVATE(inode))) | 1482 | if (unlikely(IS_PRIVATE(inode))) |
1535 | return 0; | 1483 | return 0; |
1536 | 1484 | ||
@@ -1539,7 +1487,7 @@ static int inode_has_perm(const struct cred *cred, | |||
1539 | 1487 | ||
1540 | if (!adp) { | 1488 | if (!adp) { |
1541 | adp = &ad; | 1489 | adp = &ad; |
1542 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1490 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1543 | ad.u.fs.inode = inode; | 1491 | ad.u.fs.inode = inode; |
1544 | } | 1492 | } |
1545 | 1493 | ||
@@ -1555,9 +1503,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1555 | u32 av) | 1503 | u32 av) |
1556 | { | 1504 | { |
1557 | struct inode *inode = dentry->d_inode; | 1505 | struct inode *inode = dentry->d_inode; |
1558 | struct avc_audit_data ad; | 1506 | struct common_audit_data ad; |
1559 | 1507 | ||
1560 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1508 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1561 | ad.u.fs.path.mnt = mnt; | 1509 | ad.u.fs.path.mnt = mnt; |
1562 | ad.u.fs.path.dentry = dentry; | 1510 | ad.u.fs.path.dentry = dentry; |
1563 | return inode_has_perm(cred, inode, av, &ad); | 1511 | return inode_has_perm(cred, inode, av, &ad); |
@@ -1577,11 +1525,11 @@ static int file_has_perm(const struct cred *cred, | |||
1577 | { | 1525 | { |
1578 | struct file_security_struct *fsec = file->f_security; | 1526 | struct file_security_struct *fsec = file->f_security; |
1579 | struct inode *inode = file->f_path.dentry->d_inode; | 1527 | struct inode *inode = file->f_path.dentry->d_inode; |
1580 | struct avc_audit_data ad; | 1528 | struct common_audit_data ad; |
1581 | u32 sid = cred_sid(cred); | 1529 | u32 sid = cred_sid(cred); |
1582 | int rc; | 1530 | int rc; |
1583 | 1531 | ||
1584 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1532 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1585 | ad.u.fs.path = file->f_path; | 1533 | ad.u.fs.path = file->f_path; |
1586 | 1534 | ||
1587 | if (sid != fsec->sid) { | 1535 | if (sid != fsec->sid) { |
@@ -1607,12 +1555,11 @@ static int may_create(struct inode *dir, | |||
1607 | struct dentry *dentry, | 1555 | struct dentry *dentry, |
1608 | u16 tclass) | 1556 | u16 tclass) |
1609 | { | 1557 | { |
1610 | const struct cred *cred = current_cred(); | 1558 | const struct task_security_struct *tsec = current_security(); |
1611 | const struct task_security_struct *tsec = cred->security; | ||
1612 | struct inode_security_struct *dsec; | 1559 | struct inode_security_struct *dsec; |
1613 | struct superblock_security_struct *sbsec; | 1560 | struct superblock_security_struct *sbsec; |
1614 | u32 sid, newsid; | 1561 | u32 sid, newsid; |
1615 | struct avc_audit_data ad; | 1562 | struct common_audit_data ad; |
1616 | int rc; | 1563 | int rc; |
1617 | 1564 | ||
1618 | dsec = dir->i_security; | 1565 | dsec = dir->i_security; |
@@ -1621,7 +1568,7 @@ static int may_create(struct inode *dir, | |||
1621 | sid = tsec->sid; | 1568 | sid = tsec->sid; |
1622 | newsid = tsec->create_sid; | 1569 | newsid = tsec->create_sid; |
1623 | 1570 | ||
1624 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1571 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1625 | ad.u.fs.path.dentry = dentry; | 1572 | ad.u.fs.path.dentry = dentry; |
1626 | 1573 | ||
1627 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1574 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
@@ -1665,7 +1612,7 @@ static int may_link(struct inode *dir, | |||
1665 | 1612 | ||
1666 | { | 1613 | { |
1667 | struct inode_security_struct *dsec, *isec; | 1614 | struct inode_security_struct *dsec, *isec; |
1668 | struct avc_audit_data ad; | 1615 | struct common_audit_data ad; |
1669 | u32 sid = current_sid(); | 1616 | u32 sid = current_sid(); |
1670 | u32 av; | 1617 | u32 av; |
1671 | int rc; | 1618 | int rc; |
@@ -1673,7 +1620,7 @@ static int may_link(struct inode *dir, | |||
1673 | dsec = dir->i_security; | 1620 | dsec = dir->i_security; |
1674 | isec = dentry->d_inode->i_security; | 1621 | isec = dentry->d_inode->i_security; |
1675 | 1622 | ||
1676 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1623 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1677 | ad.u.fs.path.dentry = dentry; | 1624 | ad.u.fs.path.dentry = dentry; |
1678 | 1625 | ||
1679 | av = DIR__SEARCH; | 1626 | av = DIR__SEARCH; |
@@ -1708,7 +1655,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1708 | struct dentry *new_dentry) | 1655 | struct dentry *new_dentry) |
1709 | { | 1656 | { |
1710 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1657 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1711 | struct avc_audit_data ad; | 1658 | struct common_audit_data ad; |
1712 | u32 sid = current_sid(); | 1659 | u32 sid = current_sid(); |
1713 | u32 av; | 1660 | u32 av; |
1714 | int old_is_dir, new_is_dir; | 1661 | int old_is_dir, new_is_dir; |
@@ -1719,7 +1666,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1719 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1666 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1720 | new_dsec = new_dir->i_security; | 1667 | new_dsec = new_dir->i_security; |
1721 | 1668 | ||
1722 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1669 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1723 | 1670 | ||
1724 | ad.u.fs.path.dentry = old_dentry; | 1671 | ad.u.fs.path.dentry = old_dentry; |
1725 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1672 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
@@ -1761,7 +1708,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1761 | static int superblock_has_perm(const struct cred *cred, | 1708 | static int superblock_has_perm(const struct cred *cred, |
1762 | struct super_block *sb, | 1709 | struct super_block *sb, |
1763 | u32 perms, | 1710 | u32 perms, |
1764 | struct avc_audit_data *ad) | 1711 | struct common_audit_data *ad) |
1765 | { | 1712 | { |
1766 | struct superblock_security_struct *sbsec; | 1713 | struct superblock_security_struct *sbsec; |
1767 | u32 sid = cred_sid(cred); | 1714 | u32 sid = cred_sid(cred); |
@@ -1829,38 +1776,20 @@ static inline u32 open_file_to_av(struct file *file) | |||
1829 | { | 1776 | { |
1830 | u32 av = file_to_av(file); | 1777 | u32 av = file_to_av(file); |
1831 | 1778 | ||
1832 | if (selinux_policycap_openperm) { | 1779 | if (selinux_policycap_openperm) |
1833 | mode_t mode = file->f_path.dentry->d_inode->i_mode; | 1780 | av |= FILE__OPEN; |
1834 | /* | 1781 | |
1835 | * lnk files and socks do not really have an 'open' | ||
1836 | */ | ||
1837 | if (S_ISREG(mode)) | ||
1838 | av |= FILE__OPEN; | ||
1839 | else if (S_ISCHR(mode)) | ||
1840 | av |= CHR_FILE__OPEN; | ||
1841 | else if (S_ISBLK(mode)) | ||
1842 | av |= BLK_FILE__OPEN; | ||
1843 | else if (S_ISFIFO(mode)) | ||
1844 | av |= FIFO_FILE__OPEN; | ||
1845 | else if (S_ISDIR(mode)) | ||
1846 | av |= DIR__OPEN; | ||
1847 | else if (S_ISSOCK(mode)) | ||
1848 | av |= SOCK_FILE__OPEN; | ||
1849 | else | ||
1850 | printk(KERN_ERR "SELinux: WARNING: inside %s with " | ||
1851 | "unknown mode:%o\n", __func__, mode); | ||
1852 | } | ||
1853 | return av; | 1782 | return av; |
1854 | } | 1783 | } |
1855 | 1784 | ||
1856 | /* Hook functions begin here. */ | 1785 | /* Hook functions begin here. */ |
1857 | 1786 | ||
1858 | static int selinux_ptrace_may_access(struct task_struct *child, | 1787 | static int selinux_ptrace_access_check(struct task_struct *child, |
1859 | unsigned int mode) | 1788 | unsigned int mode) |
1860 | { | 1789 | { |
1861 | int rc; | 1790 | int rc; |
1862 | 1791 | ||
1863 | rc = cap_ptrace_may_access(child, mode); | 1792 | rc = cap_ptrace_access_check(child, mode); |
1864 | if (rc) | 1793 | if (rc) |
1865 | return rc; | 1794 | return rc; |
1866 | 1795 | ||
@@ -2048,25 +1977,22 @@ static int selinux_syslog(int type) | |||
2048 | { | 1977 | { |
2049 | int rc; | 1978 | int rc; |
2050 | 1979 | ||
2051 | rc = cap_syslog(type); | ||
2052 | if (rc) | ||
2053 | return rc; | ||
2054 | |||
2055 | switch (type) { | 1980 | switch (type) { |
2056 | case 3: /* Read last kernel messages */ | 1981 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
2057 | case 10: /* Return size of the log buffer */ | 1982 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
2058 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 1983 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); |
2059 | break; | 1984 | break; |
2060 | case 6: /* Disable logging to console */ | 1985 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
2061 | case 7: /* Enable logging to console */ | 1986 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
2062 | case 8: /* Set level of messages printed to console */ | 1987 | /* Set level of messages printed to console */ |
1988 | case SYSLOG_ACTION_CONSOLE_LEVEL: | ||
2063 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 1989 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); |
2064 | break; | 1990 | break; |
2065 | case 0: /* Close log */ | 1991 | case SYSLOG_ACTION_CLOSE: /* Close log */ |
2066 | case 1: /* Open log */ | 1992 | case SYSLOG_ACTION_OPEN: /* Open log */ |
2067 | case 2: /* Read from log */ | 1993 | case SYSLOG_ACTION_READ: /* Read from log */ |
2068 | case 4: /* Read/clear last kernel messages */ | 1994 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ |
2069 | case 5: /* Clear ring buffer */ | 1995 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ |
2070 | default: | 1996 | default: |
2071 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); | 1997 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); |
2072 | break; | 1998 | break; |
@@ -2101,7 +2027,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2101 | const struct task_security_struct *old_tsec; | 2027 | const struct task_security_struct *old_tsec; |
2102 | struct task_security_struct *new_tsec; | 2028 | struct task_security_struct *new_tsec; |
2103 | struct inode_security_struct *isec; | 2029 | struct inode_security_struct *isec; |
2104 | struct avc_audit_data ad; | 2030 | struct common_audit_data ad; |
2105 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 2031 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
2106 | int rc; | 2032 | int rc; |
2107 | 2033 | ||
@@ -2139,7 +2065,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2139 | return rc; | 2065 | return rc; |
2140 | } | 2066 | } |
2141 | 2067 | ||
2142 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2068 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2143 | ad.u.fs.path = bprm->file->f_path; | 2069 | ad.u.fs.path = bprm->file->f_path; |
2144 | 2070 | ||
2145 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2071 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
@@ -2205,8 +2131,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2205 | 2131 | ||
2206 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2132 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
2207 | { | 2133 | { |
2208 | const struct cred *cred = current_cred(); | 2134 | const struct task_security_struct *tsec = current_security(); |
2209 | const struct task_security_struct *tsec = cred->security; | ||
2210 | u32 sid, osid; | 2135 | u32 sid, osid; |
2211 | int atsecure = 0; | 2136 | int atsecure = 0; |
2212 | 2137 | ||
@@ -2232,7 +2157,7 @@ extern struct dentry *selinux_null; | |||
2232 | static inline void flush_unauthorized_files(const struct cred *cred, | 2157 | static inline void flush_unauthorized_files(const struct cred *cred, |
2233 | struct files_struct *files) | 2158 | struct files_struct *files) |
2234 | { | 2159 | { |
2235 | struct avc_audit_data ad; | 2160 | struct common_audit_data ad; |
2236 | struct file *file, *devnull = NULL; | 2161 | struct file *file, *devnull = NULL; |
2237 | struct tty_struct *tty; | 2162 | struct tty_struct *tty; |
2238 | struct fdtable *fdt; | 2163 | struct fdtable *fdt; |
@@ -2241,8 +2166,9 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2241 | 2166 | ||
2242 | tty = get_current_tty(); | 2167 | tty = get_current_tty(); |
2243 | if (tty) { | 2168 | if (tty) { |
2244 | file_list_lock(); | 2169 | spin_lock(&tty_files_lock); |
2245 | if (!list_empty(&tty->tty_files)) { | 2170 | if (!list_empty(&tty->tty_files)) { |
2171 | struct tty_file_private *file_priv; | ||
2246 | struct inode *inode; | 2172 | struct inode *inode; |
2247 | 2173 | ||
2248 | /* Revalidate access to controlling tty. | 2174 | /* Revalidate access to controlling tty. |
@@ -2250,14 +2176,16 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2250 | than using file_has_perm, as this particular open | 2176 | than using file_has_perm, as this particular open |
2251 | file may belong to another process and we are only | 2177 | file may belong to another process and we are only |
2252 | interested in the inode-based check here. */ | 2178 | interested in the inode-based check here. */ |
2253 | file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); | 2179 | file_priv = list_first_entry(&tty->tty_files, |
2180 | struct tty_file_private, list); | ||
2181 | file = file_priv->file; | ||
2254 | inode = file->f_path.dentry->d_inode; | 2182 | inode = file->f_path.dentry->d_inode; |
2255 | if (inode_has_perm(cred, inode, | 2183 | if (inode_has_perm(cred, inode, |
2256 | FILE__READ | FILE__WRITE, NULL)) { | 2184 | FILE__READ | FILE__WRITE, NULL)) { |
2257 | drop_tty = 1; | 2185 | drop_tty = 1; |
2258 | } | 2186 | } |
2259 | } | 2187 | } |
2260 | file_list_unlock(); | 2188 | spin_unlock(&tty_files_lock); |
2261 | tty_kref_put(tty); | 2189 | tty_kref_put(tty); |
2262 | } | 2190 | } |
2263 | /* Reset controlling tty. */ | 2191 | /* Reset controlling tty. */ |
@@ -2266,7 +2194,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2266 | 2194 | ||
2267 | /* Revalidate access to inherited open files. */ | 2195 | /* Revalidate access to inherited open files. */ |
2268 | 2196 | ||
2269 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2197 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2270 | 2198 | ||
2271 | spin_lock(&files->file_lock); | 2199 | spin_lock(&files->file_lock); |
2272 | for (;;) { | 2200 | for (;;) { |
@@ -2355,12 +2283,15 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
2355 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | 2283 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, |
2356 | PROCESS__RLIMITINH, NULL); | 2284 | PROCESS__RLIMITINH, NULL); |
2357 | if (rc) { | 2285 | if (rc) { |
2286 | /* protect against do_prlimit() */ | ||
2287 | task_lock(current); | ||
2358 | for (i = 0; i < RLIM_NLIMITS; i++) { | 2288 | for (i = 0; i < RLIM_NLIMITS; i++) { |
2359 | rlim = current->signal->rlim + i; | 2289 | rlim = current->signal->rlim + i; |
2360 | initrlim = init_task.signal->rlim + i; | 2290 | initrlim = init_task.signal->rlim + i; |
2361 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2291 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2362 | } | 2292 | } |
2363 | update_rlimit_cpu(rlim->rlim_cur); | 2293 | task_unlock(current); |
2294 | update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); | ||
2364 | } | 2295 | } |
2365 | } | 2296 | } |
2366 | 2297 | ||
@@ -2405,7 +2336,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) | |||
2405 | /* Wake up the parent if it is waiting so that it can recheck | 2336 | /* Wake up the parent if it is waiting so that it can recheck |
2406 | * wait permission to the new task SID. */ | 2337 | * wait permission to the new task SID. */ |
2407 | read_lock(&tasklist_lock); | 2338 | read_lock(&tasklist_lock); |
2408 | wake_up_interruptible(¤t->real_parent->signal->wait_chldexit); | 2339 | __wake_up_parent(current, current->real_parent); |
2409 | read_unlock(&tasklist_lock); | 2340 | read_unlock(&tasklist_lock); |
2410 | } | 2341 | } |
2411 | 2342 | ||
@@ -2515,7 +2446,7 @@ out: | |||
2515 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2446 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2516 | { | 2447 | { |
2517 | const struct cred *cred = current_cred(); | 2448 | const struct cred *cred = current_cred(); |
2518 | struct avc_audit_data ad; | 2449 | struct common_audit_data ad; |
2519 | int rc; | 2450 | int rc; |
2520 | 2451 | ||
2521 | rc = superblock_doinit(sb, data); | 2452 | rc = superblock_doinit(sb, data); |
@@ -2526,7 +2457,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2526 | if (flags & MS_KERNMOUNT) | 2457 | if (flags & MS_KERNMOUNT) |
2527 | return 0; | 2458 | return 0; |
2528 | 2459 | ||
2529 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2460 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2530 | ad.u.fs.path.dentry = sb->s_root; | 2461 | ad.u.fs.path.dentry = sb->s_root; |
2531 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2462 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2532 | } | 2463 | } |
@@ -2534,9 +2465,9 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2534 | static int selinux_sb_statfs(struct dentry *dentry) | 2465 | static int selinux_sb_statfs(struct dentry *dentry) |
2535 | { | 2466 | { |
2536 | const struct cred *cred = current_cred(); | 2467 | const struct cred *cred = current_cred(); |
2537 | struct avc_audit_data ad; | 2468 | struct common_audit_data ad; |
2538 | 2469 | ||
2539 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2470 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2540 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2471 | ad.u.fs.path.dentry = dentry->d_sb->s_root; |
2541 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2472 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2542 | } | 2473 | } |
@@ -2581,8 +2512,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2581 | char **name, void **value, | 2512 | char **name, void **value, |
2582 | size_t *len) | 2513 | size_t *len) |
2583 | { | 2514 | { |
2584 | const struct cred *cred = current_cred(); | 2515 | const struct task_security_struct *tsec = current_security(); |
2585 | const struct task_security_struct *tsec = cred->security; | ||
2586 | struct inode_security_struct *dsec; | 2516 | struct inode_security_struct *dsec; |
2587 | struct superblock_security_struct *sbsec; | 2517 | struct superblock_security_struct *sbsec; |
2588 | u32 sid, newsid, clen; | 2518 | u32 sid, newsid, clen; |
@@ -2595,7 +2525,10 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2595 | sid = tsec->sid; | 2525 | sid = tsec->sid; |
2596 | newsid = tsec->create_sid; | 2526 | newsid = tsec->create_sid; |
2597 | 2527 | ||
2598 | if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | 2528 | if ((sbsec->flags & SE_SBINITIALIZED) && |
2529 | (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) | ||
2530 | newsid = sbsec->mntpoint_sid; | ||
2531 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | ||
2599 | rc = security_transition_sid(sid, dsec->sid, | 2532 | rc = security_transition_sid(sid, dsec->sid, |
2600 | inode_mode_to_security_class(inode->i_mode), | 2533 | inode_mode_to_security_class(inode->i_mode), |
2601 | &newsid); | 2534 | &newsid); |
@@ -2698,25 +2631,43 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2698 | static int selinux_inode_permission(struct inode *inode, int mask) | 2631 | static int selinux_inode_permission(struct inode *inode, int mask) |
2699 | { | 2632 | { |
2700 | const struct cred *cred = current_cred(); | 2633 | const struct cred *cred = current_cred(); |
2634 | struct common_audit_data ad; | ||
2635 | u32 perms; | ||
2636 | bool from_access; | ||
2701 | 2637 | ||
2702 | if (!mask) { | 2638 | from_access = mask & MAY_ACCESS; |
2703 | /* No permission to check. Existence test. */ | 2639 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
2640 | |||
2641 | /* No permission to check. Existence test. */ | ||
2642 | if (!mask) | ||
2704 | return 0; | 2643 | return 0; |
2705 | } | ||
2706 | 2644 | ||
2707 | return inode_has_perm(cred, inode, | 2645 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2708 | file_mask_to_av(inode->i_mode, mask), NULL); | 2646 | ad.u.fs.inode = inode; |
2647 | |||
2648 | if (from_access) | ||
2649 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | ||
2650 | |||
2651 | perms = file_mask_to_av(inode->i_mode, mask); | ||
2652 | |||
2653 | return inode_has_perm(cred, inode, perms, &ad); | ||
2709 | } | 2654 | } |
2710 | 2655 | ||
2711 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2656 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
2712 | { | 2657 | { |
2713 | const struct cred *cred = current_cred(); | 2658 | const struct cred *cred = current_cred(); |
2659 | unsigned int ia_valid = iattr->ia_valid; | ||
2660 | |||
2661 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | ||
2662 | if (ia_valid & ATTR_FORCE) { | ||
2663 | ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE | | ||
2664 | ATTR_FORCE); | ||
2665 | if (!ia_valid) | ||
2666 | return 0; | ||
2667 | } | ||
2714 | 2668 | ||
2715 | if (iattr->ia_valid & ATTR_FORCE) | 2669 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
2716 | return 0; | 2670 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2717 | |||
2718 | if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | | ||
2719 | ATTR_ATIME_SET | ATTR_MTIME_SET)) | ||
2720 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2671 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); |
2721 | 2672 | ||
2722 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); | 2673 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); |
@@ -2756,7 +2707,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2756 | struct inode *inode = dentry->d_inode; | 2707 | struct inode *inode = dentry->d_inode; |
2757 | struct inode_security_struct *isec = inode->i_security; | 2708 | struct inode_security_struct *isec = inode->i_security; |
2758 | struct superblock_security_struct *sbsec; | 2709 | struct superblock_security_struct *sbsec; |
2759 | struct avc_audit_data ad; | 2710 | struct common_audit_data ad; |
2760 | u32 newsid, sid = current_sid(); | 2711 | u32 newsid, sid = current_sid(); |
2761 | int rc = 0; | 2712 | int rc = 0; |
2762 | 2713 | ||
@@ -2770,7 +2721,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2770 | if (!is_owner_or_cap(inode)) | 2721 | if (!is_owner_or_cap(inode)) |
2771 | return -EPERM; | 2722 | return -EPERM; |
2772 | 2723 | ||
2773 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2724 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2774 | ad.u.fs.path.dentry = dentry; | 2725 | ad.u.fs.path.dentry = dentry; |
2775 | 2726 | ||
2776 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2727 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
@@ -2915,6 +2866,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2915 | return rc; | 2866 | return rc; |
2916 | 2867 | ||
2917 | isec->sid = newsid; | 2868 | isec->sid = newsid; |
2869 | isec->initialized = 1; | ||
2918 | return 0; | 2870 | return 0; |
2919 | } | 2871 | } |
2920 | 2872 | ||
@@ -2939,11 +2891,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2939 | const struct cred *cred = current_cred(); | 2891 | const struct cred *cred = current_cred(); |
2940 | struct inode *inode = file->f_path.dentry->d_inode; | 2892 | struct inode *inode = file->f_path.dentry->d_inode; |
2941 | 2893 | ||
2942 | if (!mask) { | ||
2943 | /* No permission to check. Existence test. */ | ||
2944 | return 0; | ||
2945 | } | ||
2946 | |||
2947 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ | 2894 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
2948 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2895 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
2949 | mask |= MAY_APPEND; | 2896 | mask |= MAY_APPEND; |
@@ -2954,10 +2901,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2954 | 2901 | ||
2955 | static int selinux_file_permission(struct file *file, int mask) | 2902 | static int selinux_file_permission(struct file *file, int mask) |
2956 | { | 2903 | { |
2904 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2905 | struct file_security_struct *fsec = file->f_security; | ||
2906 | struct inode_security_struct *isec = inode->i_security; | ||
2907 | u32 sid = current_sid(); | ||
2908 | |||
2957 | if (!mask) | 2909 | if (!mask) |
2958 | /* No permission to check. Existence test. */ | 2910 | /* No permission to check. Existence test. */ |
2959 | return 0; | 2911 | return 0; |
2960 | 2912 | ||
2913 | if (sid == fsec->sid && fsec->isid == isec->sid && | ||
2914 | fsec->pseqno == avc_policy_seqno()) | ||
2915 | /* No change since dentry_open check. */ | ||
2916 | return 0; | ||
2917 | |||
2961 | return selinux_revalidate_file_permission(file, mask); | 2918 | return selinux_revalidate_file_permission(file, mask); |
2962 | } | 2919 | } |
2963 | 2920 | ||
@@ -2987,13 +2944,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
2987 | return file_has_perm(cred, file, av); | 2944 | return file_has_perm(cred, file, av); |
2988 | } | 2945 | } |
2989 | 2946 | ||
2947 | static int default_noexec; | ||
2948 | |||
2990 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 2949 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
2991 | { | 2950 | { |
2992 | const struct cred *cred = current_cred(); | 2951 | const struct cred *cred = current_cred(); |
2993 | int rc = 0; | 2952 | int rc = 0; |
2994 | 2953 | ||
2995 | #ifndef CONFIG_PPC32 | 2954 | if (default_noexec && |
2996 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 2955 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
2997 | /* | 2956 | /* |
2998 | * We are making executable an anonymous mapping or a | 2957 | * We are making executable an anonymous mapping or a |
2999 | * private file mapping that will also be writable. | 2958 | * private file mapping that will also be writable. |
@@ -3003,7 +2962,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3003 | if (rc) | 2962 | if (rc) |
3004 | goto error; | 2963 | goto error; |
3005 | } | 2964 | } |
3006 | #endif | ||
3007 | 2965 | ||
3008 | if (file) { | 2966 | if (file) { |
3009 | /* read access is always possible with a mapping */ | 2967 | /* read access is always possible with a mapping */ |
@@ -3064,8 +3022,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3064 | if (selinux_checkreqprot) | 3022 | if (selinux_checkreqprot) |
3065 | prot = reqprot; | 3023 | prot = reqprot; |
3066 | 3024 | ||
3067 | #ifndef CONFIG_PPC32 | 3025 | if (default_noexec && |
3068 | if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3026 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
3069 | int rc = 0; | 3027 | int rc = 0; |
3070 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3028 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3071 | vma->vm_end <= vma->vm_mm->brk) { | 3029 | vma->vm_end <= vma->vm_mm->brk) { |
@@ -3087,7 +3045,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3087 | if (rc) | 3045 | if (rc) |
3088 | return rc; | 3046 | return rc; |
3089 | } | 3047 | } |
3090 | #endif | ||
3091 | 3048 | ||
3092 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3049 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
3093 | } | 3050 | } |
@@ -3220,12 +3177,29 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3220 | } | 3177 | } |
3221 | 3178 | ||
3222 | /* | 3179 | /* |
3180 | * allocate the SELinux part of blank credentials | ||
3181 | */ | ||
3182 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
3183 | { | ||
3184 | struct task_security_struct *tsec; | ||
3185 | |||
3186 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); | ||
3187 | if (!tsec) | ||
3188 | return -ENOMEM; | ||
3189 | |||
3190 | cred->security = tsec; | ||
3191 | return 0; | ||
3192 | } | ||
3193 | |||
3194 | /* | ||
3223 | * detach and free the LSM part of a set of credentials | 3195 | * detach and free the LSM part of a set of credentials |
3224 | */ | 3196 | */ |
3225 | static void selinux_cred_free(struct cred *cred) | 3197 | static void selinux_cred_free(struct cred *cred) |
3226 | { | 3198 | { |
3227 | struct task_security_struct *tsec = cred->security; | 3199 | struct task_security_struct *tsec = cred->security; |
3228 | cred->security = NULL; | 3200 | |
3201 | BUG_ON((unsigned long) cred->security < PAGE_SIZE); | ||
3202 | cred->security = (void *) 0x7UL; | ||
3229 | kfree(tsec); | 3203 | kfree(tsec); |
3230 | } | 3204 | } |
3231 | 3205 | ||
@@ -3249,6 +3223,17 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, | |||
3249 | } | 3223 | } |
3250 | 3224 | ||
3251 | /* | 3225 | /* |
3226 | * transfer the SELinux data to a blank set of creds | ||
3227 | */ | ||
3228 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) | ||
3229 | { | ||
3230 | const struct task_security_struct *old_tsec = old->security; | ||
3231 | struct task_security_struct *tsec = new->security; | ||
3232 | |||
3233 | *tsec = *old_tsec; | ||
3234 | } | ||
3235 | |||
3236 | /* | ||
3252 | * set the security data for a kernel service | 3237 | * set the security data for a kernel service |
3253 | * - all the creation contexts are set to unlabelled | 3238 | * - all the creation contexts are set to unlabelled |
3254 | */ | 3239 | */ |
@@ -3289,7 +3274,21 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3289 | 3274 | ||
3290 | if (ret == 0) | 3275 | if (ret == 0) |
3291 | tsec->create_sid = isec->sid; | 3276 | tsec->create_sid = isec->sid; |
3292 | return 0; | 3277 | return ret; |
3278 | } | ||
3279 | |||
3280 | static int selinux_kernel_module_request(char *kmod_name) | ||
3281 | { | ||
3282 | u32 sid; | ||
3283 | struct common_audit_data ad; | ||
3284 | |||
3285 | sid = task_sid(current); | ||
3286 | |||
3287 | COMMON_AUDIT_DATA_INIT(&ad, KMOD); | ||
3288 | ad.u.kmod_name = kmod_name; | ||
3289 | |||
3290 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | ||
3291 | SYSTEM__MODULE_REQUEST, &ad); | ||
3293 | } | 3292 | } |
3294 | 3293 | ||
3295 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3294 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
@@ -3339,25 +3338,26 @@ static int selinux_task_getioprio(struct task_struct *p) | |||
3339 | return current_has_perm(p, PROCESS__GETSCHED); | 3338 | return current_has_perm(p, PROCESS__GETSCHED); |
3340 | } | 3339 | } |
3341 | 3340 | ||
3342 | static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) | 3341 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
3342 | struct rlimit *new_rlim) | ||
3343 | { | 3343 | { |
3344 | struct rlimit *old_rlim = current->signal->rlim + resource; | 3344 | struct rlimit *old_rlim = p->signal->rlim + resource; |
3345 | 3345 | ||
3346 | /* Control the ability to change the hard limit (whether | 3346 | /* Control the ability to change the hard limit (whether |
3347 | lowering or raising it), so that the hard limit can | 3347 | lowering or raising it), so that the hard limit can |
3348 | later be used as a safe reset point for the soft limit | 3348 | later be used as a safe reset point for the soft limit |
3349 | upon context transitions. See selinux_bprm_committing_creds. */ | 3349 | upon context transitions. See selinux_bprm_committing_creds. */ |
3350 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3350 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3351 | return current_has_perm(current, PROCESS__SETRLIMIT); | 3351 | return current_has_perm(p, PROCESS__SETRLIMIT); |
3352 | 3352 | ||
3353 | return 0; | 3353 | return 0; |
3354 | } | 3354 | } |
3355 | 3355 | ||
3356 | static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp) | 3356 | static int selinux_task_setscheduler(struct task_struct *p) |
3357 | { | 3357 | { |
3358 | int rc; | 3358 | int rc; |
3359 | 3359 | ||
3360 | rc = cap_task_setscheduler(p, policy, lp); | 3360 | rc = cap_task_setscheduler(p); |
3361 | if (rc) | 3361 | if (rc) |
3362 | return rc; | 3362 | return rc; |
3363 | 3363 | ||
@@ -3409,7 +3409,7 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
3409 | 3409 | ||
3410 | /* Returns error only if unable to parse addresses */ | 3410 | /* Returns error only if unable to parse addresses */ |
3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
3412 | struct avc_audit_data *ad, u8 *proto) | 3412 | struct common_audit_data *ad, u8 *proto) |
3413 | { | 3413 | { |
3414 | int offset, ihlen, ret = -EINVAL; | 3414 | int offset, ihlen, ret = -EINVAL; |
3415 | struct iphdr _iph, *ih; | 3415 | struct iphdr _iph, *ih; |
@@ -3490,7 +3490,7 @@ out: | |||
3490 | 3490 | ||
3491 | /* Returns error only if unable to parse addresses */ | 3491 | /* Returns error only if unable to parse addresses */ |
3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
3493 | struct avc_audit_data *ad, u8 *proto) | 3493 | struct common_audit_data *ad, u8 *proto) |
3494 | { | 3494 | { |
3495 | u8 nexthdr; | 3495 | u8 nexthdr; |
3496 | int ret = -EINVAL, offset; | 3496 | int ret = -EINVAL, offset; |
@@ -3561,7 +3561,7 @@ out: | |||
3561 | 3561 | ||
3562 | #endif /* IPV6 */ | 3562 | #endif /* IPV6 */ |
3563 | 3563 | ||
3564 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3564 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, |
3565 | char **_addrp, int src, u8 *proto) | 3565 | char **_addrp, int src, u8 *proto) |
3566 | { | 3566 | { |
3567 | char *addrp; | 3567 | char *addrp; |
@@ -3639,71 +3639,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3639 | } | 3639 | } |
3640 | 3640 | ||
3641 | /* socket security operations */ | 3641 | /* socket security operations */ |
3642 | static int socket_has_perm(struct task_struct *task, struct socket *sock, | 3642 | |
3643 | u32 perms) | 3643 | static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) |
3644 | { | 3644 | { |
3645 | struct inode_security_struct *isec; | 3645 | return tsec->sockcreate_sid ? : tsec->sid; |
3646 | struct avc_audit_data ad; | 3646 | } |
3647 | u32 sid; | ||
3648 | int err = 0; | ||
3649 | 3647 | ||
3650 | isec = SOCK_INODE(sock)->i_security; | 3648 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
3649 | { | ||
3650 | struct sk_security_struct *sksec = sk->sk_security; | ||
3651 | struct common_audit_data ad; | ||
3652 | u32 tsid = task_sid(task); | ||
3651 | 3653 | ||
3652 | if (isec->sid == SECINITSID_KERNEL) | 3654 | if (sksec->sid == SECINITSID_KERNEL) |
3653 | goto out; | 3655 | return 0; |
3654 | sid = task_sid(task); | ||
3655 | 3656 | ||
3656 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3657 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3657 | ad.u.net.sk = sock->sk; | 3658 | ad.u.net.sk = sk; |
3658 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | ||
3659 | 3659 | ||
3660 | out: | 3660 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
3661 | return err; | ||
3662 | } | 3661 | } |
3663 | 3662 | ||
3664 | static int selinux_socket_create(int family, int type, | 3663 | static int selinux_socket_create(int family, int type, |
3665 | int protocol, int kern) | 3664 | int protocol, int kern) |
3666 | { | 3665 | { |
3667 | const struct cred *cred = current_cred(); | 3666 | const struct task_security_struct *tsec = current_security(); |
3668 | const struct task_security_struct *tsec = cred->security; | 3667 | u32 newsid; |
3669 | u32 sid, newsid; | ||
3670 | u16 secclass; | 3668 | u16 secclass; |
3671 | int err = 0; | ||
3672 | 3669 | ||
3673 | if (kern) | 3670 | if (kern) |
3674 | goto out; | 3671 | return 0; |
3675 | |||
3676 | sid = tsec->sid; | ||
3677 | newsid = tsec->sockcreate_sid ?: sid; | ||
3678 | 3672 | ||
3673 | newsid = socket_sockcreate_sid(tsec); | ||
3679 | secclass = socket_type_to_security_class(family, type, protocol); | 3674 | secclass = socket_type_to_security_class(family, type, protocol); |
3680 | err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); | 3675 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
3681 | |||
3682 | out: | ||
3683 | return err; | ||
3684 | } | 3676 | } |
3685 | 3677 | ||
3686 | static int selinux_socket_post_create(struct socket *sock, int family, | 3678 | static int selinux_socket_post_create(struct socket *sock, int family, |
3687 | int type, int protocol, int kern) | 3679 | int type, int protocol, int kern) |
3688 | { | 3680 | { |
3689 | const struct cred *cred = current_cred(); | 3681 | const struct task_security_struct *tsec = current_security(); |
3690 | const struct task_security_struct *tsec = cred->security; | 3682 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
3691 | struct inode_security_struct *isec; | ||
3692 | struct sk_security_struct *sksec; | 3683 | struct sk_security_struct *sksec; |
3693 | u32 sid, newsid; | ||
3694 | int err = 0; | 3684 | int err = 0; |
3695 | 3685 | ||
3696 | sid = tsec->sid; | ||
3697 | newsid = tsec->sockcreate_sid; | ||
3698 | |||
3699 | isec = SOCK_INODE(sock)->i_security; | ||
3700 | |||
3701 | if (kern) | 3686 | if (kern) |
3702 | isec->sid = SECINITSID_KERNEL; | 3687 | isec->sid = SECINITSID_KERNEL; |
3703 | else if (newsid) | ||
3704 | isec->sid = newsid; | ||
3705 | else | 3688 | else |
3706 | isec->sid = sid; | 3689 | isec->sid = socket_sockcreate_sid(tsec); |
3707 | 3690 | ||
3708 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3691 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
3709 | isec->initialized = 1; | 3692 | isec->initialized = 1; |
@@ -3724,10 +3707,11 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
3724 | 3707 | ||
3725 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3708 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3726 | { | 3709 | { |
3710 | struct sock *sk = sock->sk; | ||
3727 | u16 family; | 3711 | u16 family; |
3728 | int err; | 3712 | int err; |
3729 | 3713 | ||
3730 | err = socket_has_perm(current, sock, SOCKET__BIND); | 3714 | err = sock_has_perm(current, sk, SOCKET__BIND); |
3731 | if (err) | 3715 | if (err) |
3732 | goto out; | 3716 | goto out; |
3733 | 3717 | ||
@@ -3736,19 +3720,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3736 | * Multiple address binding for SCTP is not supported yet: we just | 3720 | * Multiple address binding for SCTP is not supported yet: we just |
3737 | * check the first address now. | 3721 | * check the first address now. |
3738 | */ | 3722 | */ |
3739 | family = sock->sk->sk_family; | 3723 | family = sk->sk_family; |
3740 | if (family == PF_INET || family == PF_INET6) { | 3724 | if (family == PF_INET || family == PF_INET6) { |
3741 | char *addrp; | 3725 | char *addrp; |
3742 | struct inode_security_struct *isec; | 3726 | struct sk_security_struct *sksec = sk->sk_security; |
3743 | struct avc_audit_data ad; | 3727 | struct common_audit_data ad; |
3744 | struct sockaddr_in *addr4 = NULL; | 3728 | struct sockaddr_in *addr4 = NULL; |
3745 | struct sockaddr_in6 *addr6 = NULL; | 3729 | struct sockaddr_in6 *addr6 = NULL; |
3746 | unsigned short snum; | 3730 | unsigned short snum; |
3747 | struct sock *sk = sock->sk; | ||
3748 | u32 sid, node_perm; | 3731 | u32 sid, node_perm; |
3749 | 3732 | ||
3750 | isec = SOCK_INODE(sock)->i_security; | ||
3751 | |||
3752 | if (family == PF_INET) { | 3733 | if (family == PF_INET) { |
3753 | addr4 = (struct sockaddr_in *)address; | 3734 | addr4 = (struct sockaddr_in *)address; |
3754 | snum = ntohs(addr4->sin_port); | 3735 | snum = ntohs(addr4->sin_port); |
@@ -3769,18 +3750,18 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3769 | snum, &sid); | 3750 | snum, &sid); |
3770 | if (err) | 3751 | if (err) |
3771 | goto out; | 3752 | goto out; |
3772 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3753 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3773 | ad.u.net.sport = htons(snum); | 3754 | ad.u.net.sport = htons(snum); |
3774 | ad.u.net.family = family; | 3755 | ad.u.net.family = family; |
3775 | err = avc_has_perm(isec->sid, sid, | 3756 | err = avc_has_perm(sksec->sid, sid, |
3776 | isec->sclass, | 3757 | sksec->sclass, |
3777 | SOCKET__NAME_BIND, &ad); | 3758 | SOCKET__NAME_BIND, &ad); |
3778 | if (err) | 3759 | if (err) |
3779 | goto out; | 3760 | goto out; |
3780 | } | 3761 | } |
3781 | } | 3762 | } |
3782 | 3763 | ||
3783 | switch (isec->sclass) { | 3764 | switch (sksec->sclass) { |
3784 | case SECCLASS_TCP_SOCKET: | 3765 | case SECCLASS_TCP_SOCKET: |
3785 | node_perm = TCP_SOCKET__NODE_BIND; | 3766 | node_perm = TCP_SOCKET__NODE_BIND; |
3786 | break; | 3767 | break; |
@@ -3802,7 +3783,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3802 | if (err) | 3783 | if (err) |
3803 | goto out; | 3784 | goto out; |
3804 | 3785 | ||
3805 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3786 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3806 | ad.u.net.sport = htons(snum); | 3787 | ad.u.net.sport = htons(snum); |
3807 | ad.u.net.family = family; | 3788 | ad.u.net.family = family; |
3808 | 3789 | ||
@@ -3811,8 +3792,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3811 | else | 3792 | else |
3812 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3793 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
3813 | 3794 | ||
3814 | err = avc_has_perm(isec->sid, sid, | 3795 | err = avc_has_perm(sksec->sid, sid, |
3815 | isec->sclass, node_perm, &ad); | 3796 | sksec->sclass, node_perm, &ad); |
3816 | if (err) | 3797 | if (err) |
3817 | goto out; | 3798 | goto out; |
3818 | } | 3799 | } |
@@ -3823,20 +3804,19 @@ out: | |||
3823 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3804 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
3824 | { | 3805 | { |
3825 | struct sock *sk = sock->sk; | 3806 | struct sock *sk = sock->sk; |
3826 | struct inode_security_struct *isec; | 3807 | struct sk_security_struct *sksec = sk->sk_security; |
3827 | int err; | 3808 | int err; |
3828 | 3809 | ||
3829 | err = socket_has_perm(current, sock, SOCKET__CONNECT); | 3810 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
3830 | if (err) | 3811 | if (err) |
3831 | return err; | 3812 | return err; |
3832 | 3813 | ||
3833 | /* | 3814 | /* |
3834 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3815 | * If a TCP or DCCP socket, check name_connect permission for the port. |
3835 | */ | 3816 | */ |
3836 | isec = SOCK_INODE(sock)->i_security; | 3817 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3837 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3818 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3838 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3819 | struct common_audit_data ad; |
3839 | struct avc_audit_data ad; | ||
3840 | struct sockaddr_in *addr4 = NULL; | 3820 | struct sockaddr_in *addr4 = NULL; |
3841 | struct sockaddr_in6 *addr6 = NULL; | 3821 | struct sockaddr_in6 *addr6 = NULL; |
3842 | unsigned short snum; | 3822 | unsigned short snum; |
@@ -3858,13 +3838,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3858 | if (err) | 3838 | if (err) |
3859 | goto out; | 3839 | goto out; |
3860 | 3840 | ||
3861 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3841 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3862 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3842 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3863 | 3843 | ||
3864 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3844 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3865 | ad.u.net.dport = htons(snum); | 3845 | ad.u.net.dport = htons(snum); |
3866 | ad.u.net.family = sk->sk_family; | 3846 | ad.u.net.family = sk->sk_family; |
3867 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3847 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
3868 | if (err) | 3848 | if (err) |
3869 | goto out; | 3849 | goto out; |
3870 | } | 3850 | } |
@@ -3877,7 +3857,7 @@ out: | |||
3877 | 3857 | ||
3878 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3858 | static int selinux_socket_listen(struct socket *sock, int backlog) |
3879 | { | 3859 | { |
3880 | return socket_has_perm(current, sock, SOCKET__LISTEN); | 3860 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
3881 | } | 3861 | } |
3882 | 3862 | ||
3883 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3863 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
@@ -3886,7 +3866,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3886 | struct inode_security_struct *isec; | 3866 | struct inode_security_struct *isec; |
3887 | struct inode_security_struct *newisec; | 3867 | struct inode_security_struct *newisec; |
3888 | 3868 | ||
3889 | err = socket_has_perm(current, sock, SOCKET__ACCEPT); | 3869 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
3890 | if (err) | 3870 | if (err) |
3891 | return err; | 3871 | return err; |
3892 | 3872 | ||
@@ -3903,30 +3883,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3903 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3883 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
3904 | int size) | 3884 | int size) |
3905 | { | 3885 | { |
3906 | return socket_has_perm(current, sock, SOCKET__WRITE); | 3886 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
3907 | } | 3887 | } |
3908 | 3888 | ||
3909 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3889 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
3910 | int size, int flags) | 3890 | int size, int flags) |
3911 | { | 3891 | { |
3912 | return socket_has_perm(current, sock, SOCKET__READ); | 3892 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
3913 | } | 3893 | } |
3914 | 3894 | ||
3915 | static int selinux_socket_getsockname(struct socket *sock) | 3895 | static int selinux_socket_getsockname(struct socket *sock) |
3916 | { | 3896 | { |
3917 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3897 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3918 | } | 3898 | } |
3919 | 3899 | ||
3920 | static int selinux_socket_getpeername(struct socket *sock) | 3900 | static int selinux_socket_getpeername(struct socket *sock) |
3921 | { | 3901 | { |
3922 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3902 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3923 | } | 3903 | } |
3924 | 3904 | ||
3925 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3905 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
3926 | { | 3906 | { |
3927 | int err; | 3907 | int err; |
3928 | 3908 | ||
3929 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | 3909 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
3930 | if (err) | 3910 | if (err) |
3931 | return err; | 3911 | return err; |
3932 | 3912 | ||
@@ -3936,73 +3916,63 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
3936 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3916 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
3937 | int optname) | 3917 | int optname) |
3938 | { | 3918 | { |
3939 | return socket_has_perm(current, sock, SOCKET__GETOPT); | 3919 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
3940 | } | 3920 | } |
3941 | 3921 | ||
3942 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3922 | static int selinux_socket_shutdown(struct socket *sock, int how) |
3943 | { | 3923 | { |
3944 | return socket_has_perm(current, sock, SOCKET__SHUTDOWN); | 3924 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
3945 | } | 3925 | } |
3946 | 3926 | ||
3947 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3927 | static int selinux_socket_unix_stream_connect(struct sock *sock, |
3948 | struct socket *other, | 3928 | struct sock *other, |
3949 | struct sock *newsk) | 3929 | struct sock *newsk) |
3950 | { | 3930 | { |
3951 | struct sk_security_struct *ssec; | 3931 | struct sk_security_struct *sksec_sock = sock->sk_security; |
3952 | struct inode_security_struct *isec; | 3932 | struct sk_security_struct *sksec_other = other->sk_security; |
3953 | struct inode_security_struct *other_isec; | 3933 | struct sk_security_struct *sksec_new = newsk->sk_security; |
3954 | struct avc_audit_data ad; | 3934 | struct common_audit_data ad; |
3955 | int err; | 3935 | int err; |
3956 | 3936 | ||
3957 | isec = SOCK_INODE(sock)->i_security; | 3937 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3958 | other_isec = SOCK_INODE(other)->i_security; | 3938 | ad.u.net.sk = other; |
3959 | |||
3960 | AVC_AUDIT_DATA_INIT(&ad, NET); | ||
3961 | ad.u.net.sk = other->sk; | ||
3962 | 3939 | ||
3963 | err = avc_has_perm(isec->sid, other_isec->sid, | 3940 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
3964 | isec->sclass, | 3941 | sksec_other->sclass, |
3965 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 3942 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
3966 | if (err) | 3943 | if (err) |
3967 | return err; | 3944 | return err; |
3968 | 3945 | ||
3969 | /* connecting socket */ | ||
3970 | ssec = sock->sk->sk_security; | ||
3971 | ssec->peer_sid = other_isec->sid; | ||
3972 | |||
3973 | /* server child socket */ | 3946 | /* server child socket */ |
3974 | ssec = newsk->sk_security; | 3947 | sksec_new->peer_sid = sksec_sock->sid; |
3975 | ssec->peer_sid = isec->sid; | 3948 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
3976 | err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); | 3949 | &sksec_new->sid); |
3950 | if (err) | ||
3951 | return err; | ||
3977 | 3952 | ||
3978 | return err; | 3953 | /* connecting socket */ |
3954 | sksec_sock->peer_sid = sksec_new->sid; | ||
3955 | |||
3956 | return 0; | ||
3979 | } | 3957 | } |
3980 | 3958 | ||
3981 | static int selinux_socket_unix_may_send(struct socket *sock, | 3959 | static int selinux_socket_unix_may_send(struct socket *sock, |
3982 | struct socket *other) | 3960 | struct socket *other) |
3983 | { | 3961 | { |
3984 | struct inode_security_struct *isec; | 3962 | struct sk_security_struct *ssec = sock->sk->sk_security; |
3985 | struct inode_security_struct *other_isec; | 3963 | struct sk_security_struct *osec = other->sk->sk_security; |
3986 | struct avc_audit_data ad; | 3964 | struct common_audit_data ad; |
3987 | int err; | ||
3988 | |||
3989 | isec = SOCK_INODE(sock)->i_security; | ||
3990 | other_isec = SOCK_INODE(other)->i_security; | ||
3991 | 3965 | ||
3992 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3966 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3993 | ad.u.net.sk = other->sk; | 3967 | ad.u.net.sk = other->sk; |
3994 | 3968 | ||
3995 | err = avc_has_perm(isec->sid, other_isec->sid, | 3969 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
3996 | isec->sclass, SOCKET__SENDTO, &ad); | 3970 | &ad); |
3997 | if (err) | ||
3998 | return err; | ||
3999 | |||
4000 | return 0; | ||
4001 | } | 3971 | } |
4002 | 3972 | ||
4003 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 3973 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
4004 | u32 peer_sid, | 3974 | u32 peer_sid, |
4005 | struct avc_audit_data *ad) | 3975 | struct common_audit_data *ad) |
4006 | { | 3976 | { |
4007 | int err; | 3977 | int err; |
4008 | u32 if_sid; | 3978 | u32 if_sid; |
@@ -4030,11 +4000,11 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4030 | struct sk_security_struct *sksec = sk->sk_security; | 4000 | struct sk_security_struct *sksec = sk->sk_security; |
4031 | u32 peer_sid; | 4001 | u32 peer_sid; |
4032 | u32 sk_sid = sksec->sid; | 4002 | u32 sk_sid = sksec->sid; |
4033 | struct avc_audit_data ad; | 4003 | struct common_audit_data ad; |
4034 | char *addrp; | 4004 | char *addrp; |
4035 | 4005 | ||
4036 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4006 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4037 | ad.u.net.netif = skb->iif; | 4007 | ad.u.net.netif = skb->skb_iif; |
4038 | ad.u.net.family = family; | 4008 | ad.u.net.family = family; |
4039 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4009 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4040 | if (err) | 4010 | if (err) |
@@ -4071,7 +4041,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4071 | struct sk_security_struct *sksec = sk->sk_security; | 4041 | struct sk_security_struct *sksec = sk->sk_security; |
4072 | u16 family = sk->sk_family; | 4042 | u16 family = sk->sk_family; |
4073 | u32 sk_sid = sksec->sid; | 4043 | u32 sk_sid = sksec->sid; |
4074 | struct avc_audit_data ad; | 4044 | struct common_audit_data ad; |
4075 | char *addrp; | 4045 | char *addrp; |
4076 | u8 secmark_active; | 4046 | u8 secmark_active; |
4077 | u8 peerlbl_active; | 4047 | u8 peerlbl_active; |
@@ -4095,8 +4065,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4095 | if (!secmark_active && !peerlbl_active) | 4065 | if (!secmark_active && !peerlbl_active) |
4096 | return 0; | 4066 | return 0; |
4097 | 4067 | ||
4098 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4068 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4099 | ad.u.net.netif = skb->iif; | 4069 | ad.u.net.netif = skb->skb_iif; |
4100 | ad.u.net.family = family; | 4070 | ad.u.net.family = family; |
4101 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4071 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4102 | if (err) | 4072 | if (err) |
@@ -4108,7 +4078,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4108 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 4078 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); |
4109 | if (err) | 4079 | if (err) |
4110 | return err; | 4080 | return err; |
4111 | err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, | 4081 | err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family, |
4112 | peer_sid, &ad); | 4082 | peer_sid, &ad); |
4113 | if (err) { | 4083 | if (err) { |
4114 | selinux_netlbl_err(skb, err, 0); | 4084 | selinux_netlbl_err(skb, err, 0); |
@@ -4136,26 +4106,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4136 | int err = 0; | 4106 | int err = 0; |
4137 | char *scontext; | 4107 | char *scontext; |
4138 | u32 scontext_len; | 4108 | u32 scontext_len; |
4139 | struct sk_security_struct *ssec; | 4109 | struct sk_security_struct *sksec = sock->sk->sk_security; |
4140 | struct inode_security_struct *isec; | ||
4141 | u32 peer_sid = SECSID_NULL; | 4110 | u32 peer_sid = SECSID_NULL; |
4142 | 4111 | ||
4143 | isec = SOCK_INODE(sock)->i_security; | 4112 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4144 | 4113 | sksec->sclass == SECCLASS_TCP_SOCKET) | |
4145 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4114 | peer_sid = sksec->peer_sid; |
4146 | isec->sclass == SECCLASS_TCP_SOCKET) { | 4115 | if (peer_sid == SECSID_NULL) |
4147 | ssec = sock->sk->sk_security; | 4116 | return -ENOPROTOOPT; |
4148 | peer_sid = ssec->peer_sid; | ||
4149 | } | ||
4150 | if (peer_sid == SECSID_NULL) { | ||
4151 | err = -ENOPROTOOPT; | ||
4152 | goto out; | ||
4153 | } | ||
4154 | 4117 | ||
4155 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4118 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
4156 | |||
4157 | if (err) | 4119 | if (err) |
4158 | goto out; | 4120 | return err; |
4159 | 4121 | ||
4160 | if (scontext_len > len) { | 4122 | if (scontext_len > len) { |
4161 | err = -ERANGE; | 4123 | err = -ERANGE; |
@@ -4168,9 +4130,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4168 | out_len: | 4130 | out_len: |
4169 | if (put_user(scontext_len, optlen)) | 4131 | if (put_user(scontext_len, optlen)) |
4170 | err = -EFAULT; | 4132 | err = -EFAULT; |
4171 | |||
4172 | kfree(scontext); | 4133 | kfree(scontext); |
4173 | out: | ||
4174 | return err; | 4134 | return err; |
4175 | } | 4135 | } |
4176 | 4136 | ||
@@ -4202,24 +4162,39 @@ out: | |||
4202 | 4162 | ||
4203 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4163 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
4204 | { | 4164 | { |
4205 | return sk_alloc_security(sk, family, priority); | 4165 | struct sk_security_struct *sksec; |
4166 | |||
4167 | sksec = kzalloc(sizeof(*sksec), priority); | ||
4168 | if (!sksec) | ||
4169 | return -ENOMEM; | ||
4170 | |||
4171 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
4172 | sksec->sid = SECINITSID_UNLABELED; | ||
4173 | selinux_netlbl_sk_security_reset(sksec); | ||
4174 | sk->sk_security = sksec; | ||
4175 | |||
4176 | return 0; | ||
4206 | } | 4177 | } |
4207 | 4178 | ||
4208 | static void selinux_sk_free_security(struct sock *sk) | 4179 | static void selinux_sk_free_security(struct sock *sk) |
4209 | { | 4180 | { |
4210 | sk_free_security(sk); | 4181 | struct sk_security_struct *sksec = sk->sk_security; |
4182 | |||
4183 | sk->sk_security = NULL; | ||
4184 | selinux_netlbl_sk_security_free(sksec); | ||
4185 | kfree(sksec); | ||
4211 | } | 4186 | } |
4212 | 4187 | ||
4213 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4188 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
4214 | { | 4189 | { |
4215 | struct sk_security_struct *ssec = sk->sk_security; | 4190 | struct sk_security_struct *sksec = sk->sk_security; |
4216 | struct sk_security_struct *newssec = newsk->sk_security; | 4191 | struct sk_security_struct *newsksec = newsk->sk_security; |
4217 | 4192 | ||
4218 | newssec->sid = ssec->sid; | 4193 | newsksec->sid = sksec->sid; |
4219 | newssec->peer_sid = ssec->peer_sid; | 4194 | newsksec->peer_sid = sksec->peer_sid; |
4220 | newssec->sclass = ssec->sclass; | 4195 | newsksec->sclass = sksec->sclass; |
4221 | 4196 | ||
4222 | selinux_netlbl_sk_security_reset(newssec); | 4197 | selinux_netlbl_sk_security_reset(newsksec); |
4223 | } | 4198 | } |
4224 | 4199 | ||
4225 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4200 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
@@ -4303,19 +4278,92 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) | |||
4303 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); | 4278 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); |
4304 | } | 4279 | } |
4305 | 4280 | ||
4281 | static int selinux_secmark_relabel_packet(u32 sid) | ||
4282 | { | ||
4283 | const struct task_security_struct *__tsec; | ||
4284 | u32 tsid; | ||
4285 | |||
4286 | __tsec = current_security(); | ||
4287 | tsid = __tsec->sid; | ||
4288 | |||
4289 | return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); | ||
4290 | } | ||
4291 | |||
4292 | static void selinux_secmark_refcount_inc(void) | ||
4293 | { | ||
4294 | atomic_inc(&selinux_secmark_refcount); | ||
4295 | } | ||
4296 | |||
4297 | static void selinux_secmark_refcount_dec(void) | ||
4298 | { | ||
4299 | atomic_dec(&selinux_secmark_refcount); | ||
4300 | } | ||
4301 | |||
4306 | static void selinux_req_classify_flow(const struct request_sock *req, | 4302 | static void selinux_req_classify_flow(const struct request_sock *req, |
4307 | struct flowi *fl) | 4303 | struct flowi *fl) |
4308 | { | 4304 | { |
4309 | fl->secid = req->secid; | 4305 | fl->secid = req->secid; |
4310 | } | 4306 | } |
4311 | 4307 | ||
4308 | static int selinux_tun_dev_create(void) | ||
4309 | { | ||
4310 | u32 sid = current_sid(); | ||
4311 | |||
4312 | /* we aren't taking into account the "sockcreate" SID since the socket | ||
4313 | * that is being created here is not a socket in the traditional sense, | ||
4314 | * instead it is a private sock, accessible only to the kernel, and | ||
4315 | * representing a wide range of network traffic spanning multiple | ||
4316 | * connections unlike traditional sockets - check the TUN driver to | ||
4317 | * get a better understanding of why this socket is special */ | ||
4318 | |||
4319 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | ||
4320 | NULL); | ||
4321 | } | ||
4322 | |||
4323 | static void selinux_tun_dev_post_create(struct sock *sk) | ||
4324 | { | ||
4325 | struct sk_security_struct *sksec = sk->sk_security; | ||
4326 | |||
4327 | /* we don't currently perform any NetLabel based labeling here and it | ||
4328 | * isn't clear that we would want to do so anyway; while we could apply | ||
4329 | * labeling without the support of the TUN user the resulting labeled | ||
4330 | * traffic from the other end of the connection would almost certainly | ||
4331 | * cause confusion to the TUN user that had no idea network labeling | ||
4332 | * protocols were being used */ | ||
4333 | |||
4334 | /* see the comments in selinux_tun_dev_create() about why we don't use | ||
4335 | * the sockcreate SID here */ | ||
4336 | |||
4337 | sksec->sid = current_sid(); | ||
4338 | sksec->sclass = SECCLASS_TUN_SOCKET; | ||
4339 | } | ||
4340 | |||
4341 | static int selinux_tun_dev_attach(struct sock *sk) | ||
4342 | { | ||
4343 | struct sk_security_struct *sksec = sk->sk_security; | ||
4344 | u32 sid = current_sid(); | ||
4345 | int err; | ||
4346 | |||
4347 | err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, | ||
4348 | TUN_SOCKET__RELABELFROM, NULL); | ||
4349 | if (err) | ||
4350 | return err; | ||
4351 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, | ||
4352 | TUN_SOCKET__RELABELTO, NULL); | ||
4353 | if (err) | ||
4354 | return err; | ||
4355 | |||
4356 | sksec->sid = sid; | ||
4357 | |||
4358 | return 0; | ||
4359 | } | ||
4360 | |||
4312 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | 4361 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
4313 | { | 4362 | { |
4314 | int err = 0; | 4363 | int err = 0; |
4315 | u32 perm; | 4364 | u32 perm; |
4316 | struct nlmsghdr *nlh; | 4365 | struct nlmsghdr *nlh; |
4317 | struct socket *sock = sk->sk_socket; | 4366 | struct sk_security_struct *sksec = sk->sk_security; |
4318 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
4319 | 4367 | ||
4320 | if (skb->len < NLMSG_SPACE(0)) { | 4368 | if (skb->len < NLMSG_SPACE(0)) { |
4321 | err = -EINVAL; | 4369 | err = -EINVAL; |
@@ -4323,13 +4371,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4323 | } | 4371 | } |
4324 | nlh = nlmsg_hdr(skb); | 4372 | nlh = nlmsg_hdr(skb); |
4325 | 4373 | ||
4326 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 4374 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
4327 | if (err) { | 4375 | if (err) { |
4328 | if (err == -EINVAL) { | 4376 | if (err == -EINVAL) { |
4329 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4377 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
4330 | "SELinux: unrecognized netlink message" | 4378 | "SELinux: unrecognized netlink message" |
4331 | " type=%hu for sclass=%hu\n", | 4379 | " type=%hu for sclass=%hu\n", |
4332 | nlh->nlmsg_type, isec->sclass); | 4380 | nlh->nlmsg_type, sksec->sclass); |
4333 | if (!selinux_enforcing || security_get_allow_unknown()) | 4381 | if (!selinux_enforcing || security_get_allow_unknown()) |
4334 | err = 0; | 4382 | err = 0; |
4335 | } | 4383 | } |
@@ -4340,7 +4388,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4340 | goto out; | 4388 | goto out; |
4341 | } | 4389 | } |
4342 | 4390 | ||
4343 | err = socket_has_perm(current, sock, perm); | 4391 | err = sock_has_perm(current, sk, perm); |
4344 | out: | 4392 | out: |
4345 | return err; | 4393 | return err; |
4346 | } | 4394 | } |
@@ -4353,7 +4401,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4353 | int err; | 4401 | int err; |
4354 | char *addrp; | 4402 | char *addrp; |
4355 | u32 peer_sid; | 4403 | u32 peer_sid; |
4356 | struct avc_audit_data ad; | 4404 | struct common_audit_data ad; |
4357 | u8 secmark_active; | 4405 | u8 secmark_active; |
4358 | u8 netlbl_active; | 4406 | u8 netlbl_active; |
4359 | u8 peerlbl_active; | 4407 | u8 peerlbl_active; |
@@ -4370,7 +4418,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4370 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4418 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4371 | return NF_DROP; | 4419 | return NF_DROP; |
4372 | 4420 | ||
4373 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4421 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4374 | ad.u.net.netif = ifindex; | 4422 | ad.u.net.netif = ifindex; |
4375 | ad.u.net.family = family; | 4423 | ad.u.net.family = family; |
4376 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4424 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
@@ -4458,7 +4506,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4458 | { | 4506 | { |
4459 | struct sock *sk = skb->sk; | 4507 | struct sock *sk = skb->sk; |
4460 | struct sk_security_struct *sksec; | 4508 | struct sk_security_struct *sksec; |
4461 | struct avc_audit_data ad; | 4509 | struct common_audit_data ad; |
4462 | char *addrp; | 4510 | char *addrp; |
4463 | u8 proto; | 4511 | u8 proto; |
4464 | 4512 | ||
@@ -4466,7 +4514,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4466 | return NF_ACCEPT; | 4514 | return NF_ACCEPT; |
4467 | sksec = sk->sk_security; | 4515 | sksec = sk->sk_security; |
4468 | 4516 | ||
4469 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4517 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4470 | ad.u.net.netif = ifindex; | 4518 | ad.u.net.netif = ifindex; |
4471 | ad.u.net.family = family; | 4519 | ad.u.net.family = family; |
4472 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4520 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
@@ -4475,11 +4523,11 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4475 | if (selinux_secmark_enabled()) | 4523 | if (selinux_secmark_enabled()) |
4476 | if (avc_has_perm(sksec->sid, skb->secmark, | 4524 | if (avc_has_perm(sksec->sid, skb->secmark, |
4477 | SECCLASS_PACKET, PACKET__SEND, &ad)) | 4525 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
4478 | return NF_DROP; | 4526 | return NF_DROP_ERR(-ECONNREFUSED); |
4479 | 4527 | ||
4480 | if (selinux_policycap_netpeer) | 4528 | if (selinux_policycap_netpeer) |
4481 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) | 4529 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) |
4482 | return NF_DROP; | 4530 | return NF_DROP_ERR(-ECONNREFUSED); |
4483 | 4531 | ||
4484 | return NF_ACCEPT; | 4532 | return NF_ACCEPT; |
4485 | } | 4533 | } |
@@ -4490,7 +4538,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4490 | u32 secmark_perm; | 4538 | u32 secmark_perm; |
4491 | u32 peer_sid; | 4539 | u32 peer_sid; |
4492 | struct sock *sk; | 4540 | struct sock *sk; |
4493 | struct avc_audit_data ad; | 4541 | struct common_audit_data ad; |
4494 | char *addrp; | 4542 | char *addrp; |
4495 | u8 secmark_active; | 4543 | u8 secmark_active; |
4496 | u8 peerlbl_active; | 4544 | u8 peerlbl_active; |
@@ -4536,7 +4584,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4536 | secmark_perm = PACKET__SEND; | 4584 | secmark_perm = PACKET__SEND; |
4537 | break; | 4585 | break; |
4538 | default: | 4586 | default: |
4539 | return NF_DROP; | 4587 | return NF_DROP_ERR(-ECONNREFUSED); |
4540 | } | 4588 | } |
4541 | if (secmark_perm == PACKET__FORWARD_OUT) { | 4589 | if (secmark_perm == PACKET__FORWARD_OUT) { |
4542 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | 4590 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
@@ -4549,7 +4597,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4549 | secmark_perm = PACKET__SEND; | 4597 | secmark_perm = PACKET__SEND; |
4550 | } | 4598 | } |
4551 | 4599 | ||
4552 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4600 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4553 | ad.u.net.netif = ifindex; | 4601 | ad.u.net.netif = ifindex; |
4554 | ad.u.net.family = family; | 4602 | ad.u.net.family = family; |
4555 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4603 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
@@ -4558,7 +4606,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4558 | if (secmark_active) | 4606 | if (secmark_active) |
4559 | if (avc_has_perm(peer_sid, skb->secmark, | 4607 | if (avc_has_perm(peer_sid, skb->secmark, |
4560 | SECCLASS_PACKET, secmark_perm, &ad)) | 4608 | SECCLASS_PACKET, secmark_perm, &ad)) |
4561 | return NF_DROP; | 4609 | return NF_DROP_ERR(-ECONNREFUSED); |
4562 | 4610 | ||
4563 | if (peerlbl_active) { | 4611 | if (peerlbl_active) { |
4564 | u32 if_sid; | 4612 | u32 if_sid; |
@@ -4568,13 +4616,13 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4568 | return NF_DROP; | 4616 | return NF_DROP; |
4569 | if (avc_has_perm(peer_sid, if_sid, | 4617 | if (avc_has_perm(peer_sid, if_sid, |
4570 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) | 4618 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) |
4571 | return NF_DROP; | 4619 | return NF_DROP_ERR(-ECONNREFUSED); |
4572 | 4620 | ||
4573 | if (sel_netnode_sid(addrp, family, &node_sid)) | 4621 | if (sel_netnode_sid(addrp, family, &node_sid)) |
4574 | return NF_DROP; | 4622 | return NF_DROP; |
4575 | if (avc_has_perm(peer_sid, node_sid, | 4623 | if (avc_has_perm(peer_sid, node_sid, |
4576 | SECCLASS_NODE, NODE__SENDTO, &ad)) | 4624 | SECCLASS_NODE, NODE__SENDTO, &ad)) |
4577 | return NF_DROP; | 4625 | return NF_DROP_ERR(-ECONNREFUSED); |
4578 | } | 4626 | } |
4579 | 4627 | ||
4580 | return NF_ACCEPT; | 4628 | return NF_ACCEPT; |
@@ -4610,22 +4658,19 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
4610 | if (err) | 4658 | if (err) |
4611 | return err; | 4659 | return err; |
4612 | 4660 | ||
4613 | if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) | 4661 | return selinux_nlmsg_perm(sk, skb); |
4614 | err = selinux_nlmsg_perm(sk, skb); | ||
4615 | |||
4616 | return err; | ||
4617 | } | 4662 | } |
4618 | 4663 | ||
4619 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4664 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
4620 | { | 4665 | { |
4621 | int err; | 4666 | int err; |
4622 | struct avc_audit_data ad; | 4667 | struct common_audit_data ad; |
4623 | 4668 | ||
4624 | err = cap_netlink_recv(skb, capability); | 4669 | err = cap_netlink_recv(skb, capability); |
4625 | if (err) | 4670 | if (err) |
4626 | return err; | 4671 | return err; |
4627 | 4672 | ||
4628 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 4673 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
4629 | ad.u.cap = capability; | 4674 | ad.u.cap = capability; |
4630 | 4675 | ||
4631 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, | 4676 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, |
@@ -4684,12 +4729,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4684 | u32 perms) | 4729 | u32 perms) |
4685 | { | 4730 | { |
4686 | struct ipc_security_struct *isec; | 4731 | struct ipc_security_struct *isec; |
4687 | struct avc_audit_data ad; | 4732 | struct common_audit_data ad; |
4688 | u32 sid = current_sid(); | 4733 | u32 sid = current_sid(); |
4689 | 4734 | ||
4690 | isec = ipc_perms->security; | 4735 | isec = ipc_perms->security; |
4691 | 4736 | ||
4692 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4737 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4693 | ad.u.ipc_id = ipc_perms->key; | 4738 | ad.u.ipc_id = ipc_perms->key; |
4694 | 4739 | ||
4695 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4740 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4709,7 +4754,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) | |||
4709 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4754 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
4710 | { | 4755 | { |
4711 | struct ipc_security_struct *isec; | 4756 | struct ipc_security_struct *isec; |
4712 | struct avc_audit_data ad; | 4757 | struct common_audit_data ad; |
4713 | u32 sid = current_sid(); | 4758 | u32 sid = current_sid(); |
4714 | int rc; | 4759 | int rc; |
4715 | 4760 | ||
@@ -4719,7 +4764,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4719 | 4764 | ||
4720 | isec = msq->q_perm.security; | 4765 | isec = msq->q_perm.security; |
4721 | 4766 | ||
4722 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4767 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4723 | ad.u.ipc_id = msq->q_perm.key; | 4768 | ad.u.ipc_id = msq->q_perm.key; |
4724 | 4769 | ||
4725 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4770 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4739,12 +4784,12 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq) | |||
4739 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | 4784 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
4740 | { | 4785 | { |
4741 | struct ipc_security_struct *isec; | 4786 | struct ipc_security_struct *isec; |
4742 | struct avc_audit_data ad; | 4787 | struct common_audit_data ad; |
4743 | u32 sid = current_sid(); | 4788 | u32 sid = current_sid(); |
4744 | 4789 | ||
4745 | isec = msq->q_perm.security; | 4790 | isec = msq->q_perm.security; |
4746 | 4791 | ||
4747 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4792 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4748 | ad.u.ipc_id = msq->q_perm.key; | 4793 | ad.u.ipc_id = msq->q_perm.key; |
4749 | 4794 | ||
4750 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4795 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4783,7 +4828,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4783 | { | 4828 | { |
4784 | struct ipc_security_struct *isec; | 4829 | struct ipc_security_struct *isec; |
4785 | struct msg_security_struct *msec; | 4830 | struct msg_security_struct *msec; |
4786 | struct avc_audit_data ad; | 4831 | struct common_audit_data ad; |
4787 | u32 sid = current_sid(); | 4832 | u32 sid = current_sid(); |
4788 | int rc; | 4833 | int rc; |
4789 | 4834 | ||
@@ -4804,7 +4849,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4804 | return rc; | 4849 | return rc; |
4805 | } | 4850 | } |
4806 | 4851 | ||
4807 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4852 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4808 | ad.u.ipc_id = msq->q_perm.key; | 4853 | ad.u.ipc_id = msq->q_perm.key; |
4809 | 4854 | ||
4810 | /* Can this process write to the queue? */ | 4855 | /* Can this process write to the queue? */ |
@@ -4828,14 +4873,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4828 | { | 4873 | { |
4829 | struct ipc_security_struct *isec; | 4874 | struct ipc_security_struct *isec; |
4830 | struct msg_security_struct *msec; | 4875 | struct msg_security_struct *msec; |
4831 | struct avc_audit_data ad; | 4876 | struct common_audit_data ad; |
4832 | u32 sid = task_sid(target); | 4877 | u32 sid = task_sid(target); |
4833 | int rc; | 4878 | int rc; |
4834 | 4879 | ||
4835 | isec = msq->q_perm.security; | 4880 | isec = msq->q_perm.security; |
4836 | msec = msg->security; | 4881 | msec = msg->security; |
4837 | 4882 | ||
4838 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4883 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4839 | ad.u.ipc_id = msq->q_perm.key; | 4884 | ad.u.ipc_id = msq->q_perm.key; |
4840 | 4885 | ||
4841 | rc = avc_has_perm(sid, isec->sid, | 4886 | rc = avc_has_perm(sid, isec->sid, |
@@ -4850,7 +4895,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4850 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) | 4895 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
4851 | { | 4896 | { |
4852 | struct ipc_security_struct *isec; | 4897 | struct ipc_security_struct *isec; |
4853 | struct avc_audit_data ad; | 4898 | struct common_audit_data ad; |
4854 | u32 sid = current_sid(); | 4899 | u32 sid = current_sid(); |
4855 | int rc; | 4900 | int rc; |
4856 | 4901 | ||
@@ -4860,7 +4905,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
4860 | 4905 | ||
4861 | isec = shp->shm_perm.security; | 4906 | isec = shp->shm_perm.security; |
4862 | 4907 | ||
4863 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4908 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4864 | ad.u.ipc_id = shp->shm_perm.key; | 4909 | ad.u.ipc_id = shp->shm_perm.key; |
4865 | 4910 | ||
4866 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4911 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4880,12 +4925,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) | |||
4880 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4925 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
4881 | { | 4926 | { |
4882 | struct ipc_security_struct *isec; | 4927 | struct ipc_security_struct *isec; |
4883 | struct avc_audit_data ad; | 4928 | struct common_audit_data ad; |
4884 | u32 sid = current_sid(); | 4929 | u32 sid = current_sid(); |
4885 | 4930 | ||
4886 | isec = shp->shm_perm.security; | 4931 | isec = shp->shm_perm.security; |
4887 | 4932 | ||
4888 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4933 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4889 | ad.u.ipc_id = shp->shm_perm.key; | 4934 | ad.u.ipc_id = shp->shm_perm.key; |
4890 | 4935 | ||
4891 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4936 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4942,7 +4987,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, | |||
4942 | static int selinux_sem_alloc_security(struct sem_array *sma) | 4987 | static int selinux_sem_alloc_security(struct sem_array *sma) |
4943 | { | 4988 | { |
4944 | struct ipc_security_struct *isec; | 4989 | struct ipc_security_struct *isec; |
4945 | struct avc_audit_data ad; | 4990 | struct common_audit_data ad; |
4946 | u32 sid = current_sid(); | 4991 | u32 sid = current_sid(); |
4947 | int rc; | 4992 | int rc; |
4948 | 4993 | ||
@@ -4952,7 +4997,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
4952 | 4997 | ||
4953 | isec = sma->sem_perm.security; | 4998 | isec = sma->sem_perm.security; |
4954 | 4999 | ||
4955 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5000 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4956 | ad.u.ipc_id = sma->sem_perm.key; | 5001 | ad.u.ipc_id = sma->sem_perm.key; |
4957 | 5002 | ||
4958 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5003 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -4972,12 +5017,12 @@ static void selinux_sem_free_security(struct sem_array *sma) | |||
4972 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 5017 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
4973 | { | 5018 | { |
4974 | struct ipc_security_struct *isec; | 5019 | struct ipc_security_struct *isec; |
4975 | struct avc_audit_data ad; | 5020 | struct common_audit_data ad; |
4976 | u32 sid = current_sid(); | 5021 | u32 sid = current_sid(); |
4977 | 5022 | ||
4978 | isec = sma->sem_perm.security; | 5023 | isec = sma->sem_perm.security; |
4979 | 5024 | ||
4980 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5025 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4981 | ad.u.ipc_id = sma->sem_perm.key; | 5026 | ad.u.ipc_id = sma->sem_perm.key; |
4982 | 5027 | ||
4983 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5028 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5195,7 +5240,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5195 | 5240 | ||
5196 | /* Only allow single threaded processes to change context */ | 5241 | /* Only allow single threaded processes to change context */ |
5197 | error = -EPERM; | 5242 | error = -EPERM; |
5198 | if (!is_single_threaded(p)) { | 5243 | if (!current_is_single_threaded()) { |
5199 | error = security_bounded_transition(tsec->sid, sid); | 5244 | error = security_bounded_transition(tsec->sid, sid); |
5200 | if (error) | 5245 | if (error) |
5201 | goto abort_change; | 5246 | goto abort_change; |
@@ -5252,6 +5297,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5252 | kfree(secdata); | 5297 | kfree(secdata); |
5253 | } | 5298 | } |
5254 | 5299 | ||
5300 | /* | ||
5301 | * called with inode->i_mutex locked | ||
5302 | */ | ||
5303 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
5304 | { | ||
5305 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); | ||
5306 | } | ||
5307 | |||
5308 | /* | ||
5309 | * called with inode->i_mutex locked | ||
5310 | */ | ||
5311 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
5312 | { | ||
5313 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); | ||
5314 | } | ||
5315 | |||
5316 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
5317 | { | ||
5318 | int len = 0; | ||
5319 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, | ||
5320 | ctx, true); | ||
5321 | if (len < 0) | ||
5322 | return len; | ||
5323 | *ctxlen = len; | ||
5324 | return 0; | ||
5325 | } | ||
5255 | #ifdef CONFIG_KEYS | 5326 | #ifdef CONFIG_KEYS |
5256 | 5327 | ||
5257 | static int selinux_key_alloc(struct key *k, const struct cred *cred, | 5328 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
@@ -5323,7 +5394,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5323 | static struct security_operations selinux_ops = { | 5394 | static struct security_operations selinux_ops = { |
5324 | .name = "selinux", | 5395 | .name = "selinux", |
5325 | 5396 | ||
5326 | .ptrace_may_access = selinux_ptrace_may_access, | 5397 | .ptrace_access_check = selinux_ptrace_access_check, |
5327 | .ptrace_traceme = selinux_ptrace_traceme, | 5398 | .ptrace_traceme = selinux_ptrace_traceme, |
5328 | .capget = selinux_capget, | 5399 | .capget = selinux_capget, |
5329 | .capset = selinux_capset, | 5400 | .capset = selinux_capset, |
@@ -5396,10 +5467,13 @@ static struct security_operations selinux_ops = { | |||
5396 | .dentry_open = selinux_dentry_open, | 5467 | .dentry_open = selinux_dentry_open, |
5397 | 5468 | ||
5398 | .task_create = selinux_task_create, | 5469 | .task_create = selinux_task_create, |
5470 | .cred_alloc_blank = selinux_cred_alloc_blank, | ||
5399 | .cred_free = selinux_cred_free, | 5471 | .cred_free = selinux_cred_free, |
5400 | .cred_prepare = selinux_cred_prepare, | 5472 | .cred_prepare = selinux_cred_prepare, |
5473 | .cred_transfer = selinux_cred_transfer, | ||
5401 | .kernel_act_as = selinux_kernel_act_as, | 5474 | .kernel_act_as = selinux_kernel_act_as, |
5402 | .kernel_create_files_as = selinux_kernel_create_files_as, | 5475 | .kernel_create_files_as = selinux_kernel_create_files_as, |
5476 | .kernel_module_request = selinux_kernel_module_request, | ||
5403 | .task_setpgid = selinux_task_setpgid, | 5477 | .task_setpgid = selinux_task_setpgid, |
5404 | .task_getpgid = selinux_task_getpgid, | 5478 | .task_getpgid = selinux_task_getpgid, |
5405 | .task_getsid = selinux_task_getsid, | 5479 | .task_getsid = selinux_task_getsid, |
@@ -5448,6 +5522,9 @@ static struct security_operations selinux_ops = { | |||
5448 | .secid_to_secctx = selinux_secid_to_secctx, | 5522 | .secid_to_secctx = selinux_secid_to_secctx, |
5449 | .secctx_to_secid = selinux_secctx_to_secid, | 5523 | .secctx_to_secid = selinux_secctx_to_secid, |
5450 | .release_secctx = selinux_release_secctx, | 5524 | .release_secctx = selinux_release_secctx, |
5525 | .inode_notifysecctx = selinux_inode_notifysecctx, | ||
5526 | .inode_setsecctx = selinux_inode_setsecctx, | ||
5527 | .inode_getsecctx = selinux_inode_getsecctx, | ||
5451 | 5528 | ||
5452 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5529 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
5453 | .unix_may_send = selinux_socket_unix_may_send, | 5530 | .unix_may_send = selinux_socket_unix_may_send, |
@@ -5476,7 +5553,13 @@ static struct security_operations selinux_ops = { | |||
5476 | .inet_conn_request = selinux_inet_conn_request, | 5553 | .inet_conn_request = selinux_inet_conn_request, |
5477 | .inet_csk_clone = selinux_inet_csk_clone, | 5554 | .inet_csk_clone = selinux_inet_csk_clone, |
5478 | .inet_conn_established = selinux_inet_conn_established, | 5555 | .inet_conn_established = selinux_inet_conn_established, |
5556 | .secmark_relabel_packet = selinux_secmark_relabel_packet, | ||
5557 | .secmark_refcount_inc = selinux_secmark_refcount_inc, | ||
5558 | .secmark_refcount_dec = selinux_secmark_refcount_dec, | ||
5479 | .req_classify_flow = selinux_req_classify_flow, | 5559 | .req_classify_flow = selinux_req_classify_flow, |
5560 | .tun_dev_create = selinux_tun_dev_create, | ||
5561 | .tun_dev_post_create = selinux_tun_dev_post_create, | ||
5562 | .tun_dev_attach = selinux_tun_dev_attach, | ||
5480 | 5563 | ||
5481 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 5564 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
5482 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 5565 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
@@ -5523,14 +5606,13 @@ static __init int selinux_init(void) | |||
5523 | /* Set the security state for the initial task. */ | 5606 | /* Set the security state for the initial task. */ |
5524 | cred_init_security(); | 5607 | cred_init_security(); |
5525 | 5608 | ||
5609 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | ||
5610 | |||
5526 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5611 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
5527 | sizeof(struct inode_security_struct), | 5612 | sizeof(struct inode_security_struct), |
5528 | 0, SLAB_PANIC, NULL); | 5613 | 0, SLAB_PANIC, NULL); |
5529 | avc_init(); | 5614 | avc_init(); |
5530 | 5615 | ||
5531 | secondary_ops = security_ops; | ||
5532 | if (!secondary_ops) | ||
5533 | panic("SELinux: No initial security operations\n"); | ||
5534 | if (register_security(&selinux_ops)) | 5616 | if (register_security(&selinux_ops)) |
5535 | panic("SELinux: Unable to register with kernel.\n"); | 5617 | panic("SELinux: Unable to register with kernel.\n"); |
5536 | 5618 | ||
@@ -5542,35 +5624,18 @@ static __init int selinux_init(void) | |||
5542 | return 0; | 5624 | return 0; |
5543 | } | 5625 | } |
5544 | 5626 | ||
5627 | static void delayed_superblock_init(struct super_block *sb, void *unused) | ||
5628 | { | ||
5629 | superblock_doinit(sb, NULL); | ||
5630 | } | ||
5631 | |||
5545 | void selinux_complete_init(void) | 5632 | void selinux_complete_init(void) |
5546 | { | 5633 | { |
5547 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5634 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
5548 | 5635 | ||
5549 | /* Set up any superblocks initialized prior to the policy load. */ | 5636 | /* Set up any superblocks initialized prior to the policy load. */ |
5550 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5637 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
5551 | spin_lock(&sb_lock); | 5638 | iterate_supers(delayed_superblock_init, NULL); |
5552 | spin_lock(&sb_security_lock); | ||
5553 | next_sb: | ||
5554 | if (!list_empty(&superblock_security_head)) { | ||
5555 | struct superblock_security_struct *sbsec = | ||
5556 | list_entry(superblock_security_head.next, | ||
5557 | struct superblock_security_struct, | ||
5558 | list); | ||
5559 | struct super_block *sb = sbsec->sb; | ||
5560 | sb->s_count++; | ||
5561 | spin_unlock(&sb_security_lock); | ||
5562 | spin_unlock(&sb_lock); | ||
5563 | down_read(&sb->s_umount); | ||
5564 | if (sb->s_root) | ||
5565 | superblock_doinit(sb, NULL); | ||
5566 | drop_super(sb); | ||
5567 | spin_lock(&sb_lock); | ||
5568 | spin_lock(&sb_security_lock); | ||
5569 | list_del_init(&sbsec->list); | ||
5570 | goto next_sb; | ||
5571 | } | ||
5572 | spin_unlock(&sb_security_lock); | ||
5573 | spin_unlock(&sb_lock); | ||
5574 | } | 5639 | } |
5575 | 5640 | ||
5576 | /* SELinux requires early initialization in order to label | 5641 | /* SELinux requires early initialization in order to label |
@@ -5691,8 +5756,10 @@ int selinux_disable(void) | |||
5691 | selinux_disabled = 1; | 5756 | selinux_disabled = 1; |
5692 | selinux_enabled = 0; | 5757 | selinux_enabled = 0; |
5693 | 5758 | ||
5694 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5759 | reset_security_ops(); |
5695 | security_ops = secondary_ops; | 5760 | |
5761 | /* Try to destroy the avc node cache */ | ||
5762 | avc_disable(); | ||
5696 | 5763 | ||
5697 | /* Unregister netfilter hooks. */ | 5764 | /* Unregister netfilter hooks. */ |
5698 | selinux_nf_ip_exit(); | 5765 | selinux_nf_ip_exit(); |
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h deleted file mode 100644 index 8377a4ba3b9..00000000000 --- a/security/selinux/include/av_inherit.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | S_(SECCLASS_DIR, file, 0x00020000UL) | ||
3 | S_(SECCLASS_FILE, file, 0x00020000UL) | ||
4 | S_(SECCLASS_LNK_FILE, file, 0x00020000UL) | ||
5 | S_(SECCLASS_CHR_FILE, file, 0x00020000UL) | ||
6 | S_(SECCLASS_BLK_FILE, file, 0x00020000UL) | ||
7 | S_(SECCLASS_SOCK_FILE, file, 0x00020000UL) | ||
8 | S_(SECCLASS_FIFO_FILE, file, 0x00020000UL) | ||
9 | S_(SECCLASS_SOCKET, socket, 0x00400000UL) | ||
10 | S_(SECCLASS_TCP_SOCKET, socket, 0x00400000UL) | ||
11 | S_(SECCLASS_UDP_SOCKET, socket, 0x00400000UL) | ||
12 | S_(SECCLASS_RAWIP_SOCKET, socket, 0x00400000UL) | ||
13 | S_(SECCLASS_NETLINK_SOCKET, socket, 0x00400000UL) | ||
14 | S_(SECCLASS_PACKET_SOCKET, socket, 0x00400000UL) | ||
15 | S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) | ||
16 | S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) | ||
17 | S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) | ||
18 | S_(SECCLASS_IPC, ipc, 0x00000200UL) | ||
19 | S_(SECCLASS_SEM, ipc, 0x00000200UL) | ||
20 | S_(SECCLASS_MSGQ, ipc, 0x00000200UL) | ||
21 | S_(SECCLASS_SHM, ipc, 0x00000200UL) | ||
22 | S_(SECCLASS_NETLINK_ROUTE_SOCKET, socket, 0x00400000UL) | ||
23 | S_(SECCLASS_NETLINK_FIREWALL_SOCKET, socket, 0x00400000UL) | ||
24 | S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, socket, 0x00400000UL) | ||
25 | S_(SECCLASS_NETLINK_NFLOG_SOCKET, socket, 0x00400000UL) | ||
26 | S_(SECCLASS_NETLINK_XFRM_SOCKET, socket, 0x00400000UL) | ||
27 | S_(SECCLASS_NETLINK_SELINUX_SOCKET, socket, 0x00400000UL) | ||
28 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, socket, 0x00400000UL) | ||
29 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL) | ||
30 | S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) | ||
31 | S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) | ||
32 | S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL) | ||
33 | S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL) | ||
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h deleted file mode 100644 index 31df1d7c1ae..00000000000 --- a/security/selinux/include/av_perm_to_string.h +++ /dev/null | |||
@@ -1,182 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount") | ||
3 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount") | ||
4 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount") | ||
5 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr") | ||
6 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom") | ||
7 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto") | ||
8 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition") | ||
9 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate") | ||
10 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod") | ||
11 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget") | ||
12 | S_(SECCLASS_DIR, DIR__ADD_NAME, "add_name") | ||
13 | S_(SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name") | ||
14 | S_(SECCLASS_DIR, DIR__REPARENT, "reparent") | ||
15 | S_(SECCLASS_DIR, DIR__SEARCH, "search") | ||
16 | S_(SECCLASS_DIR, DIR__RMDIR, "rmdir") | ||
17 | S_(SECCLASS_DIR, DIR__OPEN, "open") | ||
18 | S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans") | ||
19 | S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") | ||
20 | S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") | ||
21 | S_(SECCLASS_FILE, FILE__OPEN, "open") | ||
22 | S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") | ||
23 | S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint") | ||
24 | S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod") | ||
25 | S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open") | ||
26 | S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open") | ||
27 | S_(SECCLASS_SOCK_FILE, SOCK_FILE__OPEN, "open") | ||
28 | S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open") | ||
29 | S_(SECCLASS_FD, FD__USE, "use") | ||
30 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto") | ||
31 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn") | ||
32 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom") | ||
33 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind") | ||
34 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NAME_CONNECT, "name_connect") | ||
35 | S_(SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind") | ||
36 | S_(SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind") | ||
37 | S_(SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv") | ||
38 | S_(SECCLASS_NODE, NODE__TCP_SEND, "tcp_send") | ||
39 | S_(SECCLASS_NODE, NODE__UDP_RECV, "udp_recv") | ||
40 | S_(SECCLASS_NODE, NODE__UDP_SEND, "udp_send") | ||
41 | S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv") | ||
42 | S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send") | ||
43 | S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") | ||
44 | S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") | ||
45 | S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") | ||
46 | S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom") | ||
47 | S_(SECCLASS_NODE, NODE__SENDTO, "sendto") | ||
48 | S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") | ||
49 | S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") | ||
50 | S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") | ||
51 | S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send") | ||
52 | S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv") | ||
53 | S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") | ||
54 | S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") | ||
55 | S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") | ||
56 | S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress") | ||
57 | S_(SECCLASS_NETIF, NETIF__EGRESS, "egress") | ||
58 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") | ||
59 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") | ||
60 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") | ||
61 | S_(SECCLASS_PROCESS, PROCESS__FORK, "fork") | ||
62 | S_(SECCLASS_PROCESS, PROCESS__TRANSITION, "transition") | ||
63 | S_(SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld") | ||
64 | S_(SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill") | ||
65 | S_(SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop") | ||
66 | S_(SECCLASS_PROCESS, PROCESS__SIGNULL, "signull") | ||
67 | S_(SECCLASS_PROCESS, PROCESS__SIGNAL, "signal") | ||
68 | S_(SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace") | ||
69 | S_(SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched") | ||
70 | S_(SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched") | ||
71 | S_(SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession") | ||
72 | S_(SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid") | ||
73 | S_(SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid") | ||
74 | S_(SECCLASS_PROCESS, PROCESS__GETCAP, "getcap") | ||
75 | S_(SECCLASS_PROCESS, PROCESS__SETCAP, "setcap") | ||
76 | S_(SECCLASS_PROCESS, PROCESS__SHARE, "share") | ||
77 | S_(SECCLASS_PROCESS, PROCESS__GETATTR, "getattr") | ||
78 | S_(SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec") | ||
79 | S_(SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate") | ||
80 | S_(SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure") | ||
81 | S_(SECCLASS_PROCESS, PROCESS__SIGINH, "siginh") | ||
82 | S_(SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit") | ||
83 | S_(SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh") | ||
84 | S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition") | ||
85 | S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent") | ||
86 | S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") | ||
87 | S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") | ||
88 | S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") | ||
89 | S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") | ||
90 | S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") | ||
91 | S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") | ||
92 | S_(SECCLASS_MSG, MSG__SEND, "send") | ||
93 | S_(SECCLASS_MSG, MSG__RECEIVE, "receive") | ||
94 | S_(SECCLASS_SHM, SHM__LOCK, "lock") | ||
95 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av") | ||
96 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create") | ||
97 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member") | ||
98 | S_(SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context") | ||
99 | S_(SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy") | ||
100 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel") | ||
101 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user") | ||
102 | S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce") | ||
103 | S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool") | ||
104 | S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam") | ||
105 | S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot") | ||
106 | S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info") | ||
107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") | ||
108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") | ||
109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") | ||
110 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") | ||
111 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") | ||
112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") | ||
113 | S_(SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner") | ||
114 | S_(SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid") | ||
115 | S_(SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill") | ||
116 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid") | ||
117 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid") | ||
118 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap") | ||
119 | S_(SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable") | ||
120 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service") | ||
121 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast") | ||
122 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin") | ||
123 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw") | ||
124 | S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock") | ||
125 | S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner") | ||
126 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module") | ||
127 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio") | ||
128 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot") | ||
129 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace") | ||
130 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct") | ||
131 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin") | ||
132 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot") | ||
133 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice") | ||
134 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource") | ||
135 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time") | ||
136 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config") | ||
137 | S_(SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod") | ||
138 | S_(SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease") | ||
139 | S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_WRITE, "audit_write") | ||
140 | S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_CONTROL, "audit_control") | ||
141 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETFCAP, "setfcap") | ||
142 | S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_OVERRIDE, "mac_override") | ||
143 | S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_ADMIN, "mac_admin") | ||
144 | S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read") | ||
145 | S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
146 | S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read") | ||
147 | S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
148 | S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read") | ||
149 | S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
150 | S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read") | ||
151 | S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
152 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read") | ||
153 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
154 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay") | ||
155 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv") | ||
156 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT, "nlmsg_tty_audit") | ||
157 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read") | ||
158 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
159 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") | ||
160 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") | ||
161 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") | ||
162 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, "polmatch") | ||
163 | S_(SECCLASS_PACKET, PACKET__SEND, "send") | ||
164 | S_(SECCLASS_PACKET, PACKET__RECV, "recv") | ||
165 | S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") | ||
166 | S_(SECCLASS_PACKET, PACKET__FLOW_IN, "flow_in") | ||
167 | S_(SECCLASS_PACKET, PACKET__FLOW_OUT, "flow_out") | ||
168 | S_(SECCLASS_PACKET, PACKET__FORWARD_IN, "forward_in") | ||
169 | S_(SECCLASS_PACKET, PACKET__FORWARD_OUT, "forward_out") | ||
170 | S_(SECCLASS_KEY, KEY__VIEW, "view") | ||
171 | S_(SECCLASS_KEY, KEY__READ, "read") | ||
172 | S_(SECCLASS_KEY, KEY__WRITE, "write") | ||
173 | S_(SECCLASS_KEY, KEY__SEARCH, "search") | ||
174 | S_(SECCLASS_KEY, KEY__LINK, "link") | ||
175 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") | ||
176 | S_(SECCLASS_KEY, KEY__CREATE, "create") | ||
177 | S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") | ||
178 | S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") | ||
179 | S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") | ||
180 | S_(SECCLASS_PEER, PEER__RECV, "recv") | ||
181 | S_(SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__USE_AS_OVERRIDE, "use_as_override") | ||
182 | S_(SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__CREATE_FILES_AS, "create_files_as") | ||
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h deleted file mode 100644 index d645192ee95..00000000000 --- a/security/selinux/include/av_permissions.h +++ /dev/null | |||
@@ -1,847 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | #define COMMON_FILE__IOCTL 0x00000001UL | ||
3 | #define COMMON_FILE__READ 0x00000002UL | ||
4 | #define COMMON_FILE__WRITE 0x00000004UL | ||
5 | #define COMMON_FILE__CREATE 0x00000008UL | ||
6 | #define COMMON_FILE__GETATTR 0x00000010UL | ||
7 | #define COMMON_FILE__SETATTR 0x00000020UL | ||
8 | #define COMMON_FILE__LOCK 0x00000040UL | ||
9 | #define COMMON_FILE__RELABELFROM 0x00000080UL | ||
10 | #define COMMON_FILE__RELABELTO 0x00000100UL | ||
11 | #define COMMON_FILE__APPEND 0x00000200UL | ||
12 | #define COMMON_FILE__UNLINK 0x00000400UL | ||
13 | #define COMMON_FILE__LINK 0x00000800UL | ||
14 | #define COMMON_FILE__RENAME 0x00001000UL | ||
15 | #define COMMON_FILE__EXECUTE 0x00002000UL | ||
16 | #define COMMON_FILE__SWAPON 0x00004000UL | ||
17 | #define COMMON_FILE__QUOTAON 0x00008000UL | ||
18 | #define COMMON_FILE__MOUNTON 0x00010000UL | ||
19 | #define COMMON_SOCKET__IOCTL 0x00000001UL | ||
20 | #define COMMON_SOCKET__READ 0x00000002UL | ||
21 | #define COMMON_SOCKET__WRITE 0x00000004UL | ||
22 | #define COMMON_SOCKET__CREATE 0x00000008UL | ||
23 | #define COMMON_SOCKET__GETATTR 0x00000010UL | ||
24 | #define COMMON_SOCKET__SETATTR 0x00000020UL | ||
25 | #define COMMON_SOCKET__LOCK 0x00000040UL | ||
26 | #define COMMON_SOCKET__RELABELFROM 0x00000080UL | ||
27 | #define COMMON_SOCKET__RELABELTO 0x00000100UL | ||
28 | #define COMMON_SOCKET__APPEND 0x00000200UL | ||
29 | #define COMMON_SOCKET__BIND 0x00000400UL | ||
30 | #define COMMON_SOCKET__CONNECT 0x00000800UL | ||
31 | #define COMMON_SOCKET__LISTEN 0x00001000UL | ||
32 | #define COMMON_SOCKET__ACCEPT 0x00002000UL | ||
33 | #define COMMON_SOCKET__GETOPT 0x00004000UL | ||
34 | #define COMMON_SOCKET__SETOPT 0x00008000UL | ||
35 | #define COMMON_SOCKET__SHUTDOWN 0x00010000UL | ||
36 | #define COMMON_SOCKET__RECVFROM 0x00020000UL | ||
37 | #define COMMON_SOCKET__SENDTO 0x00040000UL | ||
38 | #define COMMON_SOCKET__RECV_MSG 0x00080000UL | ||
39 | #define COMMON_SOCKET__SEND_MSG 0x00100000UL | ||
40 | #define COMMON_SOCKET__NAME_BIND 0x00200000UL | ||
41 | #define COMMON_IPC__CREATE 0x00000001UL | ||
42 | #define COMMON_IPC__DESTROY 0x00000002UL | ||
43 | #define COMMON_IPC__GETATTR 0x00000004UL | ||
44 | #define COMMON_IPC__SETATTR 0x00000008UL | ||
45 | #define COMMON_IPC__READ 0x00000010UL | ||
46 | #define COMMON_IPC__WRITE 0x00000020UL | ||
47 | #define COMMON_IPC__ASSOCIATE 0x00000040UL | ||
48 | #define COMMON_IPC__UNIX_READ 0x00000080UL | ||
49 | #define COMMON_IPC__UNIX_WRITE 0x00000100UL | ||
50 | #define FILESYSTEM__MOUNT 0x00000001UL | ||
51 | #define FILESYSTEM__REMOUNT 0x00000002UL | ||
52 | #define FILESYSTEM__UNMOUNT 0x00000004UL | ||
53 | #define FILESYSTEM__GETATTR 0x00000008UL | ||
54 | #define FILESYSTEM__RELABELFROM 0x00000010UL | ||
55 | #define FILESYSTEM__RELABELTO 0x00000020UL | ||
56 | #define FILESYSTEM__TRANSITION 0x00000040UL | ||
57 | #define FILESYSTEM__ASSOCIATE 0x00000080UL | ||
58 | #define FILESYSTEM__QUOTAMOD 0x00000100UL | ||
59 | #define FILESYSTEM__QUOTAGET 0x00000200UL | ||
60 | #define DIR__IOCTL 0x00000001UL | ||
61 | #define DIR__READ 0x00000002UL | ||
62 | #define DIR__WRITE 0x00000004UL | ||
63 | #define DIR__CREATE 0x00000008UL | ||
64 | #define DIR__GETATTR 0x00000010UL | ||
65 | #define DIR__SETATTR 0x00000020UL | ||
66 | #define DIR__LOCK 0x00000040UL | ||
67 | #define DIR__RELABELFROM 0x00000080UL | ||
68 | #define DIR__RELABELTO 0x00000100UL | ||
69 | #define DIR__APPEND 0x00000200UL | ||
70 | #define DIR__UNLINK 0x00000400UL | ||
71 | #define DIR__LINK 0x00000800UL | ||
72 | #define DIR__RENAME 0x00001000UL | ||
73 | #define DIR__EXECUTE 0x00002000UL | ||
74 | #define DIR__SWAPON 0x00004000UL | ||
75 | #define DIR__QUOTAON 0x00008000UL | ||
76 | #define DIR__MOUNTON 0x00010000UL | ||
77 | #define DIR__ADD_NAME 0x00020000UL | ||
78 | #define DIR__REMOVE_NAME 0x00040000UL | ||
79 | #define DIR__REPARENT 0x00080000UL | ||
80 | #define DIR__SEARCH 0x00100000UL | ||
81 | #define DIR__RMDIR 0x00200000UL | ||
82 | #define DIR__OPEN 0x00400000UL | ||
83 | #define FILE__IOCTL 0x00000001UL | ||
84 | #define FILE__READ 0x00000002UL | ||
85 | #define FILE__WRITE 0x00000004UL | ||
86 | #define FILE__CREATE 0x00000008UL | ||
87 | #define FILE__GETATTR 0x00000010UL | ||
88 | #define FILE__SETATTR 0x00000020UL | ||
89 | #define FILE__LOCK 0x00000040UL | ||
90 | #define FILE__RELABELFROM 0x00000080UL | ||
91 | #define FILE__RELABELTO 0x00000100UL | ||
92 | #define FILE__APPEND 0x00000200UL | ||
93 | #define FILE__UNLINK 0x00000400UL | ||
94 | #define FILE__LINK 0x00000800UL | ||
95 | #define FILE__RENAME 0x00001000UL | ||
96 | #define FILE__EXECUTE 0x00002000UL | ||
97 | #define FILE__SWAPON 0x00004000UL | ||
98 | #define FILE__QUOTAON 0x00008000UL | ||
99 | #define FILE__MOUNTON 0x00010000UL | ||
100 | #define FILE__EXECUTE_NO_TRANS 0x00020000UL | ||
101 | #define FILE__ENTRYPOINT 0x00040000UL | ||
102 | #define FILE__EXECMOD 0x00080000UL | ||
103 | #define FILE__OPEN 0x00100000UL | ||
104 | #define LNK_FILE__IOCTL 0x00000001UL | ||
105 | #define LNK_FILE__READ 0x00000002UL | ||
106 | #define LNK_FILE__WRITE 0x00000004UL | ||
107 | #define LNK_FILE__CREATE 0x00000008UL | ||
108 | #define LNK_FILE__GETATTR 0x00000010UL | ||
109 | #define LNK_FILE__SETATTR 0x00000020UL | ||
110 | #define LNK_FILE__LOCK 0x00000040UL | ||
111 | #define LNK_FILE__RELABELFROM 0x00000080UL | ||
112 | #define LNK_FILE__RELABELTO 0x00000100UL | ||
113 | #define LNK_FILE__APPEND 0x00000200UL | ||
114 | #define LNK_FILE__UNLINK 0x00000400UL | ||
115 | #define LNK_FILE__LINK 0x00000800UL | ||
116 | #define LNK_FILE__RENAME 0x00001000UL | ||
117 | #define LNK_FILE__EXECUTE 0x00002000UL | ||
118 | #define LNK_FILE__SWAPON 0x00004000UL | ||
119 | #define LNK_FILE__QUOTAON 0x00008000UL | ||
120 | #define LNK_FILE__MOUNTON 0x00010000UL | ||
121 | #define CHR_FILE__IOCTL 0x00000001UL | ||
122 | #define CHR_FILE__READ 0x00000002UL | ||
123 | #define CHR_FILE__WRITE 0x00000004UL | ||
124 | #define CHR_FILE__CREATE 0x00000008UL | ||
125 | #define CHR_FILE__GETATTR 0x00000010UL | ||
126 | #define CHR_FILE__SETATTR 0x00000020UL | ||
127 | #define CHR_FILE__LOCK 0x00000040UL | ||
128 | #define CHR_FILE__RELABELFROM 0x00000080UL | ||
129 | #define CHR_FILE__RELABELTO 0x00000100UL | ||
130 | #define CHR_FILE__APPEND 0x00000200UL | ||
131 | #define CHR_FILE__UNLINK 0x00000400UL | ||
132 | #define CHR_FILE__LINK 0x00000800UL | ||
133 | #define CHR_FILE__RENAME 0x00001000UL | ||
134 | #define CHR_FILE__EXECUTE 0x00002000UL | ||
135 | #define CHR_FILE__SWAPON 0x00004000UL | ||
136 | #define CHR_FILE__QUOTAON 0x00008000UL | ||
137 | #define CHR_FILE__MOUNTON 0x00010000UL | ||
138 | #define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL | ||
139 | #define CHR_FILE__ENTRYPOINT 0x00040000UL | ||
140 | #define CHR_FILE__EXECMOD 0x00080000UL | ||
141 | #define CHR_FILE__OPEN 0x00100000UL | ||
142 | #define BLK_FILE__IOCTL 0x00000001UL | ||
143 | #define BLK_FILE__READ 0x00000002UL | ||
144 | #define BLK_FILE__WRITE 0x00000004UL | ||
145 | #define BLK_FILE__CREATE 0x00000008UL | ||
146 | #define BLK_FILE__GETATTR 0x00000010UL | ||
147 | #define BLK_FILE__SETATTR 0x00000020UL | ||
148 | #define BLK_FILE__LOCK 0x00000040UL | ||
149 | #define BLK_FILE__RELABELFROM 0x00000080UL | ||
150 | #define BLK_FILE__RELABELTO 0x00000100UL | ||
151 | #define BLK_FILE__APPEND 0x00000200UL | ||
152 | #define BLK_FILE__UNLINK 0x00000400UL | ||
153 | #define BLK_FILE__LINK 0x00000800UL | ||
154 | #define BLK_FILE__RENAME 0x00001000UL | ||
155 | #define BLK_FILE__EXECUTE 0x00002000UL | ||
156 | #define BLK_FILE__SWAPON 0x00004000UL | ||
157 | #define BLK_FILE__QUOTAON 0x00008000UL | ||
158 | #define BLK_FILE__MOUNTON 0x00010000UL | ||
159 | #define BLK_FILE__OPEN 0x00020000UL | ||
160 | #define SOCK_FILE__IOCTL 0x00000001UL | ||
161 | #define SOCK_FILE__READ 0x00000002UL | ||
162 | #define SOCK_FILE__WRITE 0x00000004UL | ||
163 | #define SOCK_FILE__CREATE 0x00000008UL | ||
164 | #define SOCK_FILE__GETATTR 0x00000010UL | ||
165 | #define SOCK_FILE__SETATTR 0x00000020UL | ||
166 | #define SOCK_FILE__LOCK 0x00000040UL | ||
167 | #define SOCK_FILE__RELABELFROM 0x00000080UL | ||
168 | #define SOCK_FILE__RELABELTO 0x00000100UL | ||
169 | #define SOCK_FILE__APPEND 0x00000200UL | ||
170 | #define SOCK_FILE__UNLINK 0x00000400UL | ||
171 | #define SOCK_FILE__LINK 0x00000800UL | ||
172 | #define SOCK_FILE__RENAME 0x00001000UL | ||
173 | #define SOCK_FILE__EXECUTE 0x00002000UL | ||
174 | #define SOCK_FILE__SWAPON 0x00004000UL | ||
175 | #define SOCK_FILE__QUOTAON 0x00008000UL | ||
176 | #define SOCK_FILE__MOUNTON 0x00010000UL | ||
177 | #define SOCK_FILE__OPEN 0x00020000UL | ||
178 | #define FIFO_FILE__IOCTL 0x00000001UL | ||
179 | #define FIFO_FILE__READ 0x00000002UL | ||
180 | #define FIFO_FILE__WRITE 0x00000004UL | ||
181 | #define FIFO_FILE__CREATE 0x00000008UL | ||
182 | #define FIFO_FILE__GETATTR 0x00000010UL | ||
183 | #define FIFO_FILE__SETATTR 0x00000020UL | ||
184 | #define FIFO_FILE__LOCK 0x00000040UL | ||
185 | #define FIFO_FILE__RELABELFROM 0x00000080UL | ||
186 | #define FIFO_FILE__RELABELTO 0x00000100UL | ||
187 | #define FIFO_FILE__APPEND 0x00000200UL | ||
188 | #define FIFO_FILE__UNLINK 0x00000400UL | ||
189 | #define FIFO_FILE__LINK 0x00000800UL | ||
190 | #define FIFO_FILE__RENAME 0x00001000UL | ||
191 | #define FIFO_FILE__EXECUTE 0x00002000UL | ||
192 | #define FIFO_FILE__SWAPON 0x00004000UL | ||
193 | #define FIFO_FILE__QUOTAON 0x00008000UL | ||
194 | #define FIFO_FILE__MOUNTON 0x00010000UL | ||
195 | #define FIFO_FILE__OPEN 0x00020000UL | ||
196 | #define FD__USE 0x00000001UL | ||
197 | #define SOCKET__IOCTL 0x00000001UL | ||
198 | #define SOCKET__READ 0x00000002UL | ||
199 | #define SOCKET__WRITE 0x00000004UL | ||
200 | #define SOCKET__CREATE 0x00000008UL | ||
201 | #define SOCKET__GETATTR 0x00000010UL | ||
202 | #define SOCKET__SETATTR 0x00000020UL | ||
203 | #define SOCKET__LOCK 0x00000040UL | ||
204 | #define SOCKET__RELABELFROM 0x00000080UL | ||
205 | #define SOCKET__RELABELTO 0x00000100UL | ||
206 | #define SOCKET__APPEND 0x00000200UL | ||
207 | #define SOCKET__BIND 0x00000400UL | ||
208 | #define SOCKET__CONNECT 0x00000800UL | ||
209 | #define SOCKET__LISTEN 0x00001000UL | ||
210 | #define SOCKET__ACCEPT 0x00002000UL | ||
211 | #define SOCKET__GETOPT 0x00004000UL | ||
212 | #define SOCKET__SETOPT 0x00008000UL | ||
213 | #define SOCKET__SHUTDOWN 0x00010000UL | ||
214 | #define SOCKET__RECVFROM 0x00020000UL | ||
215 | #define SOCKET__SENDTO 0x00040000UL | ||
216 | #define SOCKET__RECV_MSG 0x00080000UL | ||
217 | #define SOCKET__SEND_MSG 0x00100000UL | ||
218 | #define SOCKET__NAME_BIND 0x00200000UL | ||
219 | #define TCP_SOCKET__IOCTL 0x00000001UL | ||
220 | #define TCP_SOCKET__READ 0x00000002UL | ||
221 | #define TCP_SOCKET__WRITE 0x00000004UL | ||
222 | #define TCP_SOCKET__CREATE 0x00000008UL | ||
223 | #define TCP_SOCKET__GETATTR 0x00000010UL | ||
224 | #define TCP_SOCKET__SETATTR 0x00000020UL | ||
225 | #define TCP_SOCKET__LOCK 0x00000040UL | ||
226 | #define TCP_SOCKET__RELABELFROM 0x00000080UL | ||
227 | #define TCP_SOCKET__RELABELTO 0x00000100UL | ||
228 | #define TCP_SOCKET__APPEND 0x00000200UL | ||
229 | #define TCP_SOCKET__BIND 0x00000400UL | ||
230 | #define TCP_SOCKET__CONNECT 0x00000800UL | ||
231 | #define TCP_SOCKET__LISTEN 0x00001000UL | ||
232 | #define TCP_SOCKET__ACCEPT 0x00002000UL | ||
233 | #define TCP_SOCKET__GETOPT 0x00004000UL | ||
234 | #define TCP_SOCKET__SETOPT 0x00008000UL | ||
235 | #define TCP_SOCKET__SHUTDOWN 0x00010000UL | ||
236 | #define TCP_SOCKET__RECVFROM 0x00020000UL | ||
237 | #define TCP_SOCKET__SENDTO 0x00040000UL | ||
238 | #define TCP_SOCKET__RECV_MSG 0x00080000UL | ||
239 | #define TCP_SOCKET__SEND_MSG 0x00100000UL | ||
240 | #define TCP_SOCKET__NAME_BIND 0x00200000UL | ||
241 | #define TCP_SOCKET__CONNECTTO 0x00400000UL | ||
242 | #define TCP_SOCKET__NEWCONN 0x00800000UL | ||
243 | #define TCP_SOCKET__ACCEPTFROM 0x01000000UL | ||
244 | #define TCP_SOCKET__NODE_BIND 0x02000000UL | ||
245 | #define TCP_SOCKET__NAME_CONNECT 0x04000000UL | ||
246 | #define UDP_SOCKET__IOCTL 0x00000001UL | ||
247 | #define UDP_SOCKET__READ 0x00000002UL | ||
248 | #define UDP_SOCKET__WRITE 0x00000004UL | ||
249 | #define UDP_SOCKET__CREATE 0x00000008UL | ||
250 | #define UDP_SOCKET__GETATTR 0x00000010UL | ||
251 | #define UDP_SOCKET__SETATTR 0x00000020UL | ||
252 | #define UDP_SOCKET__LOCK 0x00000040UL | ||
253 | #define UDP_SOCKET__RELABELFROM 0x00000080UL | ||
254 | #define UDP_SOCKET__RELABELTO 0x00000100UL | ||
255 | #define UDP_SOCKET__APPEND 0x00000200UL | ||
256 | #define UDP_SOCKET__BIND 0x00000400UL | ||
257 | #define UDP_SOCKET__CONNECT 0x00000800UL | ||
258 | #define UDP_SOCKET__LISTEN 0x00001000UL | ||
259 | #define UDP_SOCKET__ACCEPT 0x00002000UL | ||
260 | #define UDP_SOCKET__GETOPT 0x00004000UL | ||
261 | #define UDP_SOCKET__SETOPT 0x00008000UL | ||
262 | #define UDP_SOCKET__SHUTDOWN 0x00010000UL | ||
263 | #define UDP_SOCKET__RECVFROM 0x00020000UL | ||
264 | #define UDP_SOCKET__SENDTO 0x00040000UL | ||
265 | #define UDP_SOCKET__RECV_MSG 0x00080000UL | ||
266 | #define UDP_SOCKET__SEND_MSG 0x00100000UL | ||
267 | #define UDP_SOCKET__NAME_BIND 0x00200000UL | ||
268 | #define UDP_SOCKET__NODE_BIND 0x00400000UL | ||
269 | #define RAWIP_SOCKET__IOCTL 0x00000001UL | ||
270 | #define RAWIP_SOCKET__READ 0x00000002UL | ||
271 | #define RAWIP_SOCKET__WRITE 0x00000004UL | ||
272 | #define RAWIP_SOCKET__CREATE 0x00000008UL | ||
273 | #define RAWIP_SOCKET__GETATTR 0x00000010UL | ||
274 | #define RAWIP_SOCKET__SETATTR 0x00000020UL | ||
275 | #define RAWIP_SOCKET__LOCK 0x00000040UL | ||
276 | #define RAWIP_SOCKET__RELABELFROM 0x00000080UL | ||
277 | #define RAWIP_SOCKET__RELABELTO 0x00000100UL | ||
278 | #define RAWIP_SOCKET__APPEND 0x00000200UL | ||
279 | #define RAWIP_SOCKET__BIND 0x00000400UL | ||
280 | #define RAWIP_SOCKET__CONNECT 0x00000800UL | ||
281 | #define RAWIP_SOCKET__LISTEN 0x00001000UL | ||
282 | #define RAWIP_SOCKET__ACCEPT 0x00002000UL | ||
283 | #define RAWIP_SOCKET__GETOPT 0x00004000UL | ||
284 | #define RAWIP_SOCKET__SETOPT 0x00008000UL | ||
285 | #define RAWIP_SOCKET__SHUTDOWN 0x00010000UL | ||
286 | #define RAWIP_SOCKET__RECVFROM 0x00020000UL | ||
287 | #define RAWIP_SOCKET__SENDTO 0x00040000UL | ||
288 | #define RAWIP_SOCKET__RECV_MSG 0x00080000UL | ||
289 | #define RAWIP_SOCKET__SEND_MSG 0x00100000UL | ||
290 | #define RAWIP_SOCKET__NAME_BIND 0x00200000UL | ||
291 | #define RAWIP_SOCKET__NODE_BIND 0x00400000UL | ||
292 | #define NODE__TCP_RECV 0x00000001UL | ||
293 | #define NODE__TCP_SEND 0x00000002UL | ||
294 | #define NODE__UDP_RECV 0x00000004UL | ||
295 | #define NODE__UDP_SEND 0x00000008UL | ||
296 | #define NODE__RAWIP_RECV 0x00000010UL | ||
297 | #define NODE__RAWIP_SEND 0x00000020UL | ||
298 | #define NODE__ENFORCE_DEST 0x00000040UL | ||
299 | #define NODE__DCCP_RECV 0x00000080UL | ||
300 | #define NODE__DCCP_SEND 0x00000100UL | ||
301 | #define NODE__RECVFROM 0x00000200UL | ||
302 | #define NODE__SENDTO 0x00000400UL | ||
303 | #define NETIF__TCP_RECV 0x00000001UL | ||
304 | #define NETIF__TCP_SEND 0x00000002UL | ||
305 | #define NETIF__UDP_RECV 0x00000004UL | ||
306 | #define NETIF__UDP_SEND 0x00000008UL | ||
307 | #define NETIF__RAWIP_RECV 0x00000010UL | ||
308 | #define NETIF__RAWIP_SEND 0x00000020UL | ||
309 | #define NETIF__DCCP_RECV 0x00000040UL | ||
310 | #define NETIF__DCCP_SEND 0x00000080UL | ||
311 | #define NETIF__INGRESS 0x00000100UL | ||
312 | #define NETIF__EGRESS 0x00000200UL | ||
313 | #define NETLINK_SOCKET__IOCTL 0x00000001UL | ||
314 | #define NETLINK_SOCKET__READ 0x00000002UL | ||
315 | #define NETLINK_SOCKET__WRITE 0x00000004UL | ||
316 | #define NETLINK_SOCKET__CREATE 0x00000008UL | ||
317 | #define NETLINK_SOCKET__GETATTR 0x00000010UL | ||
318 | #define NETLINK_SOCKET__SETATTR 0x00000020UL | ||
319 | #define NETLINK_SOCKET__LOCK 0x00000040UL | ||
320 | #define NETLINK_SOCKET__RELABELFROM 0x00000080UL | ||
321 | #define NETLINK_SOCKET__RELABELTO 0x00000100UL | ||
322 | #define NETLINK_SOCKET__APPEND 0x00000200UL | ||
323 | #define NETLINK_SOCKET__BIND 0x00000400UL | ||
324 | #define NETLINK_SOCKET__CONNECT 0x00000800UL | ||
325 | #define NETLINK_SOCKET__LISTEN 0x00001000UL | ||
326 | #define NETLINK_SOCKET__ACCEPT 0x00002000UL | ||
327 | #define NETLINK_SOCKET__GETOPT 0x00004000UL | ||
328 | #define NETLINK_SOCKET__SETOPT 0x00008000UL | ||
329 | #define NETLINK_SOCKET__SHUTDOWN 0x00010000UL | ||
330 | #define NETLINK_SOCKET__RECVFROM 0x00020000UL | ||
331 | #define NETLINK_SOCKET__SENDTO 0x00040000UL | ||
332 | #define NETLINK_SOCKET__RECV_MSG 0x00080000UL | ||
333 | #define NETLINK_SOCKET__SEND_MSG 0x00100000UL | ||
334 | #define NETLINK_SOCKET__NAME_BIND 0x00200000UL | ||
335 | #define PACKET_SOCKET__IOCTL 0x00000001UL | ||
336 | #define PACKET_SOCKET__READ 0x00000002UL | ||
337 | #define PACKET_SOCKET__WRITE 0x00000004UL | ||
338 | #define PACKET_SOCKET__CREATE 0x00000008UL | ||
339 | #define PACKET_SOCKET__GETATTR 0x00000010UL | ||
340 | #define PACKET_SOCKET__SETATTR 0x00000020UL | ||
341 | #define PACKET_SOCKET__LOCK 0x00000040UL | ||
342 | #define PACKET_SOCKET__RELABELFROM 0x00000080UL | ||
343 | #define PACKET_SOCKET__RELABELTO 0x00000100UL | ||
344 | #define PACKET_SOCKET__APPEND 0x00000200UL | ||
345 | #define PACKET_SOCKET__BIND 0x00000400UL | ||
346 | #define PACKET_SOCKET__CONNECT 0x00000800UL | ||
347 | #define PACKET_SOCKET__LISTEN 0x00001000UL | ||
348 | #define PACKET_SOCKET__ACCEPT 0x00002000UL | ||
349 | #define PACKET_SOCKET__GETOPT 0x00004000UL | ||
350 | #define PACKET_SOCKET__SETOPT 0x00008000UL | ||
351 | #define PACKET_SOCKET__SHUTDOWN 0x00010000UL | ||
352 | #define PACKET_SOCKET__RECVFROM 0x00020000UL | ||
353 | #define PACKET_SOCKET__SENDTO 0x00040000UL | ||
354 | #define PACKET_SOCKET__RECV_MSG 0x00080000UL | ||
355 | #define PACKET_SOCKET__SEND_MSG 0x00100000UL | ||
356 | #define PACKET_SOCKET__NAME_BIND 0x00200000UL | ||
357 | #define KEY_SOCKET__IOCTL 0x00000001UL | ||
358 | #define KEY_SOCKET__READ 0x00000002UL | ||
359 | #define KEY_SOCKET__WRITE 0x00000004UL | ||
360 | #define KEY_SOCKET__CREATE 0x00000008UL | ||
361 | #define KEY_SOCKET__GETATTR 0x00000010UL | ||
362 | #define KEY_SOCKET__SETATTR 0x00000020UL | ||
363 | #define KEY_SOCKET__LOCK 0x00000040UL | ||
364 | #define KEY_SOCKET__RELABELFROM 0x00000080UL | ||
365 | #define KEY_SOCKET__RELABELTO 0x00000100UL | ||
366 | #define KEY_SOCKET__APPEND 0x00000200UL | ||
367 | #define KEY_SOCKET__BIND 0x00000400UL | ||
368 | #define KEY_SOCKET__CONNECT 0x00000800UL | ||
369 | #define KEY_SOCKET__LISTEN 0x00001000UL | ||
370 | #define KEY_SOCKET__ACCEPT 0x00002000UL | ||
371 | #define KEY_SOCKET__GETOPT 0x00004000UL | ||
372 | #define KEY_SOCKET__SETOPT 0x00008000UL | ||
373 | #define KEY_SOCKET__SHUTDOWN 0x00010000UL | ||
374 | #define KEY_SOCKET__RECVFROM 0x00020000UL | ||
375 | #define KEY_SOCKET__SENDTO 0x00040000UL | ||
376 | #define KEY_SOCKET__RECV_MSG 0x00080000UL | ||
377 | #define KEY_SOCKET__SEND_MSG 0x00100000UL | ||
378 | #define KEY_SOCKET__NAME_BIND 0x00200000UL | ||
379 | #define UNIX_STREAM_SOCKET__IOCTL 0x00000001UL | ||
380 | #define UNIX_STREAM_SOCKET__READ 0x00000002UL | ||
381 | #define UNIX_STREAM_SOCKET__WRITE 0x00000004UL | ||
382 | #define UNIX_STREAM_SOCKET__CREATE 0x00000008UL | ||
383 | #define UNIX_STREAM_SOCKET__GETATTR 0x00000010UL | ||
384 | #define UNIX_STREAM_SOCKET__SETATTR 0x00000020UL | ||
385 | #define UNIX_STREAM_SOCKET__LOCK 0x00000040UL | ||
386 | #define UNIX_STREAM_SOCKET__RELABELFROM 0x00000080UL | ||
387 | #define UNIX_STREAM_SOCKET__RELABELTO 0x00000100UL | ||
388 | #define UNIX_STREAM_SOCKET__APPEND 0x00000200UL | ||
389 | #define UNIX_STREAM_SOCKET__BIND 0x00000400UL | ||
390 | #define UNIX_STREAM_SOCKET__CONNECT 0x00000800UL | ||
391 | #define UNIX_STREAM_SOCKET__LISTEN 0x00001000UL | ||
392 | #define UNIX_STREAM_SOCKET__ACCEPT 0x00002000UL | ||
393 | #define UNIX_STREAM_SOCKET__GETOPT 0x00004000UL | ||
394 | #define UNIX_STREAM_SOCKET__SETOPT 0x00008000UL | ||
395 | #define UNIX_STREAM_SOCKET__SHUTDOWN 0x00010000UL | ||
396 | #define UNIX_STREAM_SOCKET__RECVFROM 0x00020000UL | ||
397 | #define UNIX_STREAM_SOCKET__SENDTO 0x00040000UL | ||
398 | #define UNIX_STREAM_SOCKET__RECV_MSG 0x00080000UL | ||
399 | #define UNIX_STREAM_SOCKET__SEND_MSG 0x00100000UL | ||
400 | #define UNIX_STREAM_SOCKET__NAME_BIND 0x00200000UL | ||
401 | #define UNIX_STREAM_SOCKET__CONNECTTO 0x00400000UL | ||
402 | #define UNIX_STREAM_SOCKET__NEWCONN 0x00800000UL | ||
403 | #define UNIX_STREAM_SOCKET__ACCEPTFROM 0x01000000UL | ||
404 | #define UNIX_DGRAM_SOCKET__IOCTL 0x00000001UL | ||
405 | #define UNIX_DGRAM_SOCKET__READ 0x00000002UL | ||
406 | #define UNIX_DGRAM_SOCKET__WRITE 0x00000004UL | ||
407 | #define UNIX_DGRAM_SOCKET__CREATE 0x00000008UL | ||
408 | #define UNIX_DGRAM_SOCKET__GETATTR 0x00000010UL | ||
409 | #define UNIX_DGRAM_SOCKET__SETATTR 0x00000020UL | ||
410 | #define UNIX_DGRAM_SOCKET__LOCK 0x00000040UL | ||
411 | #define UNIX_DGRAM_SOCKET__RELABELFROM 0x00000080UL | ||
412 | #define UNIX_DGRAM_SOCKET__RELABELTO 0x00000100UL | ||
413 | #define UNIX_DGRAM_SOCKET__APPEND 0x00000200UL | ||
414 | #define UNIX_DGRAM_SOCKET__BIND 0x00000400UL | ||
415 | #define UNIX_DGRAM_SOCKET__CONNECT 0x00000800UL | ||
416 | #define UNIX_DGRAM_SOCKET__LISTEN 0x00001000UL | ||
417 | #define UNIX_DGRAM_SOCKET__ACCEPT 0x00002000UL | ||
418 | #define UNIX_DGRAM_SOCKET__GETOPT 0x00004000UL | ||
419 | #define UNIX_DGRAM_SOCKET__SETOPT 0x00008000UL | ||
420 | #define UNIX_DGRAM_SOCKET__SHUTDOWN 0x00010000UL | ||
421 | #define UNIX_DGRAM_SOCKET__RECVFROM 0x00020000UL | ||
422 | #define UNIX_DGRAM_SOCKET__SENDTO 0x00040000UL | ||
423 | #define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL | ||
424 | #define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL | ||
425 | #define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL | ||
426 | #define PROCESS__FORK 0x00000001UL | ||
427 | #define PROCESS__TRANSITION 0x00000002UL | ||
428 | #define PROCESS__SIGCHLD 0x00000004UL | ||
429 | #define PROCESS__SIGKILL 0x00000008UL | ||
430 | #define PROCESS__SIGSTOP 0x00000010UL | ||
431 | #define PROCESS__SIGNULL 0x00000020UL | ||
432 | #define PROCESS__SIGNAL 0x00000040UL | ||
433 | #define PROCESS__PTRACE 0x00000080UL | ||
434 | #define PROCESS__GETSCHED 0x00000100UL | ||
435 | #define PROCESS__SETSCHED 0x00000200UL | ||
436 | #define PROCESS__GETSESSION 0x00000400UL | ||
437 | #define PROCESS__GETPGID 0x00000800UL | ||
438 | #define PROCESS__SETPGID 0x00001000UL | ||
439 | #define PROCESS__GETCAP 0x00002000UL | ||
440 | #define PROCESS__SETCAP 0x00004000UL | ||
441 | #define PROCESS__SHARE 0x00008000UL | ||
442 | #define PROCESS__GETATTR 0x00010000UL | ||
443 | #define PROCESS__SETEXEC 0x00020000UL | ||
444 | #define PROCESS__SETFSCREATE 0x00040000UL | ||
445 | #define PROCESS__NOATSECURE 0x00080000UL | ||
446 | #define PROCESS__SIGINH 0x00100000UL | ||
447 | #define PROCESS__SETRLIMIT 0x00200000UL | ||
448 | #define PROCESS__RLIMITINH 0x00400000UL | ||
449 | #define PROCESS__DYNTRANSITION 0x00800000UL | ||
450 | #define PROCESS__SETCURRENT 0x01000000UL | ||
451 | #define PROCESS__EXECMEM 0x02000000UL | ||
452 | #define PROCESS__EXECSTACK 0x04000000UL | ||
453 | #define PROCESS__EXECHEAP 0x08000000UL | ||
454 | #define PROCESS__SETKEYCREATE 0x10000000UL | ||
455 | #define PROCESS__SETSOCKCREATE 0x20000000UL | ||
456 | #define IPC__CREATE 0x00000001UL | ||
457 | #define IPC__DESTROY 0x00000002UL | ||
458 | #define IPC__GETATTR 0x00000004UL | ||
459 | #define IPC__SETATTR 0x00000008UL | ||
460 | #define IPC__READ 0x00000010UL | ||
461 | #define IPC__WRITE 0x00000020UL | ||
462 | #define IPC__ASSOCIATE 0x00000040UL | ||
463 | #define IPC__UNIX_READ 0x00000080UL | ||
464 | #define IPC__UNIX_WRITE 0x00000100UL | ||
465 | #define SEM__CREATE 0x00000001UL | ||
466 | #define SEM__DESTROY 0x00000002UL | ||
467 | #define SEM__GETATTR 0x00000004UL | ||
468 | #define SEM__SETATTR 0x00000008UL | ||
469 | #define SEM__READ 0x00000010UL | ||
470 | #define SEM__WRITE 0x00000020UL | ||
471 | #define SEM__ASSOCIATE 0x00000040UL | ||
472 | #define SEM__UNIX_READ 0x00000080UL | ||
473 | #define SEM__UNIX_WRITE 0x00000100UL | ||
474 | #define MSGQ__CREATE 0x00000001UL | ||
475 | #define MSGQ__DESTROY 0x00000002UL | ||
476 | #define MSGQ__GETATTR 0x00000004UL | ||
477 | #define MSGQ__SETATTR 0x00000008UL | ||
478 | #define MSGQ__READ 0x00000010UL | ||
479 | #define MSGQ__WRITE 0x00000020UL | ||
480 | #define MSGQ__ASSOCIATE 0x00000040UL | ||
481 | #define MSGQ__UNIX_READ 0x00000080UL | ||
482 | #define MSGQ__UNIX_WRITE 0x00000100UL | ||
483 | #define MSGQ__ENQUEUE 0x00000200UL | ||
484 | #define MSG__SEND 0x00000001UL | ||
485 | #define MSG__RECEIVE 0x00000002UL | ||
486 | #define SHM__CREATE 0x00000001UL | ||
487 | #define SHM__DESTROY 0x00000002UL | ||
488 | #define SHM__GETATTR 0x00000004UL | ||
489 | #define SHM__SETATTR 0x00000008UL | ||
490 | #define SHM__READ 0x00000010UL | ||
491 | #define SHM__WRITE 0x00000020UL | ||
492 | #define SHM__ASSOCIATE 0x00000040UL | ||
493 | #define SHM__UNIX_READ 0x00000080UL | ||
494 | #define SHM__UNIX_WRITE 0x00000100UL | ||
495 | #define SHM__LOCK 0x00000200UL | ||
496 | #define SECURITY__COMPUTE_AV 0x00000001UL | ||
497 | #define SECURITY__COMPUTE_CREATE 0x00000002UL | ||
498 | #define SECURITY__COMPUTE_MEMBER 0x00000004UL | ||
499 | #define SECURITY__CHECK_CONTEXT 0x00000008UL | ||
500 | #define SECURITY__LOAD_POLICY 0x00000010UL | ||
501 | #define SECURITY__COMPUTE_RELABEL 0x00000020UL | ||
502 | #define SECURITY__COMPUTE_USER 0x00000040UL | ||
503 | #define SECURITY__SETENFORCE 0x00000080UL | ||
504 | #define SECURITY__SETBOOL 0x00000100UL | ||
505 | #define SECURITY__SETSECPARAM 0x00000200UL | ||
506 | #define SECURITY__SETCHECKREQPROT 0x00000400UL | ||
507 | #define SYSTEM__IPC_INFO 0x00000001UL | ||
508 | #define SYSTEM__SYSLOG_READ 0x00000002UL | ||
509 | #define SYSTEM__SYSLOG_MOD 0x00000004UL | ||
510 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL | ||
511 | #define CAPABILITY__CHOWN 0x00000001UL | ||
512 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL | ||
513 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL | ||
514 | #define CAPABILITY__FOWNER 0x00000008UL | ||
515 | #define CAPABILITY__FSETID 0x00000010UL | ||
516 | #define CAPABILITY__KILL 0x00000020UL | ||
517 | #define CAPABILITY__SETGID 0x00000040UL | ||
518 | #define CAPABILITY__SETUID 0x00000080UL | ||
519 | #define CAPABILITY__SETPCAP 0x00000100UL | ||
520 | #define CAPABILITY__LINUX_IMMUTABLE 0x00000200UL | ||
521 | #define CAPABILITY__NET_BIND_SERVICE 0x00000400UL | ||
522 | #define CAPABILITY__NET_BROADCAST 0x00000800UL | ||
523 | #define CAPABILITY__NET_ADMIN 0x00001000UL | ||
524 | #define CAPABILITY__NET_RAW 0x00002000UL | ||
525 | #define CAPABILITY__IPC_LOCK 0x00004000UL | ||
526 | #define CAPABILITY__IPC_OWNER 0x00008000UL | ||
527 | #define CAPABILITY__SYS_MODULE 0x00010000UL | ||
528 | #define CAPABILITY__SYS_RAWIO 0x00020000UL | ||
529 | #define CAPABILITY__SYS_CHROOT 0x00040000UL | ||
530 | #define CAPABILITY__SYS_PTRACE 0x00080000UL | ||
531 | #define CAPABILITY__SYS_PACCT 0x00100000UL | ||
532 | #define CAPABILITY__SYS_ADMIN 0x00200000UL | ||
533 | #define CAPABILITY__SYS_BOOT 0x00400000UL | ||
534 | #define CAPABILITY__SYS_NICE 0x00800000UL | ||
535 | #define CAPABILITY__SYS_RESOURCE 0x01000000UL | ||
536 | #define CAPABILITY__SYS_TIME 0x02000000UL | ||
537 | #define CAPABILITY__SYS_TTY_CONFIG 0x04000000UL | ||
538 | #define CAPABILITY__MKNOD 0x08000000UL | ||
539 | #define CAPABILITY__LEASE 0x10000000UL | ||
540 | #define CAPABILITY__AUDIT_WRITE 0x20000000UL | ||
541 | #define CAPABILITY__AUDIT_CONTROL 0x40000000UL | ||
542 | #define CAPABILITY__SETFCAP 0x80000000UL | ||
543 | #define CAPABILITY2__MAC_OVERRIDE 0x00000001UL | ||
544 | #define CAPABILITY2__MAC_ADMIN 0x00000002UL | ||
545 | #define NETLINK_ROUTE_SOCKET__IOCTL 0x00000001UL | ||
546 | #define NETLINK_ROUTE_SOCKET__READ 0x00000002UL | ||
547 | #define NETLINK_ROUTE_SOCKET__WRITE 0x00000004UL | ||
548 | #define NETLINK_ROUTE_SOCKET__CREATE 0x00000008UL | ||
549 | #define NETLINK_ROUTE_SOCKET__GETATTR 0x00000010UL | ||
550 | #define NETLINK_ROUTE_SOCKET__SETATTR 0x00000020UL | ||
551 | #define NETLINK_ROUTE_SOCKET__LOCK 0x00000040UL | ||
552 | #define NETLINK_ROUTE_SOCKET__RELABELFROM 0x00000080UL | ||
553 | #define NETLINK_ROUTE_SOCKET__RELABELTO 0x00000100UL | ||
554 | #define NETLINK_ROUTE_SOCKET__APPEND 0x00000200UL | ||
555 | #define NETLINK_ROUTE_SOCKET__BIND 0x00000400UL | ||
556 | #define NETLINK_ROUTE_SOCKET__CONNECT 0x00000800UL | ||
557 | #define NETLINK_ROUTE_SOCKET__LISTEN 0x00001000UL | ||
558 | #define NETLINK_ROUTE_SOCKET__ACCEPT 0x00002000UL | ||
559 | #define NETLINK_ROUTE_SOCKET__GETOPT 0x00004000UL | ||
560 | #define NETLINK_ROUTE_SOCKET__SETOPT 0x00008000UL | ||
561 | #define NETLINK_ROUTE_SOCKET__SHUTDOWN 0x00010000UL | ||
562 | #define NETLINK_ROUTE_SOCKET__RECVFROM 0x00020000UL | ||
563 | #define NETLINK_ROUTE_SOCKET__SENDTO 0x00040000UL | ||
564 | #define NETLINK_ROUTE_SOCKET__RECV_MSG 0x00080000UL | ||
565 | #define NETLINK_ROUTE_SOCKET__SEND_MSG 0x00100000UL | ||
566 | #define NETLINK_ROUTE_SOCKET__NAME_BIND 0x00200000UL | ||
567 | #define NETLINK_ROUTE_SOCKET__NLMSG_READ 0x00400000UL | ||
568 | #define NETLINK_ROUTE_SOCKET__NLMSG_WRITE 0x00800000UL | ||
569 | #define NETLINK_FIREWALL_SOCKET__IOCTL 0x00000001UL | ||
570 | #define NETLINK_FIREWALL_SOCKET__READ 0x00000002UL | ||
571 | #define NETLINK_FIREWALL_SOCKET__WRITE 0x00000004UL | ||
572 | #define NETLINK_FIREWALL_SOCKET__CREATE 0x00000008UL | ||
573 | #define NETLINK_FIREWALL_SOCKET__GETATTR 0x00000010UL | ||
574 | #define NETLINK_FIREWALL_SOCKET__SETATTR 0x00000020UL | ||
575 | #define NETLINK_FIREWALL_SOCKET__LOCK 0x00000040UL | ||
576 | #define NETLINK_FIREWALL_SOCKET__RELABELFROM 0x00000080UL | ||
577 | #define NETLINK_FIREWALL_SOCKET__RELABELTO 0x00000100UL | ||
578 | #define NETLINK_FIREWALL_SOCKET__APPEND 0x00000200UL | ||
579 | #define NETLINK_FIREWALL_SOCKET__BIND 0x00000400UL | ||
580 | #define NETLINK_FIREWALL_SOCKET__CONNECT 0x00000800UL | ||
581 | #define NETLINK_FIREWALL_SOCKET__LISTEN 0x00001000UL | ||
582 | #define NETLINK_FIREWALL_SOCKET__ACCEPT 0x00002000UL | ||
583 | #define NETLINK_FIREWALL_SOCKET__GETOPT 0x00004000UL | ||
584 | #define NETLINK_FIREWALL_SOCKET__SETOPT 0x00008000UL | ||
585 | #define NETLINK_FIREWALL_SOCKET__SHUTDOWN 0x00010000UL | ||
586 | #define NETLINK_FIREWALL_SOCKET__RECVFROM 0x00020000UL | ||
587 | #define NETLINK_FIREWALL_SOCKET__SENDTO 0x00040000UL | ||
588 | #define NETLINK_FIREWALL_SOCKET__RECV_MSG 0x00080000UL | ||
589 | #define NETLINK_FIREWALL_SOCKET__SEND_MSG 0x00100000UL | ||
590 | #define NETLINK_FIREWALL_SOCKET__NAME_BIND 0x00200000UL | ||
591 | #define NETLINK_FIREWALL_SOCKET__NLMSG_READ 0x00400000UL | ||
592 | #define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE 0x00800000UL | ||
593 | #define NETLINK_TCPDIAG_SOCKET__IOCTL 0x00000001UL | ||
594 | #define NETLINK_TCPDIAG_SOCKET__READ 0x00000002UL | ||
595 | #define NETLINK_TCPDIAG_SOCKET__WRITE 0x00000004UL | ||
596 | #define NETLINK_TCPDIAG_SOCKET__CREATE 0x00000008UL | ||
597 | #define NETLINK_TCPDIAG_SOCKET__GETATTR 0x00000010UL | ||
598 | #define NETLINK_TCPDIAG_SOCKET__SETATTR 0x00000020UL | ||
599 | #define NETLINK_TCPDIAG_SOCKET__LOCK 0x00000040UL | ||
600 | #define NETLINK_TCPDIAG_SOCKET__RELABELFROM 0x00000080UL | ||
601 | #define NETLINK_TCPDIAG_SOCKET__RELABELTO 0x00000100UL | ||
602 | #define NETLINK_TCPDIAG_SOCKET__APPEND 0x00000200UL | ||
603 | #define NETLINK_TCPDIAG_SOCKET__BIND 0x00000400UL | ||
604 | #define NETLINK_TCPDIAG_SOCKET__CONNECT 0x00000800UL | ||
605 | #define NETLINK_TCPDIAG_SOCKET__LISTEN 0x00001000UL | ||
606 | #define NETLINK_TCPDIAG_SOCKET__ACCEPT 0x00002000UL | ||
607 | #define NETLINK_TCPDIAG_SOCKET__GETOPT 0x00004000UL | ||
608 | #define NETLINK_TCPDIAG_SOCKET__SETOPT 0x00008000UL | ||
609 | #define NETLINK_TCPDIAG_SOCKET__SHUTDOWN 0x00010000UL | ||
610 | #define NETLINK_TCPDIAG_SOCKET__RECVFROM 0x00020000UL | ||
611 | #define NETLINK_TCPDIAG_SOCKET__SENDTO 0x00040000UL | ||
612 | #define NETLINK_TCPDIAG_SOCKET__RECV_MSG 0x00080000UL | ||
613 | #define NETLINK_TCPDIAG_SOCKET__SEND_MSG 0x00100000UL | ||
614 | #define NETLINK_TCPDIAG_SOCKET__NAME_BIND 0x00200000UL | ||
615 | #define NETLINK_TCPDIAG_SOCKET__NLMSG_READ 0x00400000UL | ||
616 | #define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE 0x00800000UL | ||
617 | #define NETLINK_NFLOG_SOCKET__IOCTL 0x00000001UL | ||
618 | #define NETLINK_NFLOG_SOCKET__READ 0x00000002UL | ||
619 | #define NETLINK_NFLOG_SOCKET__WRITE 0x00000004UL | ||
620 | #define NETLINK_NFLOG_SOCKET__CREATE 0x00000008UL | ||
621 | #define NETLINK_NFLOG_SOCKET__GETATTR 0x00000010UL | ||
622 | #define NETLINK_NFLOG_SOCKET__SETATTR 0x00000020UL | ||
623 | #define NETLINK_NFLOG_SOCKET__LOCK 0x00000040UL | ||
624 | #define NETLINK_NFLOG_SOCKET__RELABELFROM 0x00000080UL | ||
625 | #define NETLINK_NFLOG_SOCKET__RELABELTO 0x00000100UL | ||
626 | #define NETLINK_NFLOG_SOCKET__APPEND 0x00000200UL | ||
627 | #define NETLINK_NFLOG_SOCKET__BIND 0x00000400UL | ||
628 | #define NETLINK_NFLOG_SOCKET__CONNECT 0x00000800UL | ||
629 | #define NETLINK_NFLOG_SOCKET__LISTEN 0x00001000UL | ||
630 | #define NETLINK_NFLOG_SOCKET__ACCEPT 0x00002000UL | ||
631 | #define NETLINK_NFLOG_SOCKET__GETOPT 0x00004000UL | ||
632 | #define NETLINK_NFLOG_SOCKET__SETOPT 0x00008000UL | ||
633 | #define NETLINK_NFLOG_SOCKET__SHUTDOWN 0x00010000UL | ||
634 | #define NETLINK_NFLOG_SOCKET__RECVFROM 0x00020000UL | ||
635 | #define NETLINK_NFLOG_SOCKET__SENDTO 0x00040000UL | ||
636 | #define NETLINK_NFLOG_SOCKET__RECV_MSG 0x00080000UL | ||
637 | #define NETLINK_NFLOG_SOCKET__SEND_MSG 0x00100000UL | ||
638 | #define NETLINK_NFLOG_SOCKET__NAME_BIND 0x00200000UL | ||
639 | #define NETLINK_XFRM_SOCKET__IOCTL 0x00000001UL | ||
640 | #define NETLINK_XFRM_SOCKET__READ 0x00000002UL | ||
641 | #define NETLINK_XFRM_SOCKET__WRITE 0x00000004UL | ||
642 | #define NETLINK_XFRM_SOCKET__CREATE 0x00000008UL | ||
643 | #define NETLINK_XFRM_SOCKET__GETATTR 0x00000010UL | ||
644 | #define NETLINK_XFRM_SOCKET__SETATTR 0x00000020UL | ||
645 | #define NETLINK_XFRM_SOCKET__LOCK 0x00000040UL | ||
646 | #define NETLINK_XFRM_SOCKET__RELABELFROM 0x00000080UL | ||
647 | #define NETLINK_XFRM_SOCKET__RELABELTO 0x00000100UL | ||
648 | #define NETLINK_XFRM_SOCKET__APPEND 0x00000200UL | ||
649 | #define NETLINK_XFRM_SOCKET__BIND 0x00000400UL | ||
650 | #define NETLINK_XFRM_SOCKET__CONNECT 0x00000800UL | ||
651 | #define NETLINK_XFRM_SOCKET__LISTEN 0x00001000UL | ||
652 | #define NETLINK_XFRM_SOCKET__ACCEPT 0x00002000UL | ||
653 | #define NETLINK_XFRM_SOCKET__GETOPT 0x00004000UL | ||
654 | #define NETLINK_XFRM_SOCKET__SETOPT 0x00008000UL | ||
655 | #define NETLINK_XFRM_SOCKET__SHUTDOWN 0x00010000UL | ||
656 | #define NETLINK_XFRM_SOCKET__RECVFROM 0x00020000UL | ||
657 | #define NETLINK_XFRM_SOCKET__SENDTO 0x00040000UL | ||
658 | #define NETLINK_XFRM_SOCKET__RECV_MSG 0x00080000UL | ||
659 | #define NETLINK_XFRM_SOCKET__SEND_MSG 0x00100000UL | ||
660 | #define NETLINK_XFRM_SOCKET__NAME_BIND 0x00200000UL | ||
661 | #define NETLINK_XFRM_SOCKET__NLMSG_READ 0x00400000UL | ||
662 | #define NETLINK_XFRM_SOCKET__NLMSG_WRITE 0x00800000UL | ||
663 | #define NETLINK_SELINUX_SOCKET__IOCTL 0x00000001UL | ||
664 | #define NETLINK_SELINUX_SOCKET__READ 0x00000002UL | ||
665 | #define NETLINK_SELINUX_SOCKET__WRITE 0x00000004UL | ||
666 | #define NETLINK_SELINUX_SOCKET__CREATE 0x00000008UL | ||
667 | #define NETLINK_SELINUX_SOCKET__GETATTR 0x00000010UL | ||
668 | #define NETLINK_SELINUX_SOCKET__SETATTR 0x00000020UL | ||
669 | #define NETLINK_SELINUX_SOCKET__LOCK 0x00000040UL | ||
670 | #define NETLINK_SELINUX_SOCKET__RELABELFROM 0x00000080UL | ||
671 | #define NETLINK_SELINUX_SOCKET__RELABELTO 0x00000100UL | ||
672 | #define NETLINK_SELINUX_SOCKET__APPEND 0x00000200UL | ||
673 | #define NETLINK_SELINUX_SOCKET__BIND 0x00000400UL | ||
674 | #define NETLINK_SELINUX_SOCKET__CONNECT 0x00000800UL | ||
675 | #define NETLINK_SELINUX_SOCKET__LISTEN 0x00001000UL | ||
676 | #define NETLINK_SELINUX_SOCKET__ACCEPT 0x00002000UL | ||
677 | #define NETLINK_SELINUX_SOCKET__GETOPT 0x00004000UL | ||
678 | #define NETLINK_SELINUX_SOCKET__SETOPT 0x00008000UL | ||
679 | #define NETLINK_SELINUX_SOCKET__SHUTDOWN 0x00010000UL | ||
680 | #define NETLINK_SELINUX_SOCKET__RECVFROM 0x00020000UL | ||
681 | #define NETLINK_SELINUX_SOCKET__SENDTO 0x00040000UL | ||
682 | #define NETLINK_SELINUX_SOCKET__RECV_MSG 0x00080000UL | ||
683 | #define NETLINK_SELINUX_SOCKET__SEND_MSG 0x00100000UL | ||
684 | #define NETLINK_SELINUX_SOCKET__NAME_BIND 0x00200000UL | ||
685 | #define NETLINK_AUDIT_SOCKET__IOCTL 0x00000001UL | ||
686 | #define NETLINK_AUDIT_SOCKET__READ 0x00000002UL | ||
687 | #define NETLINK_AUDIT_SOCKET__WRITE 0x00000004UL | ||
688 | #define NETLINK_AUDIT_SOCKET__CREATE 0x00000008UL | ||
689 | #define NETLINK_AUDIT_SOCKET__GETATTR 0x00000010UL | ||
690 | #define NETLINK_AUDIT_SOCKET__SETATTR 0x00000020UL | ||
691 | #define NETLINK_AUDIT_SOCKET__LOCK 0x00000040UL | ||
692 | #define NETLINK_AUDIT_SOCKET__RELABELFROM 0x00000080UL | ||
693 | #define NETLINK_AUDIT_SOCKET__RELABELTO 0x00000100UL | ||
694 | #define NETLINK_AUDIT_SOCKET__APPEND 0x00000200UL | ||
695 | #define NETLINK_AUDIT_SOCKET__BIND 0x00000400UL | ||
696 | #define NETLINK_AUDIT_SOCKET__CONNECT 0x00000800UL | ||
697 | #define NETLINK_AUDIT_SOCKET__LISTEN 0x00001000UL | ||
698 | #define NETLINK_AUDIT_SOCKET__ACCEPT 0x00002000UL | ||
699 | #define NETLINK_AUDIT_SOCKET__GETOPT 0x00004000UL | ||
700 | #define NETLINK_AUDIT_SOCKET__SETOPT 0x00008000UL | ||
701 | #define NETLINK_AUDIT_SOCKET__SHUTDOWN 0x00010000UL | ||
702 | #define NETLINK_AUDIT_SOCKET__RECVFROM 0x00020000UL | ||
703 | #define NETLINK_AUDIT_SOCKET__SENDTO 0x00040000UL | ||
704 | #define NETLINK_AUDIT_SOCKET__RECV_MSG 0x00080000UL | ||
705 | #define NETLINK_AUDIT_SOCKET__SEND_MSG 0x00100000UL | ||
706 | #define NETLINK_AUDIT_SOCKET__NAME_BIND 0x00200000UL | ||
707 | #define NETLINK_AUDIT_SOCKET__NLMSG_READ 0x00400000UL | ||
708 | #define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL | ||
709 | #define NETLINK_AUDIT_SOCKET__NLMSG_RELAY 0x01000000UL | ||
710 | #define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV 0x02000000UL | ||
711 | #define NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT 0x04000000UL | ||
712 | #define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL | ||
713 | #define NETLINK_IP6FW_SOCKET__READ 0x00000002UL | ||
714 | #define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL | ||
715 | #define NETLINK_IP6FW_SOCKET__CREATE 0x00000008UL | ||
716 | #define NETLINK_IP6FW_SOCKET__GETATTR 0x00000010UL | ||
717 | #define NETLINK_IP6FW_SOCKET__SETATTR 0x00000020UL | ||
718 | #define NETLINK_IP6FW_SOCKET__LOCK 0x00000040UL | ||
719 | #define NETLINK_IP6FW_SOCKET__RELABELFROM 0x00000080UL | ||
720 | #define NETLINK_IP6FW_SOCKET__RELABELTO 0x00000100UL | ||
721 | #define NETLINK_IP6FW_SOCKET__APPEND 0x00000200UL | ||
722 | #define NETLINK_IP6FW_SOCKET__BIND 0x00000400UL | ||
723 | #define NETLINK_IP6FW_SOCKET__CONNECT 0x00000800UL | ||
724 | #define NETLINK_IP6FW_SOCKET__LISTEN 0x00001000UL | ||
725 | #define NETLINK_IP6FW_SOCKET__ACCEPT 0x00002000UL | ||
726 | #define NETLINK_IP6FW_SOCKET__GETOPT 0x00004000UL | ||
727 | #define NETLINK_IP6FW_SOCKET__SETOPT 0x00008000UL | ||
728 | #define NETLINK_IP6FW_SOCKET__SHUTDOWN 0x00010000UL | ||
729 | #define NETLINK_IP6FW_SOCKET__RECVFROM 0x00020000UL | ||
730 | #define NETLINK_IP6FW_SOCKET__SENDTO 0x00040000UL | ||
731 | #define NETLINK_IP6FW_SOCKET__RECV_MSG 0x00080000UL | ||
732 | #define NETLINK_IP6FW_SOCKET__SEND_MSG 0x00100000UL | ||
733 | #define NETLINK_IP6FW_SOCKET__NAME_BIND 0x00200000UL | ||
734 | #define NETLINK_IP6FW_SOCKET__NLMSG_READ 0x00400000UL | ||
735 | #define NETLINK_IP6FW_SOCKET__NLMSG_WRITE 0x00800000UL | ||
736 | #define NETLINK_DNRT_SOCKET__IOCTL 0x00000001UL | ||
737 | #define NETLINK_DNRT_SOCKET__READ 0x00000002UL | ||
738 | #define NETLINK_DNRT_SOCKET__WRITE 0x00000004UL | ||
739 | #define NETLINK_DNRT_SOCKET__CREATE 0x00000008UL | ||
740 | #define NETLINK_DNRT_SOCKET__GETATTR 0x00000010UL | ||
741 | #define NETLINK_DNRT_SOCKET__SETATTR 0x00000020UL | ||
742 | #define NETLINK_DNRT_SOCKET__LOCK 0x00000040UL | ||
743 | #define NETLINK_DNRT_SOCKET__RELABELFROM 0x00000080UL | ||
744 | #define NETLINK_DNRT_SOCKET__RELABELTO 0x00000100UL | ||
745 | #define NETLINK_DNRT_SOCKET__APPEND 0x00000200UL | ||
746 | #define NETLINK_DNRT_SOCKET__BIND 0x00000400UL | ||
747 | #define NETLINK_DNRT_SOCKET__CONNECT 0x00000800UL | ||
748 | #define NETLINK_DNRT_SOCKET__LISTEN 0x00001000UL | ||
749 | #define NETLINK_DNRT_SOCKET__ACCEPT 0x00002000UL | ||
750 | #define NETLINK_DNRT_SOCKET__GETOPT 0x00004000UL | ||
751 | #define NETLINK_DNRT_SOCKET__SETOPT 0x00008000UL | ||
752 | #define NETLINK_DNRT_SOCKET__SHUTDOWN 0x00010000UL | ||
753 | #define NETLINK_DNRT_SOCKET__RECVFROM 0x00020000UL | ||
754 | #define NETLINK_DNRT_SOCKET__SENDTO 0x00040000UL | ||
755 | #define NETLINK_DNRT_SOCKET__RECV_MSG 0x00080000UL | ||
756 | #define NETLINK_DNRT_SOCKET__SEND_MSG 0x00100000UL | ||
757 | #define NETLINK_DNRT_SOCKET__NAME_BIND 0x00200000UL | ||
758 | #define ASSOCIATION__SENDTO 0x00000001UL | ||
759 | #define ASSOCIATION__RECVFROM 0x00000002UL | ||
760 | #define ASSOCIATION__SETCONTEXT 0x00000004UL | ||
761 | #define ASSOCIATION__POLMATCH 0x00000008UL | ||
762 | #define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL | ||
763 | #define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL | ||
764 | #define NETLINK_KOBJECT_UEVENT_SOCKET__WRITE 0x00000004UL | ||
765 | #define NETLINK_KOBJECT_UEVENT_SOCKET__CREATE 0x00000008UL | ||
766 | #define NETLINK_KOBJECT_UEVENT_SOCKET__GETATTR 0x00000010UL | ||
767 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SETATTR 0x00000020UL | ||
768 | #define NETLINK_KOBJECT_UEVENT_SOCKET__LOCK 0x00000040UL | ||
769 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELFROM 0x00000080UL | ||
770 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELTO 0x00000100UL | ||
771 | #define NETLINK_KOBJECT_UEVENT_SOCKET__APPEND 0x00000200UL | ||
772 | #define NETLINK_KOBJECT_UEVENT_SOCKET__BIND 0x00000400UL | ||
773 | #define NETLINK_KOBJECT_UEVENT_SOCKET__CONNECT 0x00000800UL | ||
774 | #define NETLINK_KOBJECT_UEVENT_SOCKET__LISTEN 0x00001000UL | ||
775 | #define NETLINK_KOBJECT_UEVENT_SOCKET__ACCEPT 0x00002000UL | ||
776 | #define NETLINK_KOBJECT_UEVENT_SOCKET__GETOPT 0x00004000UL | ||
777 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SETOPT 0x00008000UL | ||
778 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SHUTDOWN 0x00010000UL | ||
779 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RECVFROM 0x00020000UL | ||
780 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SENDTO 0x00040000UL | ||
781 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RECV_MSG 0x00080000UL | ||
782 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL | ||
783 | #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL | ||
784 | #define APPLETALK_SOCKET__IOCTL 0x00000001UL | ||
785 | #define APPLETALK_SOCKET__READ 0x00000002UL | ||
786 | #define APPLETALK_SOCKET__WRITE 0x00000004UL | ||
787 | #define APPLETALK_SOCKET__CREATE 0x00000008UL | ||
788 | #define APPLETALK_SOCKET__GETATTR 0x00000010UL | ||
789 | #define APPLETALK_SOCKET__SETATTR 0x00000020UL | ||
790 | #define APPLETALK_SOCKET__LOCK 0x00000040UL | ||
791 | #define APPLETALK_SOCKET__RELABELFROM 0x00000080UL | ||
792 | #define APPLETALK_SOCKET__RELABELTO 0x00000100UL | ||
793 | #define APPLETALK_SOCKET__APPEND 0x00000200UL | ||
794 | #define APPLETALK_SOCKET__BIND 0x00000400UL | ||
795 | #define APPLETALK_SOCKET__CONNECT 0x00000800UL | ||
796 | #define APPLETALK_SOCKET__LISTEN 0x00001000UL | ||
797 | #define APPLETALK_SOCKET__ACCEPT 0x00002000UL | ||
798 | #define APPLETALK_SOCKET__GETOPT 0x00004000UL | ||
799 | #define APPLETALK_SOCKET__SETOPT 0x00008000UL | ||
800 | #define APPLETALK_SOCKET__SHUTDOWN 0x00010000UL | ||
801 | #define APPLETALK_SOCKET__RECVFROM 0x00020000UL | ||
802 | #define APPLETALK_SOCKET__SENDTO 0x00040000UL | ||
803 | #define APPLETALK_SOCKET__RECV_MSG 0x00080000UL | ||
804 | #define APPLETALK_SOCKET__SEND_MSG 0x00100000UL | ||
805 | #define APPLETALK_SOCKET__NAME_BIND 0x00200000UL | ||
806 | #define PACKET__SEND 0x00000001UL | ||
807 | #define PACKET__RECV 0x00000002UL | ||
808 | #define PACKET__RELABELTO 0x00000004UL | ||
809 | #define PACKET__FLOW_IN 0x00000008UL | ||
810 | #define PACKET__FLOW_OUT 0x00000010UL | ||
811 | #define PACKET__FORWARD_IN 0x00000020UL | ||
812 | #define PACKET__FORWARD_OUT 0x00000040UL | ||
813 | #define KEY__VIEW 0x00000001UL | ||
814 | #define KEY__READ 0x00000002UL | ||
815 | #define KEY__WRITE 0x00000004UL | ||
816 | #define KEY__SEARCH 0x00000008UL | ||
817 | #define KEY__LINK 0x00000010UL | ||
818 | #define KEY__SETATTR 0x00000020UL | ||
819 | #define KEY__CREATE 0x00000040UL | ||
820 | #define DCCP_SOCKET__IOCTL 0x00000001UL | ||
821 | #define DCCP_SOCKET__READ 0x00000002UL | ||
822 | #define DCCP_SOCKET__WRITE 0x00000004UL | ||
823 | #define DCCP_SOCKET__CREATE 0x00000008UL | ||
824 | #define DCCP_SOCKET__GETATTR 0x00000010UL | ||
825 | #define DCCP_SOCKET__SETATTR 0x00000020UL | ||
826 | #define DCCP_SOCKET__LOCK 0x00000040UL | ||
827 | #define DCCP_SOCKET__RELABELFROM 0x00000080UL | ||
828 | #define DCCP_SOCKET__RELABELTO 0x00000100UL | ||
829 | #define DCCP_SOCKET__APPEND 0x00000200UL | ||
830 | #define DCCP_SOCKET__BIND 0x00000400UL | ||
831 | #define DCCP_SOCKET__CONNECT 0x00000800UL | ||
832 | #define DCCP_SOCKET__LISTEN 0x00001000UL | ||
833 | #define DCCP_SOCKET__ACCEPT 0x00002000UL | ||
834 | #define DCCP_SOCKET__GETOPT 0x00004000UL | ||
835 | #define DCCP_SOCKET__SETOPT 0x00008000UL | ||
836 | #define DCCP_SOCKET__SHUTDOWN 0x00010000UL | ||
837 | #define DCCP_SOCKET__RECVFROM 0x00020000UL | ||
838 | #define DCCP_SOCKET__SENDTO 0x00040000UL | ||
839 | #define DCCP_SOCKET__RECV_MSG 0x00080000UL | ||
840 | #define DCCP_SOCKET__SEND_MSG 0x00100000UL | ||
841 | #define DCCP_SOCKET__NAME_BIND 0x00200000UL | ||
842 | #define DCCP_SOCKET__NODE_BIND 0x00400000UL | ||
843 | #define DCCP_SOCKET__NAME_CONNECT 0x00800000UL | ||
844 | #define MEMPROTECT__MMAP_ZERO 0x00000001UL | ||
845 | #define PEER__RECV 0x00000001UL | ||
846 | #define KERNEL_SERVICE__USE_AS_OVERRIDE 0x00000001UL | ||
847 | #define KERNEL_SERVICE__CREATE_FILES_AS 0x00000002UL | ||
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index d12ff1a9c0a..5615081b73e 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -13,8 +13,8 @@ | |||
13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/audit.h> | 15 | #include <linux/audit.h> |
16 | #include <linux/lsm_audit.h> | ||
16 | #include <linux/in6.h> | 17 | #include <linux/in6.h> |
17 | #include <linux/path.h> | ||
18 | #include <asm/system.h> | 18 | #include <asm/system.h> |
19 | #include "flask.h" | 19 | #include "flask.h" |
20 | #include "av_permissions.h" | 20 | #include "av_permissions.h" |
@@ -36,48 +36,6 @@ struct inode; | |||
36 | struct sock; | 36 | struct sock; |
37 | struct sk_buff; | 37 | struct sk_buff; |
38 | 38 | ||
39 | /* Auxiliary data to use in generating the audit record. */ | ||
40 | struct avc_audit_data { | ||
41 | char type; | ||
42 | #define AVC_AUDIT_DATA_FS 1 | ||
43 | #define AVC_AUDIT_DATA_NET 2 | ||
44 | #define AVC_AUDIT_DATA_CAP 3 | ||
45 | #define AVC_AUDIT_DATA_IPC 4 | ||
46 | struct task_struct *tsk; | ||
47 | union { | ||
48 | struct { | ||
49 | struct path path; | ||
50 | struct inode *inode; | ||
51 | } fs; | ||
52 | struct { | ||
53 | int netif; | ||
54 | struct sock *sk; | ||
55 | u16 family; | ||
56 | __be16 dport; | ||
57 | __be16 sport; | ||
58 | union { | ||
59 | struct { | ||
60 | __be32 daddr; | ||
61 | __be32 saddr; | ||
62 | } v4; | ||
63 | struct { | ||
64 | struct in6_addr daddr; | ||
65 | struct in6_addr saddr; | ||
66 | } v6; | ||
67 | } fam; | ||
68 | } net; | ||
69 | int cap; | ||
70 | int ipc_id; | ||
71 | } u; | ||
72 | }; | ||
73 | |||
74 | #define v4info fam.v4 | ||
75 | #define v6info fam.v6 | ||
76 | |||
77 | /* Initialize an AVC audit data structure. */ | ||
78 | #define AVC_AUDIT_DATA_INIT(_d,_t) \ | ||
79 | { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } | ||
80 | |||
81 | /* | 39 | /* |
82 | * AVC statistics | 40 | * AVC statistics |
83 | */ | 41 | */ |
@@ -98,7 +56,9 @@ void __init avc_init(void); | |||
98 | 56 | ||
99 | void avc_audit(u32 ssid, u32 tsid, | 57 | void avc_audit(u32 ssid, u32 tsid, |
100 | u16 tclass, u32 requested, | 58 | u16 tclass, u32 requested, |
101 | struct av_decision *avd, int result, struct avc_audit_data *auditdata); | 59 | struct av_decision *avd, |
60 | int result, | ||
61 | struct common_audit_data *a); | ||
102 | 62 | ||
103 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 63 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
104 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 64 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
@@ -108,7 +68,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
108 | 68 | ||
109 | int avc_has_perm(u32 ssid, u32 tsid, | 69 | int avc_has_perm(u32 ssid, u32 tsid, |
110 | u16 tclass, u32 requested, | 70 | u16 tclass, u32 requested, |
111 | struct avc_audit_data *auditdata); | 71 | struct common_audit_data *auditdata); |
112 | 72 | ||
113 | u32 avc_policy_seqno(void); | 73 | u32 avc_policy_seqno(void); |
114 | 74 | ||
@@ -127,13 +87,13 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |||
127 | u32 events, u32 ssid, u32 tsid, | 87 | u32 events, u32 ssid, u32 tsid, |
128 | u16 tclass, u32 perms); | 88 | u16 tclass, u32 perms); |
129 | 89 | ||
130 | /* Shows permission in human readable form */ | ||
131 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av); | ||
132 | |||
133 | /* Exported to selinuxfs */ | 90 | /* Exported to selinuxfs */ |
134 | int avc_get_hash_stats(char *page); | 91 | int avc_get_hash_stats(char *page); |
135 | extern unsigned int avc_cache_threshold; | 92 | extern unsigned int avc_cache_threshold; |
136 | 93 | ||
94 | /* Attempt to free avc node cache */ | ||
95 | void avc_disable(void); | ||
96 | |||
137 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 97 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
138 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); | 98 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); |
139 | #endif | 99 | #endif |
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index bb1ec801bdf..4677aa519b0 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h | |||
@@ -10,26 +10,13 @@ | |||
10 | 10 | ||
11 | int avc_ss_reset(u32 seqno); | 11 | int avc_ss_reset(u32 seqno); |
12 | 12 | ||
13 | struct av_perm_to_string { | 13 | /* Class/perm mapping support */ |
14 | u16 tclass; | 14 | struct security_class_mapping { |
15 | u32 value; | ||
16 | const char *name; | 15 | const char *name; |
16 | const char *perms[sizeof(u32) * 8 + 1]; | ||
17 | }; | 17 | }; |
18 | 18 | ||
19 | struct av_inherit { | 19 | extern struct security_class_mapping secclass_map[]; |
20 | const char **common_pts; | ||
21 | u32 common_base; | ||
22 | u16 tclass; | ||
23 | }; | ||
24 | |||
25 | struct selinux_class_perm { | ||
26 | const struct av_perm_to_string *av_perm_to_string; | ||
27 | u32 av_pts_len; | ||
28 | u32 cts_len; | ||
29 | const char **class_to_string; | ||
30 | const struct av_inherit *av_inherit; | ||
31 | u32 av_inherit_len; | ||
32 | }; | ||
33 | 20 | ||
34 | #endif /* _SELINUX_AVC_SS_H_ */ | 21 | #endif /* _SELINUX_AVC_SS_H_ */ |
35 | 22 | ||
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h deleted file mode 100644 index 21ec786611d..00000000000 --- a/security/selinux/include/class_to_string.h +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | /* | ||
3 | * Security object class definitions | ||
4 | */ | ||
5 | S_(NULL) | ||
6 | S_("security") | ||
7 | S_("process") | ||
8 | S_("system") | ||
9 | S_("capability") | ||
10 | S_("filesystem") | ||
11 | S_("file") | ||
12 | S_("dir") | ||
13 | S_("fd") | ||
14 | S_("lnk_file") | ||
15 | S_("chr_file") | ||
16 | S_("blk_file") | ||
17 | S_("sock_file") | ||
18 | S_("fifo_file") | ||
19 | S_("socket") | ||
20 | S_("tcp_socket") | ||
21 | S_("udp_socket") | ||
22 | S_("rawip_socket") | ||
23 | S_("node") | ||
24 | S_("netif") | ||
25 | S_("netlink_socket") | ||
26 | S_("packet_socket") | ||
27 | S_("key_socket") | ||
28 | S_("unix_stream_socket") | ||
29 | S_("unix_dgram_socket") | ||
30 | S_("sem") | ||
31 | S_("msg") | ||
32 | S_("msgq") | ||
33 | S_("shm") | ||
34 | S_("ipc") | ||
35 | S_(NULL) | ||
36 | S_(NULL) | ||
37 | S_(NULL) | ||
38 | S_(NULL) | ||
39 | S_(NULL) | ||
40 | S_(NULL) | ||
41 | S_(NULL) | ||
42 | S_(NULL) | ||
43 | S_(NULL) | ||
44 | S_(NULL) | ||
45 | S_(NULL) | ||
46 | S_(NULL) | ||
47 | S_(NULL) | ||
48 | S_("netlink_route_socket") | ||
49 | S_("netlink_firewall_socket") | ||
50 | S_("netlink_tcpdiag_socket") | ||
51 | S_("netlink_nflog_socket") | ||
52 | S_("netlink_xfrm_socket") | ||
53 | S_("netlink_selinux_socket") | ||
54 | S_("netlink_audit_socket") | ||
55 | S_("netlink_ip6fw_socket") | ||
56 | S_("netlink_dnrt_socket") | ||
57 | S_(NULL) | ||
58 | S_(NULL) | ||
59 | S_("association") | ||
60 | S_("netlink_kobject_uevent_socket") | ||
61 | S_("appletalk_socket") | ||
62 | S_("packet") | ||
63 | S_("key") | ||
64 | S_(NULL) | ||
65 | S_("dccp_socket") | ||
66 | S_("memprotect") | ||
67 | S_(NULL) | ||
68 | S_(NULL) | ||
69 | S_(NULL) | ||
70 | S_(NULL) | ||
71 | S_(NULL) | ||
72 | S_(NULL) | ||
73 | S_("peer") | ||
74 | S_("capability2") | ||
75 | S_(NULL) | ||
76 | S_(NULL) | ||
77 | S_(NULL) | ||
78 | S_(NULL) | ||
79 | S_("kernel_service") | ||
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h new file mode 100644 index 00000000000..7ed3663332e --- /dev/null +++ b/security/selinux/include/classmap.h | |||
@@ -0,0 +1,150 @@ | |||
1 | #define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \ | ||
2 | "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" | ||
3 | |||
4 | #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ | ||
5 | "rename", "execute", "swapon", "quotaon", "mounton", "audit_access", \ | ||
6 | "open", "execmod" | ||
7 | |||
8 | #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ | ||
9 | "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ | ||
10 | "sendto", "recv_msg", "send_msg", "name_bind" | ||
11 | |||
12 | #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ | ||
13 | "write", "associate", "unix_read", "unix_write" | ||
14 | |||
15 | struct security_class_mapping secclass_map[] = { | ||
16 | { "security", | ||
17 | { "compute_av", "compute_create", "compute_member", | ||
18 | "check_context", "load_policy", "compute_relabel", | ||
19 | "compute_user", "setenforce", "setbool", "setsecparam", | ||
20 | "setcheckreqprot", "read_policy", NULL } }, | ||
21 | { "process", | ||
22 | { "fork", "transition", "sigchld", "sigkill", | ||
23 | "sigstop", "signull", "signal", "ptrace", "getsched", "setsched", | ||
24 | "getsession", "getpgid", "setpgid", "getcap", "setcap", "share", | ||
25 | "getattr", "setexec", "setfscreate", "noatsecure", "siginh", | ||
26 | "setrlimit", "rlimitinh", "dyntransition", "setcurrent", | ||
27 | "execmem", "execstack", "execheap", "setkeycreate", | ||
28 | "setsockcreate", NULL } }, | ||
29 | { "system", | ||
30 | { "ipc_info", "syslog_read", "syslog_mod", | ||
31 | "syslog_console", "module_request", NULL } }, | ||
32 | { "capability", | ||
33 | { "chown", "dac_override", "dac_read_search", | ||
34 | "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", | ||
35 | "linux_immutable", "net_bind_service", "net_broadcast", | ||
36 | "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", | ||
37 | "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", | ||
38 | "sys_boot", "sys_nice", "sys_resource", "sys_time", | ||
39 | "sys_tty_config", "mknod", "lease", "audit_write", | ||
40 | "audit_control", "setfcap", NULL } }, | ||
41 | { "filesystem", | ||
42 | { "mount", "remount", "unmount", "getattr", | ||
43 | "relabelfrom", "relabelto", "transition", "associate", "quotamod", | ||
44 | "quotaget", NULL } }, | ||
45 | { "file", | ||
46 | { COMMON_FILE_PERMS, | ||
47 | "execute_no_trans", "entrypoint", NULL } }, | ||
48 | { "dir", | ||
49 | { COMMON_FILE_PERMS, "add_name", "remove_name", | ||
50 | "reparent", "search", "rmdir", NULL } }, | ||
51 | { "fd", { "use", NULL } }, | ||
52 | { "lnk_file", | ||
53 | { COMMON_FILE_PERMS, NULL } }, | ||
54 | { "chr_file", | ||
55 | { COMMON_FILE_PERMS, NULL } }, | ||
56 | { "blk_file", | ||
57 | { COMMON_FILE_PERMS, NULL } }, | ||
58 | { "sock_file", | ||
59 | { COMMON_FILE_PERMS, NULL } }, | ||
60 | { "fifo_file", | ||
61 | { COMMON_FILE_PERMS, NULL } }, | ||
62 | { "socket", | ||
63 | { COMMON_SOCK_PERMS, NULL } }, | ||
64 | { "tcp_socket", | ||
65 | { COMMON_SOCK_PERMS, | ||
66 | "connectto", "newconn", "acceptfrom", "node_bind", "name_connect", | ||
67 | NULL } }, | ||
68 | { "udp_socket", | ||
69 | { COMMON_SOCK_PERMS, | ||
70 | "node_bind", NULL } }, | ||
71 | { "rawip_socket", | ||
72 | { COMMON_SOCK_PERMS, | ||
73 | "node_bind", NULL } }, | ||
74 | { "node", | ||
75 | { "tcp_recv", "tcp_send", "udp_recv", "udp_send", | ||
76 | "rawip_recv", "rawip_send", "enforce_dest", | ||
77 | "dccp_recv", "dccp_send", "recvfrom", "sendto", NULL } }, | ||
78 | { "netif", | ||
79 | { "tcp_recv", "tcp_send", "udp_recv", "udp_send", | ||
80 | "rawip_recv", "rawip_send", "dccp_recv", "dccp_send", | ||
81 | "ingress", "egress", NULL } }, | ||
82 | { "netlink_socket", | ||
83 | { COMMON_SOCK_PERMS, NULL } }, | ||
84 | { "packet_socket", | ||
85 | { COMMON_SOCK_PERMS, NULL } }, | ||
86 | { "key_socket", | ||
87 | { COMMON_SOCK_PERMS, NULL } }, | ||
88 | { "unix_stream_socket", | ||
89 | { COMMON_SOCK_PERMS, "connectto", "newconn", "acceptfrom", NULL | ||
90 | } }, | ||
91 | { "unix_dgram_socket", | ||
92 | { COMMON_SOCK_PERMS, NULL | ||
93 | } }, | ||
94 | { "sem", | ||
95 | { COMMON_IPC_PERMS, NULL } }, | ||
96 | { "msg", { "send", "receive", NULL } }, | ||
97 | { "msgq", | ||
98 | { COMMON_IPC_PERMS, "enqueue", NULL } }, | ||
99 | { "shm", | ||
100 | { COMMON_IPC_PERMS, "lock", NULL } }, | ||
101 | { "ipc", | ||
102 | { COMMON_IPC_PERMS, NULL } }, | ||
103 | { "netlink_route_socket", | ||
104 | { COMMON_SOCK_PERMS, | ||
105 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
106 | { "netlink_firewall_socket", | ||
107 | { COMMON_SOCK_PERMS, | ||
108 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
109 | { "netlink_tcpdiag_socket", | ||
110 | { COMMON_SOCK_PERMS, | ||
111 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
112 | { "netlink_nflog_socket", | ||
113 | { COMMON_SOCK_PERMS, NULL } }, | ||
114 | { "netlink_xfrm_socket", | ||
115 | { COMMON_SOCK_PERMS, | ||
116 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
117 | { "netlink_selinux_socket", | ||
118 | { COMMON_SOCK_PERMS, NULL } }, | ||
119 | { "netlink_audit_socket", | ||
120 | { COMMON_SOCK_PERMS, | ||
121 | "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv", | ||
122 | "nlmsg_tty_audit", NULL } }, | ||
123 | { "netlink_ip6fw_socket", | ||
124 | { COMMON_SOCK_PERMS, | ||
125 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
126 | { "netlink_dnrt_socket", | ||
127 | { COMMON_SOCK_PERMS, NULL } }, | ||
128 | { "association", | ||
129 | { "sendto", "recvfrom", "setcontext", "polmatch", NULL } }, | ||
130 | { "netlink_kobject_uevent_socket", | ||
131 | { COMMON_SOCK_PERMS, NULL } }, | ||
132 | { "appletalk_socket", | ||
133 | { COMMON_SOCK_PERMS, NULL } }, | ||
134 | { "packet", | ||
135 | { "send", "recv", "relabelto", "flow_in", "flow_out", | ||
136 | "forward_in", "forward_out", NULL } }, | ||
137 | { "key", | ||
138 | { "view", "read", "write", "search", "link", "setattr", "create", | ||
139 | NULL } }, | ||
140 | { "dccp_socket", | ||
141 | { COMMON_SOCK_PERMS, | ||
142 | "node_bind", "name_connect", NULL } }, | ||
143 | { "memprotect", { "mmap_zero", NULL } }, | ||
144 | { "peer", { "recv", NULL } }, | ||
145 | { "capability2", { "mac_override", "mac_admin", "syslog", NULL } }, | ||
146 | { "kernel_service", { "use_as_override", "create_files_as", NULL } }, | ||
147 | { "tun_socket", | ||
148 | { COMMON_SOCK_PERMS, NULL } }, | ||
149 | { NULL } | ||
150 | }; | ||
diff --git a/security/selinux/include/common_perm_to_string.h b/security/selinux/include/common_perm_to_string.h deleted file mode 100644 index ce5b6e2fe9d..00000000000 --- a/security/selinux/include/common_perm_to_string.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | TB_(common_file_perm_to_string) | ||
3 | S_("ioctl") | ||
4 | S_("read") | ||
5 | S_("write") | ||
6 | S_("create") | ||
7 | S_("getattr") | ||
8 | S_("setattr") | ||
9 | S_("lock") | ||
10 | S_("relabelfrom") | ||
11 | S_("relabelto") | ||
12 | S_("append") | ||
13 | S_("unlink") | ||
14 | S_("link") | ||
15 | S_("rename") | ||
16 | S_("execute") | ||
17 | S_("swapon") | ||
18 | S_("quotaon") | ||
19 | S_("mounton") | ||
20 | TE_(common_file_perm_to_string) | ||
21 | |||
22 | TB_(common_socket_perm_to_string) | ||
23 | S_("ioctl") | ||
24 | S_("read") | ||
25 | S_("write") | ||
26 | S_("create") | ||
27 | S_("getattr") | ||
28 | S_("setattr") | ||
29 | S_("lock") | ||
30 | S_("relabelfrom") | ||
31 | S_("relabelto") | ||
32 | S_("append") | ||
33 | S_("bind") | ||
34 | S_("connect") | ||
35 | S_("listen") | ||
36 | S_("accept") | ||
37 | S_("getopt") | ||
38 | S_("setopt") | ||
39 | S_("shutdown") | ||
40 | S_("recvfrom") | ||
41 | S_("sendto") | ||
42 | S_("recv_msg") | ||
43 | S_("send_msg") | ||
44 | S_("name_bind") | ||
45 | TE_(common_socket_perm_to_string) | ||
46 | |||
47 | TB_(common_ipc_perm_to_string) | ||
48 | S_("create") | ||
49 | S_("destroy") | ||
50 | S_("getattr") | ||
51 | S_("setattr") | ||
52 | S_("read") | ||
53 | S_("write") | ||
54 | S_("associate") | ||
55 | S_("unix_read") | ||
56 | S_("unix_write") | ||
57 | TE_(common_ipc_perm_to_string) | ||
58 | |||
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h deleted file mode 100644 index 882f27d66fa..00000000000 --- a/security/selinux/include/flask.h +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | #ifndef _SELINUX_FLASK_H_ | ||
3 | #define _SELINUX_FLASK_H_ | ||
4 | |||
5 | /* | ||
6 | * Security object class definitions | ||
7 | */ | ||
8 | #define SECCLASS_SECURITY 1 | ||
9 | #define SECCLASS_PROCESS 2 | ||
10 | #define SECCLASS_SYSTEM 3 | ||
11 | #define SECCLASS_CAPABILITY 4 | ||
12 | #define SECCLASS_FILESYSTEM 5 | ||
13 | #define SECCLASS_FILE 6 | ||
14 | #define SECCLASS_DIR 7 | ||
15 | #define SECCLASS_FD 8 | ||
16 | #define SECCLASS_LNK_FILE 9 | ||
17 | #define SECCLASS_CHR_FILE 10 | ||
18 | #define SECCLASS_BLK_FILE 11 | ||
19 | #define SECCLASS_SOCK_FILE 12 | ||
20 | #define SECCLASS_FIFO_FILE 13 | ||
21 | #define SECCLASS_SOCKET 14 | ||
22 | #define SECCLASS_TCP_SOCKET 15 | ||
23 | #define SECCLASS_UDP_SOCKET 16 | ||
24 | #define SECCLASS_RAWIP_SOCKET 17 | ||
25 | #define SECCLASS_NODE 18 | ||
26 | #define SECCLASS_NETIF 19 | ||
27 | #define SECCLASS_NETLINK_SOCKET 20 | ||
28 | #define SECCLASS_PACKET_SOCKET 21 | ||
29 | #define SECCLASS_KEY_SOCKET 22 | ||
30 | #define SECCLASS_UNIX_STREAM_SOCKET 23 | ||
31 | #define SECCLASS_UNIX_DGRAM_SOCKET 24 | ||
32 | #define SECCLASS_SEM 25 | ||
33 | #define SECCLASS_MSG 26 | ||
34 | #define SECCLASS_MSGQ 27 | ||
35 | #define SECCLASS_SHM 28 | ||
36 | #define SECCLASS_IPC 29 | ||
37 | #define SECCLASS_NETLINK_ROUTE_SOCKET 43 | ||
38 | #define SECCLASS_NETLINK_FIREWALL_SOCKET 44 | ||
39 | #define SECCLASS_NETLINK_TCPDIAG_SOCKET 45 | ||
40 | #define SECCLASS_NETLINK_NFLOG_SOCKET 46 | ||
41 | #define SECCLASS_NETLINK_XFRM_SOCKET 47 | ||
42 | #define SECCLASS_NETLINK_SELINUX_SOCKET 48 | ||
43 | #define SECCLASS_NETLINK_AUDIT_SOCKET 49 | ||
44 | #define SECCLASS_NETLINK_IP6FW_SOCKET 50 | ||
45 | #define SECCLASS_NETLINK_DNRT_SOCKET 51 | ||
46 | #define SECCLASS_ASSOCIATION 54 | ||
47 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 | ||
48 | #define SECCLASS_APPLETALK_SOCKET 56 | ||
49 | #define SECCLASS_PACKET 57 | ||
50 | #define SECCLASS_KEY 58 | ||
51 | #define SECCLASS_DCCP_SOCKET 60 | ||
52 | #define SECCLASS_MEMPROTECT 61 | ||
53 | #define SECCLASS_PEER 68 | ||
54 | #define SECCLASS_CAPABILITY2 69 | ||
55 | #define SECCLASS_KERNEL_SERVICE 74 | ||
56 | |||
57 | /* | ||
58 | * Security identifier indices for initial entities | ||
59 | */ | ||
60 | #define SECINITSID_KERNEL 1 | ||
61 | #define SECINITSID_SECURITY 2 | ||
62 | #define SECINITSID_UNLABELED 3 | ||
63 | #define SECINITSID_FS 4 | ||
64 | #define SECINITSID_FILE 5 | ||
65 | #define SECINITSID_FILE_LABELS 6 | ||
66 | #define SECINITSID_INIT 7 | ||
67 | #define SECINITSID_ANY_SOCKET 8 | ||
68 | #define SECINITSID_PORT 9 | ||
69 | #define SECINITSID_NETIF 10 | ||
70 | #define SECINITSID_NETMSG 11 | ||
71 | #define SECINITSID_NODE 12 | ||
72 | #define SECINITSID_IGMP_PACKET 13 | ||
73 | #define SECINITSID_ICMP_SOCKET 14 | ||
74 | #define SECINITSID_TCP_SOCKET 15 | ||
75 | #define SECINITSID_SYSCTL_MODPROBE 16 | ||
76 | #define SECINITSID_SYSCTL 17 | ||
77 | #define SECINITSID_SYSCTL_FS 18 | ||
78 | #define SECINITSID_SYSCTL_KERNEL 19 | ||
79 | #define SECINITSID_SYSCTL_NET 20 | ||
80 | #define SECINITSID_SYSCTL_NET_UNIX 21 | ||
81 | #define SECINITSID_SYSCTL_VM 22 | ||
82 | #define SECINITSID_SYSCTL_DEV 23 | ||
83 | #define SECINITSID_KMOD 24 | ||
84 | #define SECINITSID_POLICY 25 | ||
85 | #define SECINITSID_SCMP_PACKET 26 | ||
86 | #define SECINITSID_DEVNULL 27 | ||
87 | |||
88 | #define SECINITSID_NUM 27 | ||
89 | |||
90 | #endif | ||
diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h index d4fac82793a..a59b64e3fd0 100644 --- a/security/selinux/include/initial_sid_to_string.h +++ b/security/selinux/include/initial_sid_to_string.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | 1 | /* This file is automatically generated. Do not edit. */ |
2 | static char *initial_sid_to_string[] = | 2 | static const char *initial_sid_to_string[] = |
3 | { | 3 | { |
4 | "null", | 4 | "null", |
5 | "kernel", | 5 | "kernel", |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index b4b5b9b2f0b..cf2f628e6e2 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
@@ -42,8 +42,8 @@ void selinux_netlbl_cache_invalidate(void); | |||
42 | 42 | ||
43 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); | 43 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); |
44 | 44 | ||
45 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); | 45 | void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec); |
46 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec); | 46 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec); |
47 | 47 | ||
48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, |
49 | u16 family, | 49 | u16 family, |
@@ -59,7 +59,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); | |||
59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
60 | struct sk_buff *skb, | 60 | struct sk_buff *skb, |
61 | u16 family, | 61 | u16 family, |
62 | struct avc_audit_data *ad); | 62 | struct common_audit_data *ad); |
63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | 63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, |
64 | int level, | 64 | int level, |
65 | int optname); | 65 | int optname); |
@@ -79,13 +79,13 @@ static inline void selinux_netlbl_err(struct sk_buff *skb, | |||
79 | } | 79 | } |
80 | 80 | ||
81 | static inline void selinux_netlbl_sk_security_free( | 81 | static inline void selinux_netlbl_sk_security_free( |
82 | struct sk_security_struct *ssec) | 82 | struct sk_security_struct *sksec) |
83 | { | 83 | { |
84 | return; | 84 | return; |
85 | } | 85 | } |
86 | 86 | ||
87 | static inline void selinux_netlbl_sk_security_reset( | 87 | static inline void selinux_netlbl_sk_security_reset( |
88 | struct sk_security_struct *ssec) | 88 | struct sk_security_struct *sksec) |
89 | { | 89 | { |
90 | return; | 90 | return; |
91 | } | 91 | } |
@@ -129,7 +129,7 @@ static inline int selinux_netlbl_socket_post_create(struct sock *sk, | |||
129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
130 | struct sk_buff *skb, | 130 | struct sk_buff *skb, |
131 | u16 family, | 131 | u16 family, |
132 | struct avc_audit_data *ad) | 132 | struct common_audit_data *ad) |
133 | { | 133 | { |
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index c4e062336ef..26c7eee1c30 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -55,7 +55,6 @@ struct file_security_struct { | |||
55 | 55 | ||
56 | struct superblock_security_struct { | 56 | struct superblock_security_struct { |
57 | struct super_block *sb; /* back pointer to sb object */ | 57 | struct super_block *sb; /* back pointer to sb object */ |
58 | struct list_head list; /* list of superblock_security_struct */ | ||
59 | u32 sid; /* SID of file system superblock */ | 58 | u32 sid; /* SID of file system superblock */ |
60 | u32 def_sid; /* default SID for labeling */ | 59 | u32 def_sid; /* default SID for labeling */ |
61 | u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ | 60 | u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index ca835795a8b..671273eb111 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #define _SELINUX_SECURITY_H_ | 9 | #define _SELINUX_SECURITY_H_ |
10 | 10 | ||
11 | #include <linux/magic.h> | 11 | #include <linux/magic.h> |
12 | #include <linux/types.h> | ||
12 | #include "flask.h" | 13 | #include "flask.h" |
13 | 14 | ||
14 | #define SECSID_NULL 0x00000000 /* unspecified SID */ | 15 | #define SECSID_NULL 0x00000000 /* unspecified SID */ |
@@ -57,7 +58,6 @@ | |||
57 | struct netlbl_lsm_secattr; | 58 | struct netlbl_lsm_secattr; |
58 | 59 | ||
59 | extern int selinux_enabled; | 60 | extern int selinux_enabled; |
60 | extern int selinux_mls_enabled; | ||
61 | 61 | ||
62 | /* Policy capabilities */ | 62 | /* Policy capabilities */ |
63 | enum { | 63 | enum { |
@@ -80,7 +80,11 @@ extern int selinux_policycap_openperm; | |||
80 | /* limitation of boundary depth */ | 80 | /* limitation of boundary depth */ |
81 | #define POLICYDB_BOUNDS_MAXDEPTH 4 | 81 | #define POLICYDB_BOUNDS_MAXDEPTH 4 |
82 | 82 | ||
83 | int security_mls_enabled(void); | ||
84 | |||
83 | int security_load_policy(void *data, size_t len); | 85 | int security_load_policy(void *data, size_t len); |
86 | int security_read_policy(void **data, ssize_t *len); | ||
87 | size_t security_policydb_len(void); | ||
84 | 88 | ||
85 | int security_policycap_supported(unsigned int req_cap); | 89 | int security_policycap_supported(unsigned int req_cap); |
86 | 90 | ||
@@ -96,12 +100,17 @@ struct av_decision { | |||
96 | /* definitions of av_decision.flags */ | 100 | /* definitions of av_decision.flags */ |
97 | #define AVD_FLAGS_PERMISSIVE 0x0001 | 101 | #define AVD_FLAGS_PERMISSIVE 0x0001 |
98 | 102 | ||
99 | int security_compute_av(u32 ssid, u32 tsid, | 103 | void security_compute_av(u32 ssid, u32 tsid, |
100 | u16 tclass, u32 requested, | 104 | u16 tclass, struct av_decision *avd); |
101 | struct av_decision *avd); | 105 | |
106 | void security_compute_av_user(u32 ssid, u32 tsid, | ||
107 | u16 tclass, struct av_decision *avd); | ||
102 | 108 | ||
103 | int security_transition_sid(u32 ssid, u32 tsid, | 109 | int security_transition_sid(u32 ssid, u32 tsid, |
104 | u16 tclass, u32 *out_sid); | 110 | u16 tclass, u32 *out_sid); |
111 | |||
112 | int security_transition_sid_user(u32 ssid, u32 tsid, | ||
113 | u16 tclass, u32 *out_sid); | ||
105 | 114 | ||
106 | int security_member_sid(u32 ssid, u32 tsid, | 115 | int security_member_sid(u32 ssid, u32 tsid, |
107 | u16 tclass, u32 *out_sid); | 116 | u16 tclass, u32 *out_sid); |
@@ -185,5 +194,25 @@ static inline int security_netlbl_sid_to_secattr(u32 sid, | |||
185 | 194 | ||
186 | const char *security_get_initial_sid_context(u32 sid); | 195 | const char *security_get_initial_sid_context(u32 sid); |
187 | 196 | ||
197 | /* | ||
198 | * status notifier using mmap interface | ||
199 | */ | ||
200 | extern struct page *selinux_kernel_status_page(void); | ||
201 | |||
202 | #define SELINUX_KERNEL_STATUS_VERSION 1 | ||
203 | struct selinux_kernel_status { | ||
204 | u32 version; /* version number of thie structure */ | ||
205 | u32 sequence; /* sequence number of seqlock logic */ | ||
206 | u32 enforcing; /* current setting of enforcing mode */ | ||
207 | u32 policyload; /* times of policy reloaded */ | ||
208 | u32 deny_unknown; /* current setting of deny_unknown */ | ||
209 | /* | ||
210 | * The version > 0 supports above members. | ||
211 | */ | ||
212 | } __attribute__((packed)); | ||
213 | |||
214 | extern void selinux_status_update_setenforce(int enforcing); | ||
215 | extern void selinux_status_update_policyload(int seqno); | ||
216 | |||
188 | #endif /* _SELINUX_SECURITY_H_ */ | 217 | #endif /* _SELINUX_SECURITY_H_ */ |
189 | 218 | ||
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 289e24b39e3..13128f9a3e5 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -41,9 +41,9 @@ static inline int selinux_xfrm_enabled(void) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, | 43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, |
44 | struct avc_audit_data *ad); | 44 | struct common_audit_data *ad); |
45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
46 | struct avc_audit_data *ad, u8 proto); | 46 | struct common_audit_data *ad, u8 proto); |
47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
48 | 48 | ||
49 | static inline void selinux_xfrm_notify_policyload(void) | 49 | static inline void selinux_xfrm_notify_policyload(void) |
@@ -57,13 +57,13 @@ static inline int selinux_xfrm_enabled(void) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
60 | struct avc_audit_data *ad) | 60 | struct common_audit_data *ad) |
61 | { | 61 | { |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
66 | struct avc_audit_data *ad, u8 proto) | 66 | struct common_audit_data *ad, u8 proto) |
67 | { | 67 | { |
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index b4e14bc0bf3..d6095d63d83 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/list.h> | 22 | #include <linux/list.h> |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2e984413c7b..1c2fc46544b 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | #include <linux/rcupdate.h> | 31 | #include <linux/rcupdate.h> |
32 | #include <linux/gfp.h> | ||
32 | #include <linux/ip.h> | 33 | #include <linux/ip.h> |
33 | #include <linux/ipv6.h> | 34 | #include <linux/ipv6.h> |
34 | #include <net/sock.h> | 35 | #include <net/sock.h> |
@@ -131,21 +132,21 @@ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) | |||
131 | 132 | ||
132 | /** | 133 | /** |
133 | * selinux_netlbl_sk_security_free - Free the NetLabel fields | 134 | * selinux_netlbl_sk_security_free - Free the NetLabel fields |
134 | * @sssec: the sk_security_struct | 135 | * @sksec: the sk_security_struct |
135 | * | 136 | * |
136 | * Description: | 137 | * Description: |
137 | * Free all of the memory in the NetLabel fields of a sk_security_struct. | 138 | * Free all of the memory in the NetLabel fields of a sk_security_struct. |
138 | * | 139 | * |
139 | */ | 140 | */ |
140 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | 141 | void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) |
141 | { | 142 | { |
142 | if (ssec->nlbl_secattr != NULL) | 143 | if (sksec->nlbl_secattr != NULL) |
143 | netlbl_secattr_free(ssec->nlbl_secattr); | 144 | netlbl_secattr_free(sksec->nlbl_secattr); |
144 | } | 145 | } |
145 | 146 | ||
146 | /** | 147 | /** |
147 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields | 148 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields |
148 | * @ssec: the sk_security_struct | 149 | * @sksec: the sk_security_struct |
149 | * @family: the socket family | 150 | * @family: the socket family |
150 | * | 151 | * |
151 | * Description: | 152 | * Description: |
@@ -153,9 +154,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | |||
153 | * The caller is responsibile for all the NetLabel sk_security_struct locking. | 154 | * The caller is responsibile for all the NetLabel sk_security_struct locking. |
154 | * | 155 | * |
155 | */ | 156 | */ |
156 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec) | 157 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) |
157 | { | 158 | { |
158 | ssec->nlbl_state = NLBL_UNSET; | 159 | sksec->nlbl_state = NLBL_UNSET; |
159 | } | 160 | } |
160 | 161 | ||
161 | /** | 162 | /** |
@@ -204,7 +205,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | |||
204 | * | 205 | * |
205 | * Description | 206 | * Description |
206 | * Call the NetLabel mechanism to set the label of a packet using @sid. | 207 | * Call the NetLabel mechanism to set the label of a packet using @sid. |
207 | * Returns zero on auccess, negative values on failure. | 208 | * Returns zero on success, negative values on failure. |
208 | * | 209 | * |
209 | */ | 210 | */ |
210 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, | 211 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, |
@@ -342,7 +343,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) | |||
342 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 343 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
343 | struct sk_buff *skb, | 344 | struct sk_buff *skb, |
344 | u16 family, | 345 | u16 family, |
345 | struct avc_audit_data *ad) | 346 | struct common_audit_data *ad) |
346 | { | 347 | { |
347 | int rc; | 348 | int rc; |
348 | u32 nlbl_sid; | 349 | u32 nlbl_sid; |
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 1ae556446e6..36ac257cec9 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
@@ -11,9 +11,9 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/list.h> | ||
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/netlink.h> | 18 | #include <linux/netlink.h> |
19 | #include <linux/selinux_netlink.h> | 19 | #include <linux/selinux_netlink.h> |
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 7100072bb1b..65ebfe954f8 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | #include <linux/rcupdate.h> | 32 | #include <linux/rcupdate.h> |
33 | #include <linux/list.h> | 33 | #include <linux/list.h> |
34 | #include <linux/slab.h> | ||
34 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
35 | #include <linux/in.h> | 36 | #include <linux/in.h> |
36 | #include <linux/in6.h> | 37 | #include <linux/in6.h> |
@@ -182,8 +183,6 @@ static void sel_netnode_insert(struct sel_netnode *node) | |||
182 | BUG(); | 183 | BUG(); |
183 | } | 184 | } |
184 | 185 | ||
185 | INIT_RCU_HEAD(&node->rcu); | ||
186 | |||
187 | /* we need to impose a limit on the growth of the hash table so check | 186 | /* we need to impose a limit on the growth of the hash table so check |
188 | * this bucket to make sure it is within the specified bounds */ | 187 | * this bucket to make sure it is within the specified bounds */ |
189 | list_add_rcu(&node->list, &sel_netnode_hash[idx].list); | 188 | list_add_rcu(&node->list, &sel_netnode_hash[idx].list); |
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index fe7fba67f19..cfe2d72d3fb 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/rcupdate.h> | 31 | #include <linux/rcupdate.h> |
32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
33 | #include <linux/slab.h> | ||
33 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
34 | #include <linux/in.h> | 35 | #include <linux/in.h> |
35 | #include <linux/in6.h> | 36 | #include <linux/in6.h> |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index dd7cc6de77f..8b02b2137da 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/netlink.h> | 14 | #include <linux/netlink.h> |
16 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
17 | #include <linux/if.h> | 16 | #include <linux/if.h> |
@@ -66,6 +65,8 @@ static struct nlmsg_perm nlmsg_route_perms[] = | |||
66 | { RTM_NEWADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 65 | { RTM_NEWADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
67 | { RTM_DELADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 66 | { RTM_DELADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
68 | { RTM_GETADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_READ }, | 67 | { RTM_GETADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_READ }, |
68 | { RTM_GETDCB, NETLINK_ROUTE_SOCKET__NLMSG_READ }, | ||
69 | { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | static struct nlmsg_perm nlmsg_firewall_perms[] = | 72 | static struct nlmsg_perm nlmsg_firewall_perms[] = |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index b4fc506e7a8..ea39cb742ae 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -68,6 +68,8 @@ static int *bool_pending_values; | |||
68 | static struct dentry *class_dir; | 68 | static struct dentry *class_dir; |
69 | static unsigned long last_class_ino; | 69 | static unsigned long last_class_ino; |
70 | 70 | ||
71 | static char policy_opened; | ||
72 | |||
71 | /* global data for policy capabilities */ | 73 | /* global data for policy capabilities */ |
72 | static struct dentry *policycap_dir; | 74 | static struct dentry *policycap_dir; |
73 | 75 | ||
@@ -110,6 +112,8 @@ enum sel_inos { | |||
110 | SEL_COMPAT_NET, /* whether to use old compat network packet controls */ | 112 | SEL_COMPAT_NET, /* whether to use old compat network packet controls */ |
111 | SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */ | 113 | SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */ |
112 | SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */ | 114 | SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */ |
115 | SEL_STATUS, /* export current status using mmap() */ | ||
116 | SEL_POLICY, /* allow userspace to read the in kernel policy */ | ||
113 | SEL_INO_NEXT, /* The next inode number to use */ | 117 | SEL_INO_NEXT, /* The next inode number to use */ |
114 | }; | 118 | }; |
115 | 119 | ||
@@ -137,19 +141,24 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
137 | size_t count, loff_t *ppos) | 141 | size_t count, loff_t *ppos) |
138 | 142 | ||
139 | { | 143 | { |
140 | char *page; | 144 | char *page = NULL; |
141 | ssize_t length; | 145 | ssize_t length; |
142 | int new_value; | 146 | int new_value; |
143 | 147 | ||
148 | length = -ENOMEM; | ||
144 | if (count >= PAGE_SIZE) | 149 | if (count >= PAGE_SIZE) |
145 | return -ENOMEM; | 150 | goto out; |
146 | if (*ppos != 0) { | 151 | |
147 | /* No partial writes. */ | 152 | /* No partial writes. */ |
148 | return -EINVAL; | 153 | length = EINVAL; |
149 | } | 154 | if (*ppos != 0) |
155 | goto out; | ||
156 | |||
157 | length = -ENOMEM; | ||
150 | page = (char *)get_zeroed_page(GFP_KERNEL); | 158 | page = (char *)get_zeroed_page(GFP_KERNEL); |
151 | if (!page) | 159 | if (!page) |
152 | return -ENOMEM; | 160 | goto out; |
161 | |||
153 | length = -EFAULT; | 162 | length = -EFAULT; |
154 | if (copy_from_user(page, buf, count)) | 163 | if (copy_from_user(page, buf, count)) |
155 | goto out; | 164 | goto out; |
@@ -171,6 +180,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
171 | if (selinux_enforcing) | 180 | if (selinux_enforcing) |
172 | avc_ss_reset(0); | 181 | avc_ss_reset(0); |
173 | selnl_notify_setenforce(selinux_enforcing); | 182 | selnl_notify_setenforce(selinux_enforcing); |
183 | selinux_status_update_setenforce(selinux_enforcing); | ||
174 | } | 184 | } |
175 | length = count; | 185 | length = count; |
176 | out: | 186 | out: |
@@ -184,6 +194,7 @@ out: | |||
184 | static const struct file_operations sel_enforce_ops = { | 194 | static const struct file_operations sel_enforce_ops = { |
185 | .read = sel_read_enforce, | 195 | .read = sel_read_enforce, |
186 | .write = sel_write_enforce, | 196 | .write = sel_write_enforce, |
197 | .llseek = generic_file_llseek, | ||
187 | }; | 198 | }; |
188 | 199 | ||
189 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, | 200 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, |
@@ -201,6 +212,60 @@ static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, | |||
201 | 212 | ||
202 | static const struct file_operations sel_handle_unknown_ops = { | 213 | static const struct file_operations sel_handle_unknown_ops = { |
203 | .read = sel_read_handle_unknown, | 214 | .read = sel_read_handle_unknown, |
215 | .llseek = generic_file_llseek, | ||
216 | }; | ||
217 | |||
218 | static int sel_open_handle_status(struct inode *inode, struct file *filp) | ||
219 | { | ||
220 | struct page *status = selinux_kernel_status_page(); | ||
221 | |||
222 | if (!status) | ||
223 | return -ENOMEM; | ||
224 | |||
225 | filp->private_data = status; | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static ssize_t sel_read_handle_status(struct file *filp, char __user *buf, | ||
231 | size_t count, loff_t *ppos) | ||
232 | { | ||
233 | struct page *status = filp->private_data; | ||
234 | |||
235 | BUG_ON(!status); | ||
236 | |||
237 | return simple_read_from_buffer(buf, count, ppos, | ||
238 | page_address(status), | ||
239 | sizeof(struct selinux_kernel_status)); | ||
240 | } | ||
241 | |||
242 | static int sel_mmap_handle_status(struct file *filp, | ||
243 | struct vm_area_struct *vma) | ||
244 | { | ||
245 | struct page *status = filp->private_data; | ||
246 | unsigned long size = vma->vm_end - vma->vm_start; | ||
247 | |||
248 | BUG_ON(!status); | ||
249 | |||
250 | /* only allows one page from the head */ | ||
251 | if (vma->vm_pgoff > 0 || size != PAGE_SIZE) | ||
252 | return -EIO; | ||
253 | /* disallow writable mapping */ | ||
254 | if (vma->vm_flags & VM_WRITE) | ||
255 | return -EPERM; | ||
256 | /* disallow mprotect() turns it into writable */ | ||
257 | vma->vm_flags &= ~VM_MAYWRITE; | ||
258 | |||
259 | return remap_pfn_range(vma, vma->vm_start, | ||
260 | page_to_pfn(status), | ||
261 | size, vma->vm_page_prot); | ||
262 | } | ||
263 | |||
264 | static const struct file_operations sel_handle_status_ops = { | ||
265 | .open = sel_open_handle_status, | ||
266 | .read = sel_read_handle_status, | ||
267 | .mmap = sel_mmap_handle_status, | ||
268 | .llseek = generic_file_llseek, | ||
204 | }; | 269 | }; |
205 | 270 | ||
206 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 271 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
@@ -208,20 +273,25 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
208 | size_t count, loff_t *ppos) | 273 | size_t count, loff_t *ppos) |
209 | 274 | ||
210 | { | 275 | { |
211 | char *page; | 276 | char *page = NULL; |
212 | ssize_t length; | 277 | ssize_t length; |
213 | int new_value; | 278 | int new_value; |
214 | extern int selinux_disable(void); | 279 | extern int selinux_disable(void); |
215 | 280 | ||
281 | length = -ENOMEM; | ||
216 | if (count >= PAGE_SIZE) | 282 | if (count >= PAGE_SIZE) |
217 | return -ENOMEM; | 283 | goto out;; |
218 | if (*ppos != 0) { | 284 | |
219 | /* No partial writes. */ | 285 | /* No partial writes. */ |
220 | return -EINVAL; | 286 | length = -EINVAL; |
221 | } | 287 | if (*ppos != 0) |
288 | goto out; | ||
289 | |||
290 | length = -ENOMEM; | ||
222 | page = (char *)get_zeroed_page(GFP_KERNEL); | 291 | page = (char *)get_zeroed_page(GFP_KERNEL); |
223 | if (!page) | 292 | if (!page) |
224 | return -ENOMEM; | 293 | goto out; |
294 | |||
225 | length = -EFAULT; | 295 | length = -EFAULT; |
226 | if (copy_from_user(page, buf, count)) | 296 | if (copy_from_user(page, buf, count)) |
227 | goto out; | 297 | goto out; |
@@ -232,7 +302,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
232 | 302 | ||
233 | if (new_value) { | 303 | if (new_value) { |
234 | length = selinux_disable(); | 304 | length = selinux_disable(); |
235 | if (length < 0) | 305 | if (length) |
236 | goto out; | 306 | goto out; |
237 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 307 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
238 | "selinux=0 auid=%u ses=%u", | 308 | "selinux=0 auid=%u ses=%u", |
@@ -251,6 +321,7 @@ out: | |||
251 | 321 | ||
252 | static const struct file_operations sel_disable_ops = { | 322 | static const struct file_operations sel_disable_ops = { |
253 | .write = sel_write_disable, | 323 | .write = sel_write_disable, |
324 | .llseek = generic_file_llseek, | ||
254 | }; | 325 | }; |
255 | 326 | ||
256 | static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, | 327 | static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, |
@@ -265,6 +336,7 @@ static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, | |||
265 | 336 | ||
266 | static const struct file_operations sel_policyvers_ops = { | 337 | static const struct file_operations sel_policyvers_ops = { |
267 | .read = sel_read_policyvers, | 338 | .read = sel_read_policyvers, |
339 | .llseek = generic_file_llseek, | ||
268 | }; | 340 | }; |
269 | 341 | ||
270 | /* declaration for sel_write_load */ | 342 | /* declaration for sel_write_load */ |
@@ -282,19 +354,155 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf, | |||
282 | char tmpbuf[TMPBUFLEN]; | 354 | char tmpbuf[TMPBUFLEN]; |
283 | ssize_t length; | 355 | ssize_t length; |
284 | 356 | ||
285 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled); | 357 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
358 | security_mls_enabled()); | ||
286 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 359 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
287 | } | 360 | } |
288 | 361 | ||
289 | static const struct file_operations sel_mls_ops = { | 362 | static const struct file_operations sel_mls_ops = { |
290 | .read = sel_read_mls, | 363 | .read = sel_read_mls, |
364 | .llseek = generic_file_llseek, | ||
365 | }; | ||
366 | |||
367 | struct policy_load_memory { | ||
368 | size_t len; | ||
369 | void *data; | ||
370 | }; | ||
371 | |||
372 | static int sel_open_policy(struct inode *inode, struct file *filp) | ||
373 | { | ||
374 | struct policy_load_memory *plm = NULL; | ||
375 | int rc; | ||
376 | |||
377 | BUG_ON(filp->private_data); | ||
378 | |||
379 | mutex_lock(&sel_mutex); | ||
380 | |||
381 | rc = task_has_security(current, SECURITY__READ_POLICY); | ||
382 | if (rc) | ||
383 | goto err; | ||
384 | |||
385 | rc = -EBUSY; | ||
386 | if (policy_opened) | ||
387 | goto err; | ||
388 | |||
389 | rc = -ENOMEM; | ||
390 | plm = kzalloc(sizeof(*plm), GFP_KERNEL); | ||
391 | if (!plm) | ||
392 | goto err; | ||
393 | |||
394 | if (i_size_read(inode) != security_policydb_len()) { | ||
395 | mutex_lock(&inode->i_mutex); | ||
396 | i_size_write(inode, security_policydb_len()); | ||
397 | mutex_unlock(&inode->i_mutex); | ||
398 | } | ||
399 | |||
400 | rc = security_read_policy(&plm->data, &plm->len); | ||
401 | if (rc) | ||
402 | goto err; | ||
403 | |||
404 | policy_opened = 1; | ||
405 | |||
406 | filp->private_data = plm; | ||
407 | |||
408 | mutex_unlock(&sel_mutex); | ||
409 | |||
410 | return 0; | ||
411 | err: | ||
412 | mutex_unlock(&sel_mutex); | ||
413 | |||
414 | if (plm) | ||
415 | vfree(plm->data); | ||
416 | kfree(plm); | ||
417 | return rc; | ||
418 | } | ||
419 | |||
420 | static int sel_release_policy(struct inode *inode, struct file *filp) | ||
421 | { | ||
422 | struct policy_load_memory *plm = filp->private_data; | ||
423 | |||
424 | BUG_ON(!plm); | ||
425 | |||
426 | policy_opened = 0; | ||
427 | |||
428 | vfree(plm->data); | ||
429 | kfree(plm); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static ssize_t sel_read_policy(struct file *filp, char __user *buf, | ||
435 | size_t count, loff_t *ppos) | ||
436 | { | ||
437 | struct policy_load_memory *plm = filp->private_data; | ||
438 | int ret; | ||
439 | |||
440 | mutex_lock(&sel_mutex); | ||
441 | |||
442 | ret = task_has_security(current, SECURITY__READ_POLICY); | ||
443 | if (ret) | ||
444 | goto out; | ||
445 | |||
446 | ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len); | ||
447 | out: | ||
448 | mutex_unlock(&sel_mutex); | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | static int sel_mmap_policy_fault(struct vm_area_struct *vma, | ||
453 | struct vm_fault *vmf) | ||
454 | { | ||
455 | struct policy_load_memory *plm = vma->vm_file->private_data; | ||
456 | unsigned long offset; | ||
457 | struct page *page; | ||
458 | |||
459 | if (vmf->flags & (FAULT_FLAG_MKWRITE | FAULT_FLAG_WRITE)) | ||
460 | return VM_FAULT_SIGBUS; | ||
461 | |||
462 | offset = vmf->pgoff << PAGE_SHIFT; | ||
463 | if (offset >= roundup(plm->len, PAGE_SIZE)) | ||
464 | return VM_FAULT_SIGBUS; | ||
465 | |||
466 | page = vmalloc_to_page(plm->data + offset); | ||
467 | get_page(page); | ||
468 | |||
469 | vmf->page = page; | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static struct vm_operations_struct sel_mmap_policy_ops = { | ||
475 | .fault = sel_mmap_policy_fault, | ||
476 | .page_mkwrite = sel_mmap_policy_fault, | ||
477 | }; | ||
478 | |||
479 | int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma) | ||
480 | { | ||
481 | if (vma->vm_flags & VM_SHARED) { | ||
482 | /* do not allow mprotect to make mapping writable */ | ||
483 | vma->vm_flags &= ~VM_MAYWRITE; | ||
484 | |||
485 | if (vma->vm_flags & VM_WRITE) | ||
486 | return -EACCES; | ||
487 | } | ||
488 | |||
489 | vma->vm_flags |= VM_RESERVED; | ||
490 | vma->vm_ops = &sel_mmap_policy_ops; | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static const struct file_operations sel_policy_ops = { | ||
496 | .open = sel_open_policy, | ||
497 | .read = sel_read_policy, | ||
498 | .mmap = sel_mmap_policy, | ||
499 | .release = sel_release_policy, | ||
291 | }; | 500 | }; |
292 | 501 | ||
293 | static ssize_t sel_write_load(struct file *file, const char __user *buf, | 502 | static ssize_t sel_write_load(struct file *file, const char __user *buf, |
294 | size_t count, loff_t *ppos) | 503 | size_t count, loff_t *ppos) |
295 | 504 | ||
296 | { | 505 | { |
297 | int ret; | ||
298 | ssize_t length; | 506 | ssize_t length; |
299 | void *data = NULL; | 507 | void *data = NULL; |
300 | 508 | ||
@@ -304,17 +512,19 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
304 | if (length) | 512 | if (length) |
305 | goto out; | 513 | goto out; |
306 | 514 | ||
307 | if (*ppos != 0) { | 515 | /* No partial writes. */ |
308 | /* No partial writes. */ | 516 | length = -EINVAL; |
309 | length = -EINVAL; | 517 | if (*ppos != 0) |
310 | goto out; | 518 | goto out; |
311 | } | ||
312 | 519 | ||
313 | if ((count > 64 * 1024 * 1024) | 520 | length = -EFBIG; |
314 | || (data = vmalloc(count)) == NULL) { | 521 | if (count > 64 * 1024 * 1024) |
315 | length = -ENOMEM; | 522 | goto out; |
523 | |||
524 | length = -ENOMEM; | ||
525 | data = vmalloc(count); | ||
526 | if (!data) | ||
316 | goto out; | 527 | goto out; |
317 | } | ||
318 | 528 | ||
319 | length = -EFAULT; | 529 | length = -EFAULT; |
320 | if (copy_from_user(data, buf, count) != 0) | 530 | if (copy_from_user(data, buf, count) != 0) |
@@ -324,23 +534,19 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
324 | if (length) | 534 | if (length) |
325 | goto out; | 535 | goto out; |
326 | 536 | ||
327 | ret = sel_make_bools(); | 537 | length = sel_make_bools(); |
328 | if (ret) { | 538 | if (length) |
329 | length = ret; | ||
330 | goto out1; | 539 | goto out1; |
331 | } | ||
332 | 540 | ||
333 | ret = sel_make_classes(); | 541 | length = sel_make_classes(); |
334 | if (ret) { | 542 | if (length) |
335 | length = ret; | ||
336 | goto out1; | 543 | goto out1; |
337 | } | ||
338 | 544 | ||
339 | ret = sel_make_policycap(); | 545 | length = sel_make_policycap(); |
340 | if (ret) | 546 | if (length) |
341 | length = ret; | 547 | goto out1; |
342 | else | 548 | |
343 | length = count; | 549 | length = count; |
344 | 550 | ||
345 | out1: | 551 | out1: |
346 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, | 552 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, |
@@ -355,30 +561,31 @@ out: | |||
355 | 561 | ||
356 | static const struct file_operations sel_load_ops = { | 562 | static const struct file_operations sel_load_ops = { |
357 | .write = sel_write_load, | 563 | .write = sel_write_load, |
564 | .llseek = generic_file_llseek, | ||
358 | }; | 565 | }; |
359 | 566 | ||
360 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | 567 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) |
361 | { | 568 | { |
362 | char *canon; | 569 | char *canon = NULL; |
363 | u32 sid, len; | 570 | u32 sid, len; |
364 | ssize_t length; | 571 | ssize_t length; |
365 | 572 | ||
366 | length = task_has_security(current, SECURITY__CHECK_CONTEXT); | 573 | length = task_has_security(current, SECURITY__CHECK_CONTEXT); |
367 | if (length) | 574 | if (length) |
368 | return length; | 575 | goto out; |
369 | 576 | ||
370 | length = security_context_to_sid(buf, size, &sid); | 577 | length = security_context_to_sid(buf, size, &sid); |
371 | if (length < 0) | 578 | if (length) |
372 | return length; | 579 | goto out; |
373 | 580 | ||
374 | length = security_sid_to_context(sid, &canon, &len); | 581 | length = security_sid_to_context(sid, &canon, &len); |
375 | if (length < 0) | 582 | if (length) |
376 | return length; | 583 | goto out; |
377 | 584 | ||
585 | length = -ERANGE; | ||
378 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 586 | if (len > SIMPLE_TRANSACTION_LIMIT) { |
379 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " | 587 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " |
380 | "payload max\n", __func__, len); | 588 | "payload max\n", __func__, len); |
381 | length = -ERANGE; | ||
382 | goto out; | 589 | goto out; |
383 | } | 590 | } |
384 | 591 | ||
@@ -402,23 +609,28 @@ static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, | |||
402 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, | 609 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, |
403 | size_t count, loff_t *ppos) | 610 | size_t count, loff_t *ppos) |
404 | { | 611 | { |
405 | char *page; | 612 | char *page = NULL; |
406 | ssize_t length; | 613 | ssize_t length; |
407 | unsigned int new_value; | 614 | unsigned int new_value; |
408 | 615 | ||
409 | length = task_has_security(current, SECURITY__SETCHECKREQPROT); | 616 | length = task_has_security(current, SECURITY__SETCHECKREQPROT); |
410 | if (length) | 617 | if (length) |
411 | return length; | 618 | goto out; |
412 | 619 | ||
620 | length = -ENOMEM; | ||
413 | if (count >= PAGE_SIZE) | 621 | if (count >= PAGE_SIZE) |
414 | return -ENOMEM; | 622 | goto out; |
415 | if (*ppos != 0) { | 623 | |
416 | /* No partial writes. */ | 624 | /* No partial writes. */ |
417 | return -EINVAL; | 625 | length = -EINVAL; |
418 | } | 626 | if (*ppos != 0) |
627 | goto out; | ||
628 | |||
629 | length = -ENOMEM; | ||
419 | page = (char *)get_zeroed_page(GFP_KERNEL); | 630 | page = (char *)get_zeroed_page(GFP_KERNEL); |
420 | if (!page) | 631 | if (!page) |
421 | return -ENOMEM; | 632 | goto out; |
633 | |||
422 | length = -EFAULT; | 634 | length = -EFAULT; |
423 | if (copy_from_user(page, buf, count)) | 635 | if (copy_from_user(page, buf, count)) |
424 | goto out; | 636 | goto out; |
@@ -436,6 +648,7 @@ out: | |||
436 | static const struct file_operations sel_checkreqprot_ops = { | 648 | static const struct file_operations sel_checkreqprot_ops = { |
437 | .read = sel_read_checkreqprot, | 649 | .read = sel_read_checkreqprot, |
438 | .write = sel_write_checkreqprot, | 650 | .write = sel_write_checkreqprot, |
651 | .llseek = generic_file_llseek, | ||
439 | }; | 652 | }; |
440 | 653 | ||
441 | /* | 654 | /* |
@@ -481,6 +694,7 @@ static const struct file_operations transaction_ops = { | |||
481 | .write = selinux_transaction_write, | 694 | .write = selinux_transaction_write, |
482 | .read = simple_transaction_read, | 695 | .read = simple_transaction_read, |
483 | .release = simple_transaction_release, | 696 | .release = simple_transaction_release, |
697 | .llseek = generic_file_llseek, | ||
484 | }; | 698 | }; |
485 | 699 | ||
486 | /* | 700 | /* |
@@ -491,173 +705,170 @@ static const struct file_operations transaction_ops = { | |||
491 | 705 | ||
492 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | 706 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) |
493 | { | 707 | { |
494 | char *scon, *tcon; | 708 | char *scon = NULL, *tcon = NULL; |
495 | u32 ssid, tsid; | 709 | u32 ssid, tsid; |
496 | u16 tclass; | 710 | u16 tclass; |
497 | u32 req; | ||
498 | struct av_decision avd; | 711 | struct av_decision avd; |
499 | ssize_t length; | 712 | ssize_t length; |
500 | 713 | ||
501 | length = task_has_security(current, SECURITY__COMPUTE_AV); | 714 | length = task_has_security(current, SECURITY__COMPUTE_AV); |
502 | if (length) | 715 | if (length) |
503 | return length; | 716 | goto out; |
504 | 717 | ||
505 | length = -ENOMEM; | 718 | length = -ENOMEM; |
506 | scon = kzalloc(size+1, GFP_KERNEL); | 719 | scon = kzalloc(size + 1, GFP_KERNEL); |
507 | if (!scon) | 720 | if (!scon) |
508 | return length; | 721 | goto out; |
509 | 722 | ||
510 | tcon = kzalloc(size+1, GFP_KERNEL); | 723 | length = -ENOMEM; |
724 | tcon = kzalloc(size + 1, GFP_KERNEL); | ||
511 | if (!tcon) | 725 | if (!tcon) |
512 | goto out; | 726 | goto out; |
513 | 727 | ||
514 | length = -EINVAL; | 728 | length = -EINVAL; |
515 | if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4) | 729 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
516 | goto out2; | 730 | goto out; |
517 | 731 | ||
518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 732 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
519 | if (length < 0) | 733 | if (length) |
520 | goto out2; | 734 | goto out; |
521 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | ||
522 | if (length < 0) | ||
523 | goto out2; | ||
524 | 735 | ||
525 | length = security_compute_av(ssid, tsid, tclass, req, &avd); | 736 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
526 | if (length < 0) | 737 | if (length) |
527 | goto out2; | 738 | goto out; |
739 | |||
740 | security_compute_av_user(ssid, tsid, tclass, &avd); | ||
528 | 741 | ||
529 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, | 742 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, |
530 | "%x %x %x %x %u %x", | 743 | "%x %x %x %x %u %x", |
531 | avd.allowed, 0xffffffff, | 744 | avd.allowed, 0xffffffff, |
532 | avd.auditallow, avd.auditdeny, | 745 | avd.auditallow, avd.auditdeny, |
533 | avd.seqno, avd.flags); | 746 | avd.seqno, avd.flags); |
534 | out2: | ||
535 | kfree(tcon); | ||
536 | out: | 747 | out: |
748 | kfree(tcon); | ||
537 | kfree(scon); | 749 | kfree(scon); |
538 | return length; | 750 | return length; |
539 | } | 751 | } |
540 | 752 | ||
541 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | 753 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) |
542 | { | 754 | { |
543 | char *scon, *tcon; | 755 | char *scon = NULL, *tcon = NULL; |
544 | u32 ssid, tsid, newsid; | 756 | u32 ssid, tsid, newsid; |
545 | u16 tclass; | 757 | u16 tclass; |
546 | ssize_t length; | 758 | ssize_t length; |
547 | char *newcon; | 759 | char *newcon = NULL; |
548 | u32 len; | 760 | u32 len; |
549 | 761 | ||
550 | length = task_has_security(current, SECURITY__COMPUTE_CREATE); | 762 | length = task_has_security(current, SECURITY__COMPUTE_CREATE); |
551 | if (length) | 763 | if (length) |
552 | return length; | 764 | goto out; |
553 | 765 | ||
554 | length = -ENOMEM; | 766 | length = -ENOMEM; |
555 | scon = kzalloc(size+1, GFP_KERNEL); | 767 | scon = kzalloc(size + 1, GFP_KERNEL); |
556 | if (!scon) | 768 | if (!scon) |
557 | return length; | 769 | goto out; |
558 | 770 | ||
559 | tcon = kzalloc(size+1, GFP_KERNEL); | 771 | length = -ENOMEM; |
772 | tcon = kzalloc(size + 1, GFP_KERNEL); | ||
560 | if (!tcon) | 773 | if (!tcon) |
561 | goto out; | 774 | goto out; |
562 | 775 | ||
563 | length = -EINVAL; | 776 | length = -EINVAL; |
564 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 777 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
565 | goto out2; | 778 | goto out; |
779 | |||
780 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); | ||
781 | if (length) | ||
782 | goto out; | ||
566 | 783 | ||
567 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 784 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
568 | if (length < 0) | 785 | if (length) |
569 | goto out2; | 786 | goto out; |
570 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | ||
571 | if (length < 0) | ||
572 | goto out2; | ||
573 | 787 | ||
574 | length = security_transition_sid(ssid, tsid, tclass, &newsid); | 788 | length = security_transition_sid_user(ssid, tsid, tclass, &newsid); |
575 | if (length < 0) | 789 | if (length) |
576 | goto out2; | 790 | goto out; |
577 | 791 | ||
578 | length = security_sid_to_context(newsid, &newcon, &len); | 792 | length = security_sid_to_context(newsid, &newcon, &len); |
579 | if (length < 0) | 793 | if (length) |
580 | goto out2; | 794 | goto out; |
581 | 795 | ||
796 | length = -ERANGE; | ||
582 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 797 | if (len > SIMPLE_TRANSACTION_LIMIT) { |
583 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " | 798 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " |
584 | "payload max\n", __func__, len); | 799 | "payload max\n", __func__, len); |
585 | length = -ERANGE; | 800 | goto out; |
586 | goto out3; | ||
587 | } | 801 | } |
588 | 802 | ||
589 | memcpy(buf, newcon, len); | 803 | memcpy(buf, newcon, len); |
590 | length = len; | 804 | length = len; |
591 | out3: | 805 | out: |
592 | kfree(newcon); | 806 | kfree(newcon); |
593 | out2: | ||
594 | kfree(tcon); | 807 | kfree(tcon); |
595 | out: | ||
596 | kfree(scon); | 808 | kfree(scon); |
597 | return length; | 809 | return length; |
598 | } | 810 | } |
599 | 811 | ||
600 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | 812 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) |
601 | { | 813 | { |
602 | char *scon, *tcon; | 814 | char *scon = NULL, *tcon = NULL; |
603 | u32 ssid, tsid, newsid; | 815 | u32 ssid, tsid, newsid; |
604 | u16 tclass; | 816 | u16 tclass; |
605 | ssize_t length; | 817 | ssize_t length; |
606 | char *newcon; | 818 | char *newcon = NULL; |
607 | u32 len; | 819 | u32 len; |
608 | 820 | ||
609 | length = task_has_security(current, SECURITY__COMPUTE_RELABEL); | 821 | length = task_has_security(current, SECURITY__COMPUTE_RELABEL); |
610 | if (length) | 822 | if (length) |
611 | return length; | 823 | goto out; |
612 | 824 | ||
613 | length = -ENOMEM; | 825 | length = -ENOMEM; |
614 | scon = kzalloc(size+1, GFP_KERNEL); | 826 | scon = kzalloc(size + 1, GFP_KERNEL); |
615 | if (!scon) | 827 | if (!scon) |
616 | return length; | 828 | goto out; |
617 | 829 | ||
618 | tcon = kzalloc(size+1, GFP_KERNEL); | 830 | length = -ENOMEM; |
831 | tcon = kzalloc(size + 1, GFP_KERNEL); | ||
619 | if (!tcon) | 832 | if (!tcon) |
620 | goto out; | 833 | goto out; |
621 | 834 | ||
622 | length = -EINVAL; | 835 | length = -EINVAL; |
623 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 836 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
624 | goto out2; | 837 | goto out; |
625 | 838 | ||
626 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 839 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
627 | if (length < 0) | 840 | if (length) |
628 | goto out2; | 841 | goto out; |
629 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 842 | |
630 | if (length < 0) | 843 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
631 | goto out2; | 844 | if (length) |
845 | goto out; | ||
632 | 846 | ||
633 | length = security_change_sid(ssid, tsid, tclass, &newsid); | 847 | length = security_change_sid(ssid, tsid, tclass, &newsid); |
634 | if (length < 0) | 848 | if (length) |
635 | goto out2; | 849 | goto out; |
636 | 850 | ||
637 | length = security_sid_to_context(newsid, &newcon, &len); | 851 | length = security_sid_to_context(newsid, &newcon, &len); |
638 | if (length < 0) | 852 | if (length) |
639 | goto out2; | 853 | goto out; |
640 | 854 | ||
641 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 855 | length = -ERANGE; |
642 | length = -ERANGE; | 856 | if (len > SIMPLE_TRANSACTION_LIMIT) |
643 | goto out3; | 857 | goto out; |
644 | } | ||
645 | 858 | ||
646 | memcpy(buf, newcon, len); | 859 | memcpy(buf, newcon, len); |
647 | length = len; | 860 | length = len; |
648 | out3: | 861 | out: |
649 | kfree(newcon); | 862 | kfree(newcon); |
650 | out2: | ||
651 | kfree(tcon); | 863 | kfree(tcon); |
652 | out: | ||
653 | kfree(scon); | 864 | kfree(scon); |
654 | return length; | 865 | return length; |
655 | } | 866 | } |
656 | 867 | ||
657 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | 868 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) |
658 | { | 869 | { |
659 | char *con, *user, *ptr; | 870 | char *con = NULL, *user = NULL, *ptr; |
660 | u32 sid, *sids; | 871 | u32 sid, *sids = NULL; |
661 | ssize_t length; | 872 | ssize_t length; |
662 | char *newcon; | 873 | char *newcon; |
663 | int i, rc; | 874 | int i, rc; |
@@ -665,28 +876,29 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
665 | 876 | ||
666 | length = task_has_security(current, SECURITY__COMPUTE_USER); | 877 | length = task_has_security(current, SECURITY__COMPUTE_USER); |
667 | if (length) | 878 | if (length) |
668 | return length; | 879 | goto out;; |
669 | 880 | ||
670 | length = -ENOMEM; | 881 | length = -ENOMEM; |
671 | con = kzalloc(size+1, GFP_KERNEL); | 882 | con = kzalloc(size + 1, GFP_KERNEL); |
672 | if (!con) | 883 | if (!con) |
673 | return length; | 884 | goto out;; |
674 | 885 | ||
675 | user = kzalloc(size+1, GFP_KERNEL); | 886 | length = -ENOMEM; |
887 | user = kzalloc(size + 1, GFP_KERNEL); | ||
676 | if (!user) | 888 | if (!user) |
677 | goto out; | 889 | goto out; |
678 | 890 | ||
679 | length = -EINVAL; | 891 | length = -EINVAL; |
680 | if (sscanf(buf, "%s %s", con, user) != 2) | 892 | if (sscanf(buf, "%s %s", con, user) != 2) |
681 | goto out2; | 893 | goto out; |
682 | 894 | ||
683 | length = security_context_to_sid(con, strlen(con)+1, &sid); | 895 | length = security_context_to_sid(con, strlen(con) + 1, &sid); |
684 | if (length < 0) | 896 | if (length) |
685 | goto out2; | 897 | goto out; |
686 | 898 | ||
687 | length = security_get_user_sids(sid, user, &sids, &nsids); | 899 | length = security_get_user_sids(sid, user, &sids, &nsids); |
688 | if (length < 0) | 900 | if (length) |
689 | goto out2; | 901 | goto out; |
690 | 902 | ||
691 | length = sprintf(buf, "%u", nsids) + 1; | 903 | length = sprintf(buf, "%u", nsids) + 1; |
692 | ptr = buf + length; | 904 | ptr = buf + length; |
@@ -694,82 +906,80 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
694 | rc = security_sid_to_context(sids[i], &newcon, &len); | 906 | rc = security_sid_to_context(sids[i], &newcon, &len); |
695 | if (rc) { | 907 | if (rc) { |
696 | length = rc; | 908 | length = rc; |
697 | goto out3; | 909 | goto out; |
698 | } | 910 | } |
699 | if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { | 911 | if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { |
700 | kfree(newcon); | 912 | kfree(newcon); |
701 | length = -ERANGE; | 913 | length = -ERANGE; |
702 | goto out3; | 914 | goto out; |
703 | } | 915 | } |
704 | memcpy(ptr, newcon, len); | 916 | memcpy(ptr, newcon, len); |
705 | kfree(newcon); | 917 | kfree(newcon); |
706 | ptr += len; | 918 | ptr += len; |
707 | length += len; | 919 | length += len; |
708 | } | 920 | } |
709 | out3: | 921 | out: |
710 | kfree(sids); | 922 | kfree(sids); |
711 | out2: | ||
712 | kfree(user); | 923 | kfree(user); |
713 | out: | ||
714 | kfree(con); | 924 | kfree(con); |
715 | return length; | 925 | return length; |
716 | } | 926 | } |
717 | 927 | ||
718 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | 928 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) |
719 | { | 929 | { |
720 | char *scon, *tcon; | 930 | char *scon = NULL, *tcon = NULL; |
721 | u32 ssid, tsid, newsid; | 931 | u32 ssid, tsid, newsid; |
722 | u16 tclass; | 932 | u16 tclass; |
723 | ssize_t length; | 933 | ssize_t length; |
724 | char *newcon; | 934 | char *newcon = NULL; |
725 | u32 len; | 935 | u32 len; |
726 | 936 | ||
727 | length = task_has_security(current, SECURITY__COMPUTE_MEMBER); | 937 | length = task_has_security(current, SECURITY__COMPUTE_MEMBER); |
728 | if (length) | 938 | if (length) |
729 | return length; | 939 | goto out; |
730 | 940 | ||
731 | length = -ENOMEM; | 941 | length = -ENOMEM; |
732 | scon = kzalloc(size+1, GFP_KERNEL); | 942 | scon = kzalloc(size + 1, GFP_KERNEL); |
733 | if (!scon) | 943 | if (!scon) |
734 | return length; | 944 | goto out;; |
735 | 945 | ||
736 | tcon = kzalloc(size+1, GFP_KERNEL); | 946 | length = -ENOMEM; |
947 | tcon = kzalloc(size + 1, GFP_KERNEL); | ||
737 | if (!tcon) | 948 | if (!tcon) |
738 | goto out; | 949 | goto out; |
739 | 950 | ||
740 | length = -EINVAL; | 951 | length = -EINVAL; |
741 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 952 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
742 | goto out2; | 953 | goto out; |
743 | 954 | ||
744 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 955 | length = security_context_to_sid(scon, strlen(scon) + 1, &ssid); |
745 | if (length < 0) | 956 | if (length) |
746 | goto out2; | 957 | goto out; |
747 | length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); | 958 | |
748 | if (length < 0) | 959 | length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid); |
749 | goto out2; | 960 | if (length) |
961 | goto out; | ||
750 | 962 | ||
751 | length = security_member_sid(ssid, tsid, tclass, &newsid); | 963 | length = security_member_sid(ssid, tsid, tclass, &newsid); |
752 | if (length < 0) | 964 | if (length) |
753 | goto out2; | 965 | goto out; |
754 | 966 | ||
755 | length = security_sid_to_context(newsid, &newcon, &len); | 967 | length = security_sid_to_context(newsid, &newcon, &len); |
756 | if (length < 0) | 968 | if (length) |
757 | goto out2; | 969 | goto out; |
758 | 970 | ||
971 | length = -ERANGE; | ||
759 | if (len > SIMPLE_TRANSACTION_LIMIT) { | 972 | if (len > SIMPLE_TRANSACTION_LIMIT) { |
760 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " | 973 | printk(KERN_ERR "SELinux: %s: context size (%u) exceeds " |
761 | "payload max\n", __func__, len); | 974 | "payload max\n", __func__, len); |
762 | length = -ERANGE; | 975 | goto out; |
763 | goto out3; | ||
764 | } | 976 | } |
765 | 977 | ||
766 | memcpy(buf, newcon, len); | 978 | memcpy(buf, newcon, len); |
767 | length = len; | 979 | length = len; |
768 | out3: | 980 | out: |
769 | kfree(newcon); | 981 | kfree(newcon); |
770 | out2: | ||
771 | kfree(tcon); | 982 | kfree(tcon); |
772 | out: | ||
773 | kfree(scon); | 983 | kfree(scon); |
774 | return length; | 984 | return length; |
775 | } | 985 | } |
@@ -798,16 +1008,14 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
798 | 1008 | ||
799 | mutex_lock(&sel_mutex); | 1009 | mutex_lock(&sel_mutex); |
800 | 1010 | ||
801 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) { | 1011 | ret = -EINVAL; |
802 | ret = -EINVAL; | 1012 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) |
803 | goto out; | 1013 | goto out; |
804 | } | ||
805 | 1014 | ||
1015 | ret = -ENOMEM; | ||
806 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1016 | page = (char *)get_zeroed_page(GFP_KERNEL); |
807 | if (!page) { | 1017 | if (!page) |
808 | ret = -ENOMEM; | ||
809 | goto out; | 1018 | goto out; |
810 | } | ||
811 | 1019 | ||
812 | cur_enforcing = security_get_bool_value(index); | 1020 | cur_enforcing = security_get_bool_value(index); |
813 | if (cur_enforcing < 0) { | 1021 | if (cur_enforcing < 0) { |
@@ -819,8 +1027,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
819 | ret = simple_read_from_buffer(buf, count, ppos, page, length); | 1027 | ret = simple_read_from_buffer(buf, count, ppos, page, length); |
820 | out: | 1028 | out: |
821 | mutex_unlock(&sel_mutex); | 1029 | mutex_unlock(&sel_mutex); |
822 | if (page) | 1030 | free_page((unsigned long)page); |
823 | free_page((unsigned long)page); | ||
824 | return ret; | 1031 | return ret; |
825 | } | 1032 | } |
826 | 1033 | ||
@@ -840,26 +1047,23 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
840 | if (length) | 1047 | if (length) |
841 | goto out; | 1048 | goto out; |
842 | 1049 | ||
843 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) { | 1050 | length = -EINVAL; |
844 | length = -EINVAL; | 1051 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) |
845 | goto out; | 1052 | goto out; |
846 | } | ||
847 | 1053 | ||
848 | if (count >= PAGE_SIZE) { | 1054 | length = -ENOMEM; |
849 | length = -ENOMEM; | 1055 | if (count >= PAGE_SIZE) |
850 | goto out; | 1056 | goto out; |
851 | } | ||
852 | 1057 | ||
853 | if (*ppos != 0) { | 1058 | /* No partial writes. */ |
854 | /* No partial writes. */ | 1059 | length = -EINVAL; |
855 | length = -EINVAL; | 1060 | if (*ppos != 0) |
856 | goto out; | 1061 | goto out; |
857 | } | 1062 | |
1063 | length = -ENOMEM; | ||
858 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1064 | page = (char *)get_zeroed_page(GFP_KERNEL); |
859 | if (!page) { | 1065 | if (!page) |
860 | length = -ENOMEM; | ||
861 | goto out; | 1066 | goto out; |
862 | } | ||
863 | 1067 | ||
864 | length = -EFAULT; | 1068 | length = -EFAULT; |
865 | if (copy_from_user(page, buf, count)) | 1069 | if (copy_from_user(page, buf, count)) |
@@ -877,14 +1081,14 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
877 | 1081 | ||
878 | out: | 1082 | out: |
879 | mutex_unlock(&sel_mutex); | 1083 | mutex_unlock(&sel_mutex); |
880 | if (page) | 1084 | free_page((unsigned long) page); |
881 | free_page((unsigned long) page); | ||
882 | return length; | 1085 | return length; |
883 | } | 1086 | } |
884 | 1087 | ||
885 | static const struct file_operations sel_bool_ops = { | 1088 | static const struct file_operations sel_bool_ops = { |
886 | .read = sel_read_bool, | 1089 | .read = sel_read_bool, |
887 | .write = sel_write_bool, | 1090 | .write = sel_write_bool, |
1091 | .llseek = generic_file_llseek, | ||
888 | }; | 1092 | }; |
889 | 1093 | ||
890 | static ssize_t sel_commit_bools_write(struct file *filep, | 1094 | static ssize_t sel_commit_bools_write(struct file *filep, |
@@ -901,19 +1105,19 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
901 | if (length) | 1105 | if (length) |
902 | goto out; | 1106 | goto out; |
903 | 1107 | ||
904 | if (count >= PAGE_SIZE) { | 1108 | length = -ENOMEM; |
905 | length = -ENOMEM; | 1109 | if (count >= PAGE_SIZE) |
906 | goto out; | 1110 | goto out; |
907 | } | 1111 | |
908 | if (*ppos != 0) { | 1112 | /* No partial writes. */ |
909 | /* No partial writes. */ | 1113 | length = -EINVAL; |
1114 | if (*ppos != 0) | ||
910 | goto out; | 1115 | goto out; |
911 | } | 1116 | |
1117 | length = -ENOMEM; | ||
912 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1118 | page = (char *)get_zeroed_page(GFP_KERNEL); |
913 | if (!page) { | 1119 | if (!page) |
914 | length = -ENOMEM; | ||
915 | goto out; | 1120 | goto out; |
916 | } | ||
917 | 1121 | ||
918 | length = -EFAULT; | 1122 | length = -EFAULT; |
919 | if (copy_from_user(page, buf, count)) | 1123 | if (copy_from_user(page, buf, count)) |
@@ -923,51 +1127,57 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
923 | if (sscanf(page, "%d", &new_value) != 1) | 1127 | if (sscanf(page, "%d", &new_value) != 1) |
924 | goto out; | 1128 | goto out; |
925 | 1129 | ||
1130 | length = 0; | ||
926 | if (new_value && bool_pending_values) | 1131 | if (new_value && bool_pending_values) |
927 | security_set_bools(bool_num, bool_pending_values); | 1132 | length = security_set_bools(bool_num, bool_pending_values); |
928 | 1133 | ||
929 | length = count; | 1134 | if (!length) |
1135 | length = count; | ||
930 | 1136 | ||
931 | out: | 1137 | out: |
932 | mutex_unlock(&sel_mutex); | 1138 | mutex_unlock(&sel_mutex); |
933 | if (page) | 1139 | free_page((unsigned long) page); |
934 | free_page((unsigned long) page); | ||
935 | return length; | 1140 | return length; |
936 | } | 1141 | } |
937 | 1142 | ||
938 | static const struct file_operations sel_commit_bools_ops = { | 1143 | static const struct file_operations sel_commit_bools_ops = { |
939 | .write = sel_commit_bools_write, | 1144 | .write = sel_commit_bools_write, |
1145 | .llseek = generic_file_llseek, | ||
940 | }; | 1146 | }; |
941 | 1147 | ||
942 | static void sel_remove_entries(struct dentry *de) | 1148 | static void sel_remove_entries(struct dentry *de) |
943 | { | 1149 | { |
944 | struct list_head *node; | 1150 | struct list_head *node; |
945 | 1151 | ||
946 | spin_lock(&dcache_lock); | 1152 | spin_lock(&de->d_lock); |
947 | node = de->d_subdirs.next; | 1153 | node = de->d_subdirs.next; |
948 | while (node != &de->d_subdirs) { | 1154 | while (node != &de->d_subdirs) { |
949 | struct dentry *d = list_entry(node, struct dentry, d_u.d_child); | 1155 | struct dentry *d = list_entry(node, struct dentry, d_u.d_child); |
1156 | |||
1157 | spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); | ||
950 | list_del_init(node); | 1158 | list_del_init(node); |
951 | 1159 | ||
952 | if (d->d_inode) { | 1160 | if (d->d_inode) { |
953 | d = dget_locked(d); | 1161 | dget_dlock(d); |
954 | spin_unlock(&dcache_lock); | 1162 | spin_unlock(&de->d_lock); |
1163 | spin_unlock(&d->d_lock); | ||
955 | d_delete(d); | 1164 | d_delete(d); |
956 | simple_unlink(de->d_inode, d); | 1165 | simple_unlink(de->d_inode, d); |
957 | dput(d); | 1166 | dput(d); |
958 | spin_lock(&dcache_lock); | 1167 | spin_lock(&de->d_lock); |
959 | } | 1168 | } else |
1169 | spin_unlock(&d->d_lock); | ||
960 | node = de->d_subdirs.next; | 1170 | node = de->d_subdirs.next; |
961 | } | 1171 | } |
962 | 1172 | ||
963 | spin_unlock(&dcache_lock); | 1173 | spin_unlock(&de->d_lock); |
964 | } | 1174 | } |
965 | 1175 | ||
966 | #define BOOL_DIR_NAME "booleans" | 1176 | #define BOOL_DIR_NAME "booleans" |
967 | 1177 | ||
968 | static int sel_make_bools(void) | 1178 | static int sel_make_bools(void) |
969 | { | 1179 | { |
970 | int i, ret = 0; | 1180 | int i, ret; |
971 | ssize_t len; | 1181 | ssize_t len; |
972 | struct dentry *dentry = NULL; | 1182 | struct dentry *dentry = NULL; |
973 | struct dentry *dir = bool_dir; | 1183 | struct dentry *dir = bool_dir; |
@@ -979,6 +1189,8 @@ static int sel_make_bools(void) | |||
979 | u32 sid; | 1189 | u32 sid; |
980 | 1190 | ||
981 | /* remove any existing files */ | 1191 | /* remove any existing files */ |
1192 | for (i = 0; i < bool_num; i++) | ||
1193 | kfree(bool_pending_names[i]); | ||
982 | kfree(bool_pending_names); | 1194 | kfree(bool_pending_names); |
983 | kfree(bool_pending_values); | 1195 | kfree(bool_pending_values); |
984 | bool_pending_names = NULL; | 1196 | bool_pending_names = NULL; |
@@ -986,38 +1198,40 @@ static int sel_make_bools(void) | |||
986 | 1198 | ||
987 | sel_remove_entries(dir); | 1199 | sel_remove_entries(dir); |
988 | 1200 | ||
1201 | ret = -ENOMEM; | ||
989 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1202 | page = (char *)get_zeroed_page(GFP_KERNEL); |
990 | if (!page) | 1203 | if (!page) |
991 | return -ENOMEM; | 1204 | goto out; |
992 | 1205 | ||
993 | ret = security_get_bools(&num, &names, &values); | 1206 | ret = security_get_bools(&num, &names, &values); |
994 | if (ret != 0) | 1207 | if (ret) |
995 | goto out; | 1208 | goto out; |
996 | 1209 | ||
997 | for (i = 0; i < num; i++) { | 1210 | for (i = 0; i < num; i++) { |
1211 | ret = -ENOMEM; | ||
998 | dentry = d_alloc_name(dir, names[i]); | 1212 | dentry = d_alloc_name(dir, names[i]); |
999 | if (!dentry) { | 1213 | if (!dentry) |
1000 | ret = -ENOMEM; | 1214 | goto out; |
1001 | goto err; | 1215 | |
1002 | } | 1216 | ret = -ENOMEM; |
1003 | inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); | 1217 | inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); |
1004 | if (!inode) { | 1218 | if (!inode) |
1005 | ret = -ENOMEM; | 1219 | goto out; |
1006 | goto err; | ||
1007 | } | ||
1008 | 1220 | ||
1221 | ret = -EINVAL; | ||
1009 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | 1222 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); |
1010 | if (len < 0) { | 1223 | if (len < 0) |
1011 | ret = -EINVAL; | 1224 | goto out; |
1012 | goto err; | 1225 | |
1013 | } else if (len >= PAGE_SIZE) { | 1226 | ret = -ENAMETOOLONG; |
1014 | ret = -ENAMETOOLONG; | 1227 | if (len >= PAGE_SIZE) |
1015 | goto err; | 1228 | goto out; |
1016 | } | 1229 | |
1017 | isec = (struct inode_security_struct *)inode->i_security; | 1230 | isec = (struct inode_security_struct *)inode->i_security; |
1018 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); | 1231 | ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid); |
1019 | if (ret) | 1232 | if (ret) |
1020 | goto err; | 1233 | goto out; |
1234 | |||
1021 | isec->sid = sid; | 1235 | isec->sid = sid; |
1022 | isec->initialized = 1; | 1236 | isec->initialized = 1; |
1023 | inode->i_fop = &sel_bool_ops; | 1237 | inode->i_fop = &sel_bool_ops; |
@@ -1027,10 +1241,12 @@ static int sel_make_bools(void) | |||
1027 | bool_num = num; | 1241 | bool_num = num; |
1028 | bool_pending_names = names; | 1242 | bool_pending_names = names; |
1029 | bool_pending_values = values; | 1243 | bool_pending_values = values; |
1244 | |||
1245 | free_page((unsigned long)page); | ||
1246 | return 0; | ||
1030 | out: | 1247 | out: |
1031 | free_page((unsigned long)page); | 1248 | free_page((unsigned long)page); |
1032 | return ret; | 1249 | |
1033 | err: | ||
1034 | if (names) { | 1250 | if (names) { |
1035 | for (i = 0; i < num; i++) | 1251 | for (i = 0; i < num; i++) |
1036 | kfree(names[i]); | 1252 | kfree(names[i]); |
@@ -1038,8 +1254,8 @@ err: | |||
1038 | } | 1254 | } |
1039 | kfree(values); | 1255 | kfree(values); |
1040 | sel_remove_entries(dir); | 1256 | sel_remove_entries(dir); |
1041 | ret = -ENOMEM; | 1257 | |
1042 | goto out; | 1258 | return ret; |
1043 | } | 1259 | } |
1044 | 1260 | ||
1045 | #define NULL_FILE_NAME "null" | 1261 | #define NULL_FILE_NAME "null" |
@@ -1061,47 +1277,41 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file, | |||
1061 | size_t count, loff_t *ppos) | 1277 | size_t count, loff_t *ppos) |
1062 | 1278 | ||
1063 | { | 1279 | { |
1064 | char *page; | 1280 | char *page = NULL; |
1065 | ssize_t ret; | 1281 | ssize_t ret; |
1066 | int new_value; | 1282 | int new_value; |
1067 | 1283 | ||
1068 | if (count >= PAGE_SIZE) { | 1284 | ret = task_has_security(current, SECURITY__SETSECPARAM); |
1069 | ret = -ENOMEM; | 1285 | if (ret) |
1070 | goto out; | 1286 | goto out; |
1071 | } | ||
1072 | 1287 | ||
1073 | if (*ppos != 0) { | 1288 | ret = -ENOMEM; |
1074 | /* No partial writes. */ | 1289 | if (count >= PAGE_SIZE) |
1075 | ret = -EINVAL; | ||
1076 | goto out; | 1290 | goto out; |
1077 | } | ||
1078 | 1291 | ||
1292 | /* No partial writes. */ | ||
1293 | ret = -EINVAL; | ||
1294 | if (*ppos != 0) | ||
1295 | goto out; | ||
1296 | |||
1297 | ret = -ENOMEM; | ||
1079 | page = (char *)get_zeroed_page(GFP_KERNEL); | 1298 | page = (char *)get_zeroed_page(GFP_KERNEL); |
1080 | if (!page) { | 1299 | if (!page) |
1081 | ret = -ENOMEM; | ||
1082 | goto out; | 1300 | goto out; |
1083 | } | ||
1084 | 1301 | ||
1085 | if (copy_from_user(page, buf, count)) { | 1302 | ret = -EFAULT; |
1086 | ret = -EFAULT; | 1303 | if (copy_from_user(page, buf, count)) |
1087 | goto out_free; | 1304 | goto out; |
1088 | } | ||
1089 | 1305 | ||
1090 | if (sscanf(page, "%u", &new_value) != 1) { | 1306 | ret = -EINVAL; |
1091 | ret = -EINVAL; | 1307 | if (sscanf(page, "%u", &new_value) != 1) |
1092 | goto out; | 1308 | goto out; |
1093 | } | ||
1094 | 1309 | ||
1095 | if (new_value != avc_cache_threshold) { | 1310 | avc_cache_threshold = new_value; |
1096 | ret = task_has_security(current, SECURITY__SETSECPARAM); | 1311 | |
1097 | if (ret) | ||
1098 | goto out_free; | ||
1099 | avc_cache_threshold = new_value; | ||
1100 | } | ||
1101 | ret = count; | 1312 | ret = count; |
1102 | out_free: | ||
1103 | free_page((unsigned long)page); | ||
1104 | out: | 1313 | out: |
1314 | free_page((unsigned long)page); | ||
1105 | return ret; | 1315 | return ret; |
1106 | } | 1316 | } |
1107 | 1317 | ||
@@ -1109,28 +1319,29 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, | |||
1109 | size_t count, loff_t *ppos) | 1319 | size_t count, loff_t *ppos) |
1110 | { | 1320 | { |
1111 | char *page; | 1321 | char *page; |
1112 | ssize_t ret = 0; | 1322 | ssize_t length; |
1113 | 1323 | ||
1114 | page = (char *)__get_free_page(GFP_KERNEL); | 1324 | page = (char *)__get_free_page(GFP_KERNEL); |
1115 | if (!page) { | 1325 | if (!page) |
1116 | ret = -ENOMEM; | 1326 | return -ENOMEM; |
1117 | goto out; | 1327 | |
1118 | } | 1328 | length = avc_get_hash_stats(page); |
1119 | ret = avc_get_hash_stats(page); | 1329 | if (length >= 0) |
1120 | if (ret >= 0) | 1330 | length = simple_read_from_buffer(buf, count, ppos, page, length); |
1121 | ret = simple_read_from_buffer(buf, count, ppos, page, ret); | ||
1122 | free_page((unsigned long)page); | 1331 | free_page((unsigned long)page); |
1123 | out: | 1332 | |
1124 | return ret; | 1333 | return length; |
1125 | } | 1334 | } |
1126 | 1335 | ||
1127 | static const struct file_operations sel_avc_cache_threshold_ops = { | 1336 | static const struct file_operations sel_avc_cache_threshold_ops = { |
1128 | .read = sel_read_avc_cache_threshold, | 1337 | .read = sel_read_avc_cache_threshold, |
1129 | .write = sel_write_avc_cache_threshold, | 1338 | .write = sel_write_avc_cache_threshold, |
1339 | .llseek = generic_file_llseek, | ||
1130 | }; | 1340 | }; |
1131 | 1341 | ||
1132 | static const struct file_operations sel_avc_hash_stats_ops = { | 1342 | static const struct file_operations sel_avc_hash_stats_ops = { |
1133 | .read = sel_read_avc_hash_stats, | 1343 | .read = sel_read_avc_hash_stats, |
1344 | .llseek = generic_file_llseek, | ||
1134 | }; | 1345 | }; |
1135 | 1346 | ||
1136 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 1347 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
@@ -1201,7 +1412,7 @@ static const struct file_operations sel_avc_cache_stats_ops = { | |||
1201 | 1412 | ||
1202 | static int sel_make_avc_files(struct dentry *dir) | 1413 | static int sel_make_avc_files(struct dentry *dir) |
1203 | { | 1414 | { |
1204 | int i, ret = 0; | 1415 | int i; |
1205 | static struct tree_descr files[] = { | 1416 | static struct tree_descr files[] = { |
1206 | { "cache_threshold", | 1417 | { "cache_threshold", |
1207 | &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR }, | 1418 | &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR }, |
@@ -1216,22 +1427,19 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1216 | struct dentry *dentry; | 1427 | struct dentry *dentry; |
1217 | 1428 | ||
1218 | dentry = d_alloc_name(dir, files[i].name); | 1429 | dentry = d_alloc_name(dir, files[i].name); |
1219 | if (!dentry) { | 1430 | if (!dentry) |
1220 | ret = -ENOMEM; | 1431 | return -ENOMEM; |
1221 | goto out; | ||
1222 | } | ||
1223 | 1432 | ||
1224 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); | 1433 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); |
1225 | if (!inode) { | 1434 | if (!inode) |
1226 | ret = -ENOMEM; | 1435 | return -ENOMEM; |
1227 | goto out; | 1436 | |
1228 | } | ||
1229 | inode->i_fop = files[i].ops; | 1437 | inode->i_fop = files[i].ops; |
1230 | inode->i_ino = ++sel_last_ino; | 1438 | inode->i_ino = ++sel_last_ino; |
1231 | d_add(dentry, inode); | 1439 | d_add(dentry, inode); |
1232 | } | 1440 | } |
1233 | out: | 1441 | |
1234 | return ret; | 1442 | return 0; |
1235 | } | 1443 | } |
1236 | 1444 | ||
1237 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, | 1445 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, |
@@ -1245,7 +1453,7 @@ static ssize_t sel_read_initcon(struct file *file, char __user *buf, | |||
1245 | inode = file->f_path.dentry->d_inode; | 1453 | inode = file->f_path.dentry->d_inode; |
1246 | sid = inode->i_ino&SEL_INO_MASK; | 1454 | sid = inode->i_ino&SEL_INO_MASK; |
1247 | ret = security_sid_to_context(sid, &con, &len); | 1455 | ret = security_sid_to_context(sid, &con, &len); |
1248 | if (ret < 0) | 1456 | if (ret) |
1249 | return ret; | 1457 | return ret; |
1250 | 1458 | ||
1251 | ret = simple_read_from_buffer(buf, count, ppos, con, len); | 1459 | ret = simple_read_from_buffer(buf, count, ppos, con, len); |
@@ -1255,32 +1463,30 @@ static ssize_t sel_read_initcon(struct file *file, char __user *buf, | |||
1255 | 1463 | ||
1256 | static const struct file_operations sel_initcon_ops = { | 1464 | static const struct file_operations sel_initcon_ops = { |
1257 | .read = sel_read_initcon, | 1465 | .read = sel_read_initcon, |
1466 | .llseek = generic_file_llseek, | ||
1258 | }; | 1467 | }; |
1259 | 1468 | ||
1260 | static int sel_make_initcon_files(struct dentry *dir) | 1469 | static int sel_make_initcon_files(struct dentry *dir) |
1261 | { | 1470 | { |
1262 | int i, ret = 0; | 1471 | int i; |
1263 | 1472 | ||
1264 | for (i = 1; i <= SECINITSID_NUM; i++) { | 1473 | for (i = 1; i <= SECINITSID_NUM; i++) { |
1265 | struct inode *inode; | 1474 | struct inode *inode; |
1266 | struct dentry *dentry; | 1475 | struct dentry *dentry; |
1267 | dentry = d_alloc_name(dir, security_get_initial_sid_context(i)); | 1476 | dentry = d_alloc_name(dir, security_get_initial_sid_context(i)); |
1268 | if (!dentry) { | 1477 | if (!dentry) |
1269 | ret = -ENOMEM; | 1478 | return -ENOMEM; |
1270 | goto out; | ||
1271 | } | ||
1272 | 1479 | ||
1273 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1480 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1274 | if (!inode) { | 1481 | if (!inode) |
1275 | ret = -ENOMEM; | 1482 | return -ENOMEM; |
1276 | goto out; | 1483 | |
1277 | } | ||
1278 | inode->i_fop = &sel_initcon_ops; | 1484 | inode->i_fop = &sel_initcon_ops; |
1279 | inode->i_ino = i|SEL_INITCON_INO_OFFSET; | 1485 | inode->i_ino = i|SEL_INITCON_INO_OFFSET; |
1280 | d_add(dentry, inode); | 1486 | d_add(dentry, inode); |
1281 | } | 1487 | } |
1282 | out: | 1488 | |
1283 | return ret; | 1489 | return 0; |
1284 | } | 1490 | } |
1285 | 1491 | ||
1286 | static inline unsigned int sel_div(unsigned long a, unsigned long b) | 1492 | static inline unsigned int sel_div(unsigned long a, unsigned long b) |
@@ -1316,20 +1522,19 @@ static ssize_t sel_read_class(struct file *file, char __user *buf, | |||
1316 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1522 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1317 | 1523 | ||
1318 | page = (char *)__get_free_page(GFP_KERNEL); | 1524 | page = (char *)__get_free_page(GFP_KERNEL); |
1319 | if (!page) { | 1525 | if (!page) |
1320 | rc = -ENOMEM; | 1526 | return -ENOMEM; |
1321 | goto out; | ||
1322 | } | ||
1323 | 1527 | ||
1324 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); | 1528 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); |
1325 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | 1529 | rc = simple_read_from_buffer(buf, count, ppos, page, len); |
1326 | free_page((unsigned long)page); | 1530 | free_page((unsigned long)page); |
1327 | out: | 1531 | |
1328 | return rc; | 1532 | return rc; |
1329 | } | 1533 | } |
1330 | 1534 | ||
1331 | static const struct file_operations sel_class_ops = { | 1535 | static const struct file_operations sel_class_ops = { |
1332 | .read = sel_read_class, | 1536 | .read = sel_read_class, |
1537 | .llseek = generic_file_llseek, | ||
1333 | }; | 1538 | }; |
1334 | 1539 | ||
1335 | static ssize_t sel_read_perm(struct file *file, char __user *buf, | 1540 | static ssize_t sel_read_perm(struct file *file, char __user *buf, |
@@ -1340,20 +1545,19 @@ static ssize_t sel_read_perm(struct file *file, char __user *buf, | |||
1340 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1545 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1341 | 1546 | ||
1342 | page = (char *)__get_free_page(GFP_KERNEL); | 1547 | page = (char *)__get_free_page(GFP_KERNEL); |
1343 | if (!page) { | 1548 | if (!page) |
1344 | rc = -ENOMEM; | 1549 | return -ENOMEM; |
1345 | goto out; | ||
1346 | } | ||
1347 | 1550 | ||
1348 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); | 1551 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); |
1349 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | 1552 | rc = simple_read_from_buffer(buf, count, ppos, page, len); |
1350 | free_page((unsigned long)page); | 1553 | free_page((unsigned long)page); |
1351 | out: | 1554 | |
1352 | return rc; | 1555 | return rc; |
1353 | } | 1556 | } |
1354 | 1557 | ||
1355 | static const struct file_operations sel_perm_ops = { | 1558 | static const struct file_operations sel_perm_ops = { |
1356 | .read = sel_read_perm, | 1559 | .read = sel_read_perm, |
1560 | .llseek = generic_file_llseek, | ||
1357 | }; | 1561 | }; |
1358 | 1562 | ||
1359 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, | 1563 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, |
@@ -1372,44 +1576,43 @@ static ssize_t sel_read_policycap(struct file *file, char __user *buf, | |||
1372 | 1576 | ||
1373 | static const struct file_operations sel_policycap_ops = { | 1577 | static const struct file_operations sel_policycap_ops = { |
1374 | .read = sel_read_policycap, | 1578 | .read = sel_read_policycap, |
1579 | .llseek = generic_file_llseek, | ||
1375 | }; | 1580 | }; |
1376 | 1581 | ||
1377 | static int sel_make_perm_files(char *objclass, int classvalue, | 1582 | static int sel_make_perm_files(char *objclass, int classvalue, |
1378 | struct dentry *dir) | 1583 | struct dentry *dir) |
1379 | { | 1584 | { |
1380 | int i, rc = 0, nperms; | 1585 | int i, rc, nperms; |
1381 | char **perms; | 1586 | char **perms; |
1382 | 1587 | ||
1383 | rc = security_get_permissions(objclass, &perms, &nperms); | 1588 | rc = security_get_permissions(objclass, &perms, &nperms); |
1384 | if (rc) | 1589 | if (rc) |
1385 | goto out; | 1590 | return rc; |
1386 | 1591 | ||
1387 | for (i = 0; i < nperms; i++) { | 1592 | for (i = 0; i < nperms; i++) { |
1388 | struct inode *inode; | 1593 | struct inode *inode; |
1389 | struct dentry *dentry; | 1594 | struct dentry *dentry; |
1390 | 1595 | ||
1596 | rc = -ENOMEM; | ||
1391 | dentry = d_alloc_name(dir, perms[i]); | 1597 | dentry = d_alloc_name(dir, perms[i]); |
1392 | if (!dentry) { | 1598 | if (!dentry) |
1393 | rc = -ENOMEM; | 1599 | goto out; |
1394 | goto out1; | ||
1395 | } | ||
1396 | 1600 | ||
1601 | rc = -ENOMEM; | ||
1397 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1602 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1398 | if (!inode) { | 1603 | if (!inode) |
1399 | rc = -ENOMEM; | 1604 | goto out; |
1400 | goto out1; | 1605 | |
1401 | } | ||
1402 | inode->i_fop = &sel_perm_ops; | 1606 | inode->i_fop = &sel_perm_ops; |
1403 | /* i+1 since perm values are 1-indexed */ | 1607 | /* i+1 since perm values are 1-indexed */ |
1404 | inode->i_ino = sel_perm_to_ino(classvalue, i+1); | 1608 | inode->i_ino = sel_perm_to_ino(classvalue, i + 1); |
1405 | d_add(dentry, inode); | 1609 | d_add(dentry, inode); |
1406 | } | 1610 | } |
1407 | 1611 | rc = 0; | |
1408 | out1: | 1612 | out: |
1409 | for (i = 0; i < nperms; i++) | 1613 | for (i = 0; i < nperms; i++) |
1410 | kfree(perms[i]); | 1614 | kfree(perms[i]); |
1411 | kfree(perms); | 1615 | kfree(perms); |
1412 | out: | ||
1413 | return rc; | 1616 | return rc; |
1414 | } | 1617 | } |
1415 | 1618 | ||
@@ -1421,34 +1624,27 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
1421 | int rc; | 1624 | int rc; |
1422 | 1625 | ||
1423 | dentry = d_alloc_name(dir, "index"); | 1626 | dentry = d_alloc_name(dir, "index"); |
1424 | if (!dentry) { | 1627 | if (!dentry) |
1425 | rc = -ENOMEM; | 1628 | return -ENOMEM; |
1426 | goto out; | ||
1427 | } | ||
1428 | 1629 | ||
1429 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); | 1630 | inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); |
1430 | if (!inode) { | 1631 | if (!inode) |
1431 | rc = -ENOMEM; | 1632 | return -ENOMEM; |
1432 | goto out; | ||
1433 | } | ||
1434 | 1633 | ||
1435 | inode->i_fop = &sel_class_ops; | 1634 | inode->i_fop = &sel_class_ops; |
1436 | inode->i_ino = sel_class_to_ino(index); | 1635 | inode->i_ino = sel_class_to_ino(index); |
1437 | d_add(dentry, inode); | 1636 | d_add(dentry, inode); |
1438 | 1637 | ||
1439 | dentry = d_alloc_name(dir, "perms"); | 1638 | dentry = d_alloc_name(dir, "perms"); |
1440 | if (!dentry) { | 1639 | if (!dentry) |
1441 | rc = -ENOMEM; | 1640 | return -ENOMEM; |
1442 | goto out; | ||
1443 | } | ||
1444 | 1641 | ||
1445 | rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); | 1642 | rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); |
1446 | if (rc) | 1643 | if (rc) |
1447 | goto out; | 1644 | return rc; |
1448 | 1645 | ||
1449 | rc = sel_make_perm_files(classname, index, dentry); | 1646 | rc = sel_make_perm_files(classname, index, dentry); |
1450 | 1647 | ||
1451 | out: | ||
1452 | return rc; | 1648 | return rc; |
1453 | } | 1649 | } |
1454 | 1650 | ||
@@ -1478,45 +1674,43 @@ static void sel_remove_classes(void) | |||
1478 | 1674 | ||
1479 | static int sel_make_classes(void) | 1675 | static int sel_make_classes(void) |
1480 | { | 1676 | { |
1481 | int rc = 0, nclasses, i; | 1677 | int rc, nclasses, i; |
1482 | char **classes; | 1678 | char **classes; |
1483 | 1679 | ||
1484 | /* delete any existing entries */ | 1680 | /* delete any existing entries */ |
1485 | sel_remove_classes(); | 1681 | sel_remove_classes(); |
1486 | 1682 | ||
1487 | rc = security_get_classes(&classes, &nclasses); | 1683 | rc = security_get_classes(&classes, &nclasses); |
1488 | if (rc < 0) | 1684 | if (rc) |
1489 | goto out; | 1685 | return rc; |
1490 | 1686 | ||
1491 | /* +2 since classes are 1-indexed */ | 1687 | /* +2 since classes are 1-indexed */ |
1492 | last_class_ino = sel_class_to_ino(nclasses+2); | 1688 | last_class_ino = sel_class_to_ino(nclasses + 2); |
1493 | 1689 | ||
1494 | for (i = 0; i < nclasses; i++) { | 1690 | for (i = 0; i < nclasses; i++) { |
1495 | struct dentry *class_name_dir; | 1691 | struct dentry *class_name_dir; |
1496 | 1692 | ||
1693 | rc = -ENOMEM; | ||
1497 | class_name_dir = d_alloc_name(class_dir, classes[i]); | 1694 | class_name_dir = d_alloc_name(class_dir, classes[i]); |
1498 | if (!class_name_dir) { | 1695 | if (!class_name_dir) |
1499 | rc = -ENOMEM; | 1696 | goto out; |
1500 | goto out1; | ||
1501 | } | ||
1502 | 1697 | ||
1503 | rc = sel_make_dir(class_dir->d_inode, class_name_dir, | 1698 | rc = sel_make_dir(class_dir->d_inode, class_name_dir, |
1504 | &last_class_ino); | 1699 | &last_class_ino); |
1505 | if (rc) | 1700 | if (rc) |
1506 | goto out1; | 1701 | goto out; |
1507 | 1702 | ||
1508 | /* i+1 since class values are 1-indexed */ | 1703 | /* i+1 since class values are 1-indexed */ |
1509 | rc = sel_make_class_dir_entries(classes[i], i+1, | 1704 | rc = sel_make_class_dir_entries(classes[i], i + 1, |
1510 | class_name_dir); | 1705 | class_name_dir); |
1511 | if (rc) | 1706 | if (rc) |
1512 | goto out1; | 1707 | goto out; |
1513 | } | 1708 | } |
1514 | 1709 | rc = 0; | |
1515 | out1: | 1710 | out: |
1516 | for (i = 0; i < nclasses; i++) | 1711 | for (i = 0; i < nclasses; i++) |
1517 | kfree(classes[i]); | 1712 | kfree(classes[i]); |
1518 | kfree(classes); | 1713 | kfree(classes); |
1519 | out: | ||
1520 | return rc; | 1714 | return rc; |
1521 | } | 1715 | } |
1522 | 1716 | ||
@@ -1553,14 +1747,12 @@ static int sel_make_policycap(void) | |||
1553 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, | 1747 | static int sel_make_dir(struct inode *dir, struct dentry *dentry, |
1554 | unsigned long *ino) | 1748 | unsigned long *ino) |
1555 | { | 1749 | { |
1556 | int ret = 0; | ||
1557 | struct inode *inode; | 1750 | struct inode *inode; |
1558 | 1751 | ||
1559 | inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); | 1752 | inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); |
1560 | if (!inode) { | 1753 | if (!inode) |
1561 | ret = -ENOMEM; | 1754 | return -ENOMEM; |
1562 | goto out; | 1755 | |
1563 | } | ||
1564 | inode->i_op = &simple_dir_inode_operations; | 1756 | inode->i_op = &simple_dir_inode_operations; |
1565 | inode->i_fop = &simple_dir_operations; | 1757 | inode->i_fop = &simple_dir_operations; |
1566 | inode->i_ino = ++(*ino); | 1758 | inode->i_ino = ++(*ino); |
@@ -1569,8 +1761,8 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry, | |||
1569 | d_add(dentry, inode); | 1761 | d_add(dentry, inode); |
1570 | /* bump link count on parent directory, too */ | 1762 | /* bump link count on parent directory, too */ |
1571 | inc_nlink(dir); | 1763 | inc_nlink(dir); |
1572 | out: | 1764 | |
1573 | return ret; | 1765 | return 0; |
1574 | } | 1766 | } |
1575 | 1767 | ||
1576 | static int sel_fill_super(struct super_block *sb, void *data, int silent) | 1768 | static int sel_fill_super(struct super_block *sb, void *data, int silent) |
@@ -1596,6 +1788,8 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1596 | [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR}, | 1788 | [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR}, |
1597 | [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, | 1789 | [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
1598 | [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, | 1790 | [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
1791 | [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, | ||
1792 | [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR}, | ||
1599 | /* last one */ {""} | 1793 | /* last one */ {""} |
1600 | }; | 1794 | }; |
1601 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); | 1795 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |
@@ -1604,11 +1798,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1604 | 1798 | ||
1605 | root_inode = sb->s_root->d_inode; | 1799 | root_inode = sb->s_root->d_inode; |
1606 | 1800 | ||
1801 | ret = -ENOMEM; | ||
1607 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); | 1802 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); |
1608 | if (!dentry) { | 1803 | if (!dentry) |
1609 | ret = -ENOMEM; | ||
1610 | goto err; | 1804 | goto err; |
1611 | } | ||
1612 | 1805 | ||
1613 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1806 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1614 | if (ret) | 1807 | if (ret) |
@@ -1616,17 +1809,16 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1616 | 1809 | ||
1617 | bool_dir = dentry; | 1810 | bool_dir = dentry; |
1618 | 1811 | ||
1812 | ret = -ENOMEM; | ||
1619 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); | 1813 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); |
1620 | if (!dentry) { | 1814 | if (!dentry) |
1621 | ret = -ENOMEM; | ||
1622 | goto err; | 1815 | goto err; |
1623 | } | ||
1624 | 1816 | ||
1817 | ret = -ENOMEM; | ||
1625 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); | 1818 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); |
1626 | if (!inode) { | 1819 | if (!inode) |
1627 | ret = -ENOMEM; | ||
1628 | goto err; | 1820 | goto err; |
1629 | } | 1821 | |
1630 | inode->i_ino = ++sel_last_ino; | 1822 | inode->i_ino = ++sel_last_ino; |
1631 | isec = (struct inode_security_struct *)inode->i_security; | 1823 | isec = (struct inode_security_struct *)inode->i_security; |
1632 | isec->sid = SECINITSID_DEVNULL; | 1824 | isec->sid = SECINITSID_DEVNULL; |
@@ -1637,11 +1829,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1637 | d_add(dentry, inode); | 1829 | d_add(dentry, inode); |
1638 | selinux_null = dentry; | 1830 | selinux_null = dentry; |
1639 | 1831 | ||
1832 | ret = -ENOMEM; | ||
1640 | dentry = d_alloc_name(sb->s_root, "avc"); | 1833 | dentry = d_alloc_name(sb->s_root, "avc"); |
1641 | if (!dentry) { | 1834 | if (!dentry) |
1642 | ret = -ENOMEM; | ||
1643 | goto err; | 1835 | goto err; |
1644 | } | ||
1645 | 1836 | ||
1646 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1837 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1647 | if (ret) | 1838 | if (ret) |
@@ -1651,11 +1842,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1651 | if (ret) | 1842 | if (ret) |
1652 | goto err; | 1843 | goto err; |
1653 | 1844 | ||
1845 | ret = -ENOMEM; | ||
1654 | dentry = d_alloc_name(sb->s_root, "initial_contexts"); | 1846 | dentry = d_alloc_name(sb->s_root, "initial_contexts"); |
1655 | if (!dentry) { | 1847 | if (!dentry) |
1656 | ret = -ENOMEM; | ||
1657 | goto err; | 1848 | goto err; |
1658 | } | ||
1659 | 1849 | ||
1660 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1850 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1661 | if (ret) | 1851 | if (ret) |
@@ -1665,11 +1855,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1665 | if (ret) | 1855 | if (ret) |
1666 | goto err; | 1856 | goto err; |
1667 | 1857 | ||
1858 | ret = -ENOMEM; | ||
1668 | dentry = d_alloc_name(sb->s_root, "class"); | 1859 | dentry = d_alloc_name(sb->s_root, "class"); |
1669 | if (!dentry) { | 1860 | if (!dentry) |
1670 | ret = -ENOMEM; | ||
1671 | goto err; | 1861 | goto err; |
1672 | } | ||
1673 | 1862 | ||
1674 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1863 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1675 | if (ret) | 1864 | if (ret) |
@@ -1677,11 +1866,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1677 | 1866 | ||
1678 | class_dir = dentry; | 1867 | class_dir = dentry; |
1679 | 1868 | ||
1869 | ret = -ENOMEM; | ||
1680 | dentry = d_alloc_name(sb->s_root, "policy_capabilities"); | 1870 | dentry = d_alloc_name(sb->s_root, "policy_capabilities"); |
1681 | if (!dentry) { | 1871 | if (!dentry) |
1682 | ret = -ENOMEM; | ||
1683 | goto err; | 1872 | goto err; |
1684 | } | ||
1685 | 1873 | ||
1686 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); | 1874 | ret = sel_make_dir(root_inode, dentry, &sel_last_ino); |
1687 | if (ret) | 1875 | if (ret) |
@@ -1689,24 +1877,22 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1689 | 1877 | ||
1690 | policycap_dir = dentry; | 1878 | policycap_dir = dentry; |
1691 | 1879 | ||
1692 | out: | 1880 | return 0; |
1693 | return ret; | ||
1694 | err: | 1881 | err: |
1695 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", | 1882 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", |
1696 | __func__); | 1883 | __func__); |
1697 | goto out; | 1884 | return ret; |
1698 | } | 1885 | } |
1699 | 1886 | ||
1700 | static int sel_get_sb(struct file_system_type *fs_type, | 1887 | static struct dentry *sel_mount(struct file_system_type *fs_type, |
1701 | int flags, const char *dev_name, void *data, | 1888 | int flags, const char *dev_name, void *data) |
1702 | struct vfsmount *mnt) | ||
1703 | { | 1889 | { |
1704 | return get_sb_single(fs_type, flags, data, sel_fill_super, mnt); | 1890 | return mount_single(fs_type, flags, data, sel_fill_super); |
1705 | } | 1891 | } |
1706 | 1892 | ||
1707 | static struct file_system_type sel_fs_type = { | 1893 | static struct file_system_type sel_fs_type = { |
1708 | .name = "selinuxfs", | 1894 | .name = "selinuxfs", |
1709 | .get_sb = sel_get_sb, | 1895 | .mount = sel_mount, |
1710 | .kill_sb = kill_litter_super, | 1896 | .kill_sb = kill_litter_super, |
1711 | }; | 1897 | }; |
1712 | 1898 | ||
@@ -1719,14 +1905,16 @@ static int __init init_sel_fs(void) | |||
1719 | if (!selinux_enabled) | 1905 | if (!selinux_enabled) |
1720 | return 0; | 1906 | return 0; |
1721 | err = register_filesystem(&sel_fs_type); | 1907 | err = register_filesystem(&sel_fs_type); |
1722 | if (!err) { | 1908 | if (err) |
1723 | selinuxfs_mount = kern_mount(&sel_fs_type); | 1909 | return err; |
1724 | if (IS_ERR(selinuxfs_mount)) { | 1910 | |
1725 | printk(KERN_ERR "selinuxfs: could not mount!\n"); | 1911 | selinuxfs_mount = kern_mount(&sel_fs_type); |
1726 | err = PTR_ERR(selinuxfs_mount); | 1912 | if (IS_ERR(selinuxfs_mount)) { |
1727 | selinuxfs_mount = NULL; | 1913 | printk(KERN_ERR "selinuxfs: could not mount!\n"); |
1728 | } | 1914 | err = PTR_ERR(selinuxfs_mount); |
1915 | selinuxfs_mount = NULL; | ||
1729 | } | 1916 | } |
1917 | |||
1730 | return err; | 1918 | return err; |
1731 | } | 1919 | } |
1732 | 1920 | ||
diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile deleted file mode 100644 index bad78779b9b..00000000000 --- a/security/selinux/ss/Makefile +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for building the SELinux security server as part of the kernel tree. | ||
3 | # | ||
4 | |||
5 | EXTRA_CFLAGS += -Isecurity/selinux/include | ||
6 | obj-y := ss.o | ||
7 | |||
8 | ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o | ||
9 | |||
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 1215b8e47db..a3dd9faa19c 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
@@ -266,8 +266,8 @@ int avtab_alloc(struct avtab *h, u32 nrules) | |||
266 | if (shift > 2) | 266 | if (shift > 2) |
267 | shift = shift - 2; | 267 | shift = shift - 2; |
268 | nslot = 1 << shift; | 268 | nslot = 1 << shift; |
269 | if (nslot > MAX_AVTAB_SIZE) | 269 | if (nslot > MAX_AVTAB_HASH_BUCKETS) |
270 | nslot = MAX_AVTAB_SIZE; | 270 | nslot = MAX_AVTAB_HASH_BUCKETS; |
271 | mask = nslot - 1; | 271 | mask = nslot - 1; |
272 | 272 | ||
273 | h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL); | 273 | h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL); |
@@ -342,20 +342,20 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
342 | 342 | ||
343 | if (vers < POLICYDB_VERSION_AVTAB) { | 343 | if (vers < POLICYDB_VERSION_AVTAB) { |
344 | rc = next_entry(buf32, fp, sizeof(u32)); | 344 | rc = next_entry(buf32, fp, sizeof(u32)); |
345 | if (rc < 0) { | 345 | if (rc) { |
346 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 346 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
347 | return -1; | 347 | return rc; |
348 | } | 348 | } |
349 | items2 = le32_to_cpu(buf32[0]); | 349 | items2 = le32_to_cpu(buf32[0]); |
350 | if (items2 > ARRAY_SIZE(buf32)) { | 350 | if (items2 > ARRAY_SIZE(buf32)) { |
351 | printk(KERN_ERR "SELinux: avtab: entry overflow\n"); | 351 | printk(KERN_ERR "SELinux: avtab: entry overflow\n"); |
352 | return -1; | 352 | return -EINVAL; |
353 | 353 | ||
354 | } | 354 | } |
355 | rc = next_entry(buf32, fp, sizeof(u32)*items2); | 355 | rc = next_entry(buf32, fp, sizeof(u32)*items2); |
356 | if (rc < 0) { | 356 | if (rc) { |
357 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 357 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
358 | return -1; | 358 | return rc; |
359 | } | 359 | } |
360 | items = 0; | 360 | items = 0; |
361 | 361 | ||
@@ -363,19 +363,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
363 | key.source_type = (u16)val; | 363 | key.source_type = (u16)val; |
364 | if (key.source_type != val) { | 364 | if (key.source_type != val) { |
365 | printk(KERN_ERR "SELinux: avtab: truncated source type\n"); | 365 | printk(KERN_ERR "SELinux: avtab: truncated source type\n"); |
366 | return -1; | 366 | return -EINVAL; |
367 | } | 367 | } |
368 | val = le32_to_cpu(buf32[items++]); | 368 | val = le32_to_cpu(buf32[items++]); |
369 | key.target_type = (u16)val; | 369 | key.target_type = (u16)val; |
370 | if (key.target_type != val) { | 370 | if (key.target_type != val) { |
371 | printk(KERN_ERR "SELinux: avtab: truncated target type\n"); | 371 | printk(KERN_ERR "SELinux: avtab: truncated target type\n"); |
372 | return -1; | 372 | return -EINVAL; |
373 | } | 373 | } |
374 | val = le32_to_cpu(buf32[items++]); | 374 | val = le32_to_cpu(buf32[items++]); |
375 | key.target_class = (u16)val; | 375 | key.target_class = (u16)val; |
376 | if (key.target_class != val) { | 376 | if (key.target_class != val) { |
377 | printk(KERN_ERR "SELinux: avtab: truncated target class\n"); | 377 | printk(KERN_ERR "SELinux: avtab: truncated target class\n"); |
378 | return -1; | 378 | return -EINVAL; |
379 | } | 379 | } |
380 | 380 | ||
381 | val = le32_to_cpu(buf32[items++]); | 381 | val = le32_to_cpu(buf32[items++]); |
@@ -383,12 +383,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
383 | 383 | ||
384 | if (!(val & (AVTAB_AV | AVTAB_TYPE))) { | 384 | if (!(val & (AVTAB_AV | AVTAB_TYPE))) { |
385 | printk(KERN_ERR "SELinux: avtab: null entry\n"); | 385 | printk(KERN_ERR "SELinux: avtab: null entry\n"); |
386 | return -1; | 386 | return -EINVAL; |
387 | } | 387 | } |
388 | if ((val & AVTAB_AV) && | 388 | if ((val & AVTAB_AV) && |
389 | (val & AVTAB_TYPE)) { | 389 | (val & AVTAB_TYPE)) { |
390 | printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); | 390 | printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); |
391 | return -1; | 391 | return -EINVAL; |
392 | } | 392 | } |
393 | 393 | ||
394 | for (i = 0; i < ARRAY_SIZE(spec_order); i++) { | 394 | for (i = 0; i < ARRAY_SIZE(spec_order); i++) { |
@@ -403,15 +403,15 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
403 | 403 | ||
404 | if (items != items2) { | 404 | if (items != items2) { |
405 | printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); | 405 | printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); |
406 | return -1; | 406 | return -EINVAL; |
407 | } | 407 | } |
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | rc = next_entry(buf16, fp, sizeof(u16)*4); | 411 | rc = next_entry(buf16, fp, sizeof(u16)*4); |
412 | if (rc < 0) { | 412 | if (rc) { |
413 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 413 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
414 | return -1; | 414 | return rc; |
415 | } | 415 | } |
416 | 416 | ||
417 | items = 0; | 417 | items = 0; |
@@ -424,7 +424,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
424 | !policydb_type_isvalid(pol, key.target_type) || | 424 | !policydb_type_isvalid(pol, key.target_type) || |
425 | !policydb_class_isvalid(pol, key.target_class)) { | 425 | !policydb_class_isvalid(pol, key.target_class)) { |
426 | printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); | 426 | printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); |
427 | return -1; | 427 | return -EINVAL; |
428 | } | 428 | } |
429 | 429 | ||
430 | set = 0; | 430 | set = 0; |
@@ -434,19 +434,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
434 | } | 434 | } |
435 | if (!set || set > 1) { | 435 | if (!set || set > 1) { |
436 | printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); | 436 | printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); |
437 | return -1; | 437 | return -EINVAL; |
438 | } | 438 | } |
439 | 439 | ||
440 | rc = next_entry(buf32, fp, sizeof(u32)); | 440 | rc = next_entry(buf32, fp, sizeof(u32)); |
441 | if (rc < 0) { | 441 | if (rc) { |
442 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); | 442 | printk(KERN_ERR "SELinux: avtab: truncated entry\n"); |
443 | return -1; | 443 | return rc; |
444 | } | 444 | } |
445 | datum.data = le32_to_cpu(*buf32); | 445 | datum.data = le32_to_cpu(*buf32); |
446 | if ((key.specified & AVTAB_TYPE) && | 446 | if ((key.specified & AVTAB_TYPE) && |
447 | !policydb_type_isvalid(pol, datum.data)) { | 447 | !policydb_type_isvalid(pol, datum.data)) { |
448 | printk(KERN_ERR "SELinux: avtab: invalid type\n"); | 448 | printk(KERN_ERR "SELinux: avtab: invalid type\n"); |
449 | return -1; | 449 | return -EINVAL; |
450 | } | 450 | } |
451 | return insertf(a, &key, &datum, p); | 451 | return insertf(a, &key, &datum, p); |
452 | } | 452 | } |
@@ -487,8 +487,7 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) | |||
487 | printk(KERN_ERR "SELinux: avtab: out of memory\n"); | 487 | printk(KERN_ERR "SELinux: avtab: out of memory\n"); |
488 | else if (rc == -EEXIST) | 488 | else if (rc == -EEXIST) |
489 | printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); | 489 | printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); |
490 | else | 490 | |
491 | rc = -EINVAL; | ||
492 | goto bad; | 491 | goto bad; |
493 | } | 492 | } |
494 | } | 493 | } |
@@ -502,6 +501,48 @@ bad: | |||
502 | goto out; | 501 | goto out; |
503 | } | 502 | } |
504 | 503 | ||
504 | int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp) | ||
505 | { | ||
506 | __le16 buf16[4]; | ||
507 | __le32 buf32[1]; | ||
508 | int rc; | ||
509 | |||
510 | buf16[0] = cpu_to_le16(cur->key.source_type); | ||
511 | buf16[1] = cpu_to_le16(cur->key.target_type); | ||
512 | buf16[2] = cpu_to_le16(cur->key.target_class); | ||
513 | buf16[3] = cpu_to_le16(cur->key.specified); | ||
514 | rc = put_entry(buf16, sizeof(u16), 4, fp); | ||
515 | if (rc) | ||
516 | return rc; | ||
517 | buf32[0] = cpu_to_le32(cur->datum.data); | ||
518 | rc = put_entry(buf32, sizeof(u32), 1, fp); | ||
519 | if (rc) | ||
520 | return rc; | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | int avtab_write(struct policydb *p, struct avtab *a, void *fp) | ||
525 | { | ||
526 | unsigned int i; | ||
527 | int rc = 0; | ||
528 | struct avtab_node *cur; | ||
529 | __le32 buf[1]; | ||
530 | |||
531 | buf[0] = cpu_to_le32(a->nel); | ||
532 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
533 | if (rc) | ||
534 | return rc; | ||
535 | |||
536 | for (i = 0; i < a->nslot; i++) { | ||
537 | for (cur = a->htable[i]; cur; cur = cur->next) { | ||
538 | rc = avtab_write_item(p, cur, fp); | ||
539 | if (rc) | ||
540 | return rc; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | return rc; | ||
545 | } | ||
505 | void avtab_cache_init(void) | 546 | void avtab_cache_init(void) |
506 | { | 547 | { |
507 | avtab_node_cachep = kmem_cache_create("avtab_node", | 548 | avtab_node_cachep = kmem_cache_create("avtab_node", |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 8da6a842808..dff0c75345c 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -71,6 +71,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, | |||
71 | void *p); | 71 | void *p); |
72 | 72 | ||
73 | int avtab_read(struct avtab *a, void *fp, struct policydb *pol); | 73 | int avtab_read(struct avtab *a, void *fp, struct policydb *pol); |
74 | int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp); | ||
75 | int avtab_write(struct policydb *p, struct avtab *a, void *fp); | ||
74 | 76 | ||
75 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, | 77 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, |
76 | struct avtab_datum *datum); | 78 | struct avtab_datum *datum); |
@@ -82,10 +84,9 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified | |||
82 | void avtab_cache_init(void); | 84 | void avtab_cache_init(void); |
83 | void avtab_cache_destroy(void); | 85 | void avtab_cache_destroy(void); |
84 | 86 | ||
85 | #define MAX_AVTAB_HASH_BITS 13 | 87 | #define MAX_AVTAB_HASH_BITS 11 |
86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 88 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) | 89 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) |
88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS | ||
89 | 90 | ||
90 | #endif /* _SS_AVTAB_H_ */ | 91 | #endif /* _SS_AVTAB_H_ */ |
91 | 92 | ||
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 4a4e35cac22..c3f845cbcd4 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c | |||
@@ -117,10 +117,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) | |||
117 | 117 | ||
118 | int cond_policydb_init(struct policydb *p) | 118 | int cond_policydb_init(struct policydb *p) |
119 | { | 119 | { |
120 | int rc; | ||
121 | |||
120 | p->bool_val_to_struct = NULL; | 122 | p->bool_val_to_struct = NULL; |
121 | p->cond_list = NULL; | 123 | p->cond_list = NULL; |
122 | if (avtab_init(&p->te_cond_avtab)) | 124 | |
123 | return -1; | 125 | rc = avtab_init(&p->te_cond_avtab); |
126 | if (rc) | ||
127 | return rc; | ||
124 | 128 | ||
125 | return 0; | 129 | return 0; |
126 | } | 130 | } |
@@ -189,6 +193,7 @@ int cond_index_bool(void *key, void *datum, void *datap) | |||
189 | { | 193 | { |
190 | struct policydb *p; | 194 | struct policydb *p; |
191 | struct cond_bool_datum *booldatum; | 195 | struct cond_bool_datum *booldatum; |
196 | struct flex_array *fa; | ||
192 | 197 | ||
193 | booldatum = datum; | 198 | booldatum = datum; |
194 | p = datap; | 199 | p = datap; |
@@ -196,7 +201,10 @@ int cond_index_bool(void *key, void *datum, void *datap) | |||
196 | if (!booldatum->value || booldatum->value > p->p_bools.nprim) | 201 | if (!booldatum->value || booldatum->value > p->p_bools.nprim) |
197 | return -EINVAL; | 202 | return -EINVAL; |
198 | 203 | ||
199 | p->p_bool_val_to_name[booldatum->value - 1] = key; | 204 | fa = p->sym_val_to_name[SYM_BOOLS]; |
205 | if (flex_array_put_ptr(fa, booldatum->value - 1, key, | ||
206 | GFP_KERNEL | __GFP_ZERO)) | ||
207 | BUG(); | ||
200 | p->bool_val_to_struct[booldatum->value - 1] = booldatum; | 208 | p->bool_val_to_struct[booldatum->value - 1] = booldatum; |
201 | 209 | ||
202 | return 0; | 210 | return 0; |
@@ -219,34 +227,37 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
219 | 227 | ||
220 | booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); | 228 | booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); |
221 | if (!booldatum) | 229 | if (!booldatum) |
222 | return -1; | 230 | return -ENOMEM; |
223 | 231 | ||
224 | rc = next_entry(buf, fp, sizeof buf); | 232 | rc = next_entry(buf, fp, sizeof buf); |
225 | if (rc < 0) | 233 | if (rc) |
226 | goto err; | 234 | goto err; |
227 | 235 | ||
228 | booldatum->value = le32_to_cpu(buf[0]); | 236 | booldatum->value = le32_to_cpu(buf[0]); |
229 | booldatum->state = le32_to_cpu(buf[1]); | 237 | booldatum->state = le32_to_cpu(buf[1]); |
230 | 238 | ||
239 | rc = -EINVAL; | ||
231 | if (!bool_isvalid(booldatum)) | 240 | if (!bool_isvalid(booldatum)) |
232 | goto err; | 241 | goto err; |
233 | 242 | ||
234 | len = le32_to_cpu(buf[2]); | 243 | len = le32_to_cpu(buf[2]); |
235 | 244 | ||
245 | rc = -ENOMEM; | ||
236 | key = kmalloc(len + 1, GFP_KERNEL); | 246 | key = kmalloc(len + 1, GFP_KERNEL); |
237 | if (!key) | 247 | if (!key) |
238 | goto err; | 248 | goto err; |
239 | rc = next_entry(key, fp, len); | 249 | rc = next_entry(key, fp, len); |
240 | if (rc < 0) | 250 | if (rc) |
241 | goto err; | 251 | goto err; |
242 | key[len] = '\0'; | 252 | key[len] = '\0'; |
243 | if (hashtab_insert(h, key, booldatum)) | 253 | rc = hashtab_insert(h, key, booldatum); |
254 | if (rc) | ||
244 | goto err; | 255 | goto err; |
245 | 256 | ||
246 | return 0; | 257 | return 0; |
247 | err: | 258 | err: |
248 | cond_destroy_bool(key, booldatum, NULL); | 259 | cond_destroy_bool(key, booldatum, NULL); |
249 | return -1; | 260 | return rc; |
250 | } | 261 | } |
251 | 262 | ||
252 | struct cond_insertf_data { | 263 | struct cond_insertf_data { |
@@ -263,7 +274,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
263 | struct cond_av_list *other = data->other, *list, *cur; | 274 | struct cond_av_list *other = data->other, *list, *cur; |
264 | struct avtab_node *node_ptr; | 275 | struct avtab_node *node_ptr; |
265 | u8 found; | 276 | u8 found; |
266 | 277 | int rc = -EINVAL; | |
267 | 278 | ||
268 | /* | 279 | /* |
269 | * For type rules we have to make certain there aren't any | 280 | * For type rules we have to make certain there aren't any |
@@ -313,12 +324,15 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
313 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); | 324 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); |
314 | if (!node_ptr) { | 325 | if (!node_ptr) { |
315 | printk(KERN_ERR "SELinux: could not insert rule.\n"); | 326 | printk(KERN_ERR "SELinux: could not insert rule.\n"); |
327 | rc = -ENOMEM; | ||
316 | goto err; | 328 | goto err; |
317 | } | 329 | } |
318 | 330 | ||
319 | list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); | 331 | list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); |
320 | if (!list) | 332 | if (!list) { |
333 | rc = -ENOMEM; | ||
321 | goto err; | 334 | goto err; |
335 | } | ||
322 | 336 | ||
323 | list->node = node_ptr; | 337 | list->node = node_ptr; |
324 | if (!data->head) | 338 | if (!data->head) |
@@ -331,7 +345,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum | |||
331 | err: | 345 | err: |
332 | cond_av_list_destroy(data->head); | 346 | cond_av_list_destroy(data->head); |
333 | data->head = NULL; | 347 | data->head = NULL; |
334 | return -1; | 348 | return rc; |
335 | } | 349 | } |
336 | 350 | ||
337 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) | 351 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) |
@@ -345,8 +359,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * | |||
345 | 359 | ||
346 | len = 0; | 360 | len = 0; |
347 | rc = next_entry(buf, fp, sizeof(u32)); | 361 | rc = next_entry(buf, fp, sizeof(u32)); |
348 | if (rc < 0) | 362 | if (rc) |
349 | return -1; | 363 | return rc; |
350 | 364 | ||
351 | len = le32_to_cpu(buf[0]); | 365 | len = le32_to_cpu(buf[0]); |
352 | if (len == 0) | 366 | if (len == 0) |
@@ -361,7 +375,6 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * | |||
361 | &data); | 375 | &data); |
362 | if (rc) | 376 | if (rc) |
363 | return rc; | 377 | return rc; |
364 | |||
365 | } | 378 | } |
366 | 379 | ||
367 | *ret_list = data.head; | 380 | *ret_list = data.head; |
@@ -390,24 +403,25 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | |||
390 | struct cond_expr *expr = NULL, *last = NULL; | 403 | struct cond_expr *expr = NULL, *last = NULL; |
391 | 404 | ||
392 | rc = next_entry(buf, fp, sizeof(u32)); | 405 | rc = next_entry(buf, fp, sizeof(u32)); |
393 | if (rc < 0) | 406 | if (rc) |
394 | return -1; | 407 | return rc; |
395 | 408 | ||
396 | node->cur_state = le32_to_cpu(buf[0]); | 409 | node->cur_state = le32_to_cpu(buf[0]); |
397 | 410 | ||
398 | len = 0; | 411 | len = 0; |
399 | rc = next_entry(buf, fp, sizeof(u32)); | 412 | rc = next_entry(buf, fp, sizeof(u32)); |
400 | if (rc < 0) | 413 | if (rc) |
401 | return -1; | 414 | return rc; |
402 | 415 | ||
403 | /* expr */ | 416 | /* expr */ |
404 | len = le32_to_cpu(buf[0]); | 417 | len = le32_to_cpu(buf[0]); |
405 | 418 | ||
406 | for (i = 0; i < len; i++) { | 419 | for (i = 0; i < len; i++) { |
407 | rc = next_entry(buf, fp, sizeof(u32) * 2); | 420 | rc = next_entry(buf, fp, sizeof(u32) * 2); |
408 | if (rc < 0) | 421 | if (rc) |
409 | goto err; | 422 | goto err; |
410 | 423 | ||
424 | rc = -ENOMEM; | ||
411 | expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); | 425 | expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); |
412 | if (!expr) | 426 | if (!expr) |
413 | goto err; | 427 | goto err; |
@@ -416,6 +430,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | |||
416 | expr->bool = le32_to_cpu(buf[1]); | 430 | expr->bool = le32_to_cpu(buf[1]); |
417 | 431 | ||
418 | if (!expr_isvalid(p, expr)) { | 432 | if (!expr_isvalid(p, expr)) { |
433 | rc = -EINVAL; | ||
419 | kfree(expr); | 434 | kfree(expr); |
420 | goto err; | 435 | goto err; |
421 | } | 436 | } |
@@ -427,14 +442,16 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | |||
427 | last = expr; | 442 | last = expr; |
428 | } | 443 | } |
429 | 444 | ||
430 | if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) | 445 | rc = cond_read_av_list(p, fp, &node->true_list, NULL); |
446 | if (rc) | ||
431 | goto err; | 447 | goto err; |
432 | if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0) | 448 | rc = cond_read_av_list(p, fp, &node->false_list, node->true_list); |
449 | if (rc) | ||
433 | goto err; | 450 | goto err; |
434 | return 0; | 451 | return 0; |
435 | err: | 452 | err: |
436 | cond_node_destroy(node); | 453 | cond_node_destroy(node); |
437 | return -1; | 454 | return rc; |
438 | } | 455 | } |
439 | 456 | ||
440 | int cond_read_list(struct policydb *p, void *fp) | 457 | int cond_read_list(struct policydb *p, void *fp) |
@@ -445,8 +462,8 @@ int cond_read_list(struct policydb *p, void *fp) | |||
445 | int rc; | 462 | int rc; |
446 | 463 | ||
447 | rc = next_entry(buf, fp, sizeof buf); | 464 | rc = next_entry(buf, fp, sizeof buf); |
448 | if (rc < 0) | 465 | if (rc) |
449 | return -1; | 466 | return rc; |
450 | 467 | ||
451 | len = le32_to_cpu(buf[0]); | 468 | len = le32_to_cpu(buf[0]); |
452 | 469 | ||
@@ -455,11 +472,13 @@ int cond_read_list(struct policydb *p, void *fp) | |||
455 | goto err; | 472 | goto err; |
456 | 473 | ||
457 | for (i = 0; i < len; i++) { | 474 | for (i = 0; i < len; i++) { |
475 | rc = -ENOMEM; | ||
458 | node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); | 476 | node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); |
459 | if (!node) | 477 | if (!node) |
460 | goto err; | 478 | goto err; |
461 | 479 | ||
462 | if (cond_read_node(p, node, fp) != 0) | 480 | rc = cond_read_node(p, node, fp); |
481 | if (rc) | ||
463 | goto err; | 482 | goto err; |
464 | 483 | ||
465 | if (i == 0) | 484 | if (i == 0) |
@@ -472,9 +491,132 @@ int cond_read_list(struct policydb *p, void *fp) | |||
472 | err: | 491 | err: |
473 | cond_list_destroy(p->cond_list); | 492 | cond_list_destroy(p->cond_list); |
474 | p->cond_list = NULL; | 493 | p->cond_list = NULL; |
475 | return -1; | 494 | return rc; |
495 | } | ||
496 | |||
497 | int cond_write_bool(void *vkey, void *datum, void *ptr) | ||
498 | { | ||
499 | char *key = vkey; | ||
500 | struct cond_bool_datum *booldatum = datum; | ||
501 | struct policy_data *pd = ptr; | ||
502 | void *fp = pd->fp; | ||
503 | __le32 buf[3]; | ||
504 | u32 len; | ||
505 | int rc; | ||
506 | |||
507 | len = strlen(key); | ||
508 | buf[0] = cpu_to_le32(booldatum->value); | ||
509 | buf[1] = cpu_to_le32(booldatum->state); | ||
510 | buf[2] = cpu_to_le32(len); | ||
511 | rc = put_entry(buf, sizeof(u32), 3, fp); | ||
512 | if (rc) | ||
513 | return rc; | ||
514 | rc = put_entry(key, 1, len, fp); | ||
515 | if (rc) | ||
516 | return rc; | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * cond_write_cond_av_list doesn't write out the av_list nodes. | ||
522 | * Instead it writes out the key/value pairs from the avtab. This | ||
523 | * is necessary because there is no way to uniquely identifying rules | ||
524 | * in the avtab so it is not possible to associate individual rules | ||
525 | * in the avtab with a conditional without saving them as part of | ||
526 | * the conditional. This means that the avtab with the conditional | ||
527 | * rules will not be saved but will be rebuilt on policy load. | ||
528 | */ | ||
529 | static int cond_write_av_list(struct policydb *p, | ||
530 | struct cond_av_list *list, struct policy_file *fp) | ||
531 | { | ||
532 | __le32 buf[1]; | ||
533 | struct cond_av_list *cur_list; | ||
534 | u32 len; | ||
535 | int rc; | ||
536 | |||
537 | len = 0; | ||
538 | for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) | ||
539 | len++; | ||
540 | |||
541 | buf[0] = cpu_to_le32(len); | ||
542 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
543 | if (rc) | ||
544 | return rc; | ||
545 | |||
546 | if (len == 0) | ||
547 | return 0; | ||
548 | |||
549 | for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { | ||
550 | rc = avtab_write_item(p, cur_list->node, fp); | ||
551 | if (rc) | ||
552 | return rc; | ||
553 | } | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | int cond_write_node(struct policydb *p, struct cond_node *node, | ||
559 | struct policy_file *fp) | ||
560 | { | ||
561 | struct cond_expr *cur_expr; | ||
562 | __le32 buf[2]; | ||
563 | int rc; | ||
564 | u32 len = 0; | ||
565 | |||
566 | buf[0] = cpu_to_le32(node->cur_state); | ||
567 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
568 | if (rc) | ||
569 | return rc; | ||
570 | |||
571 | for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) | ||
572 | len++; | ||
573 | |||
574 | buf[0] = cpu_to_le32(len); | ||
575 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
576 | if (rc) | ||
577 | return rc; | ||
578 | |||
579 | for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { | ||
580 | buf[0] = cpu_to_le32(cur_expr->expr_type); | ||
581 | buf[1] = cpu_to_le32(cur_expr->bool); | ||
582 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
583 | if (rc) | ||
584 | return rc; | ||
585 | } | ||
586 | |||
587 | rc = cond_write_av_list(p, node->true_list, fp); | ||
588 | if (rc) | ||
589 | return rc; | ||
590 | rc = cond_write_av_list(p, node->false_list, fp); | ||
591 | if (rc) | ||
592 | return rc; | ||
593 | |||
594 | return 0; | ||
476 | } | 595 | } |
477 | 596 | ||
597 | int cond_write_list(struct policydb *p, struct cond_node *list, void *fp) | ||
598 | { | ||
599 | struct cond_node *cur; | ||
600 | u32 len; | ||
601 | __le32 buf[1]; | ||
602 | int rc; | ||
603 | |||
604 | len = 0; | ||
605 | for (cur = list; cur != NULL; cur = cur->next) | ||
606 | len++; | ||
607 | buf[0] = cpu_to_le32(len); | ||
608 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
609 | if (rc) | ||
610 | return rc; | ||
611 | |||
612 | for (cur = list; cur != NULL; cur = cur->next) { | ||
613 | rc = cond_write_node(p, cur, fp); | ||
614 | if (rc) | ||
615 | return rc; | ||
616 | } | ||
617 | |||
618 | return 0; | ||
619 | } | ||
478 | /* Determine whether additional permissions are granted by the conditional | 620 | /* Determine whether additional permissions are granted by the conditional |
479 | * av table, and if so, add them to the result | 621 | * av table, and if so, add them to the result |
480 | */ | 622 | */ |
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h index 53ddb013ae5..3f209c63529 100644 --- a/security/selinux/ss/conditional.h +++ b/security/selinux/ss/conditional.h | |||
@@ -69,6 +69,8 @@ int cond_index_bool(void *key, void *datum, void *datap); | |||
69 | 69 | ||
70 | int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp); | 70 | int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp); |
71 | int cond_read_list(struct policydb *p, void *fp); | 71 | int cond_read_list(struct policydb *p, void *fp); |
72 | int cond_write_bool(void *key, void *datum, void *ptr); | ||
73 | int cond_write_list(struct policydb *p, struct cond_node *list, void *fp); | ||
72 | 74 | ||
73 | void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd); | 75 | void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd); |
74 | 76 | ||
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index d9dd7a2f6a8..45e8fb0515f 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
@@ -41,9 +41,6 @@ static inline int mls_context_cpy(struct context *dst, struct context *src) | |||
41 | { | 41 | { |
42 | int rc; | 42 | int rc; |
43 | 43 | ||
44 | if (!selinux_mls_enabled) | ||
45 | return 0; | ||
46 | |||
47 | dst->range.level[0].sens = src->range.level[0].sens; | 44 | dst->range.level[0].sens = src->range.level[0].sens; |
48 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 45 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
49 | if (rc) | 46 | if (rc) |
@@ -64,9 +61,6 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src) | |||
64 | { | 61 | { |
65 | int rc; | 62 | int rc; |
66 | 63 | ||
67 | if (!selinux_mls_enabled) | ||
68 | return 0; | ||
69 | |||
70 | dst->range.level[0].sens = src->range.level[0].sens; | 64 | dst->range.level[0].sens = src->range.level[0].sens; |
71 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 65 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
72 | if (rc) | 66 | if (rc) |
@@ -82,9 +76,6 @@ out: | |||
82 | 76 | ||
83 | static inline int mls_context_cmp(struct context *c1, struct context *c2) | 77 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
84 | { | 78 | { |
85 | if (!selinux_mls_enabled) | ||
86 | return 1; | ||
87 | |||
88 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && | 79 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
89 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && | 80 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && |
90 | (c1->range.level[1].sens == c2->range.level[1].sens) && | 81 | (c1->range.level[1].sens == c2->range.level[1].sens) && |
@@ -93,9 +84,6 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2) | |||
93 | 84 | ||
94 | static inline void mls_context_destroy(struct context *c) | 85 | static inline void mls_context_destroy(struct context *c) |
95 | { | 86 | { |
96 | if (!selinux_mls_enabled) | ||
97 | return; | ||
98 | |||
99 | ebitmap_destroy(&c->range.level[0].cat); | 87 | ebitmap_destroy(&c->range.level[0].cat); |
100 | ebitmap_destroy(&c->range.level[1].cat); | 88 | ebitmap_destroy(&c->range.level[1].cat); |
101 | mls_context_init(c); | 89 | mls_context_init(c); |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 68c7348d1ac..d42951fcbe8 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include "ebitmap.h" | 22 | #include "ebitmap.h" |
23 | #include "policydb.h" | 23 | #include "policydb.h" |
24 | 24 | ||
25 | #define BITS_PER_U64 (sizeof(u64) * 8) | ||
26 | |||
25 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2) | 27 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2) |
26 | { | 28 | { |
27 | struct ebitmap_node *n1, *n2; | 29 | struct ebitmap_node *n1, *n2; |
@@ -128,7 +130,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, | |||
128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; | 130 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; |
129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; | 131 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; |
130 | c_iter->bitmap[cmap_idx] | 132 | c_iter->bitmap[cmap_idx] |
131 | |= e_iter->maps[cmap_idx] << cmap_sft; | 133 | |= e_iter->maps[i] << cmap_sft; |
132 | } | 134 | } |
133 | e_iter = e_iter->next; | 135 | e_iter = e_iter->next; |
134 | } | 136 | } |
@@ -363,10 +365,10 @@ int ebitmap_read(struct ebitmap *e, void *fp) | |||
363 | e->highbit = le32_to_cpu(buf[1]); | 365 | e->highbit = le32_to_cpu(buf[1]); |
364 | count = le32_to_cpu(buf[2]); | 366 | count = le32_to_cpu(buf[2]); |
365 | 367 | ||
366 | if (mapunit != sizeof(u64) * 8) { | 368 | if (mapunit != BITS_PER_U64) { |
367 | printk(KERN_ERR "SELinux: ebitmap: map size %u does not " | 369 | printk(KERN_ERR "SELinux: ebitmap: map size %u does not " |
368 | "match my size %Zd (high bit was %d)\n", | 370 | "match my size %Zd (high bit was %d)\n", |
369 | mapunit, sizeof(u64) * 8, e->highbit); | 371 | mapunit, BITS_PER_U64, e->highbit); |
370 | goto bad; | 372 | goto bad; |
371 | } | 373 | } |
372 | 374 | ||
@@ -446,3 +448,78 @@ bad: | |||
446 | ebitmap_destroy(e); | 448 | ebitmap_destroy(e); |
447 | goto out; | 449 | goto out; |
448 | } | 450 | } |
451 | |||
452 | int ebitmap_write(struct ebitmap *e, void *fp) | ||
453 | { | ||
454 | struct ebitmap_node *n; | ||
455 | u32 count; | ||
456 | __le32 buf[3]; | ||
457 | u64 map; | ||
458 | int bit, last_bit, last_startbit, rc; | ||
459 | |||
460 | buf[0] = cpu_to_le32(BITS_PER_U64); | ||
461 | |||
462 | count = 0; | ||
463 | last_bit = 0; | ||
464 | last_startbit = -1; | ||
465 | ebitmap_for_each_positive_bit(e, n, bit) { | ||
466 | if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) { | ||
467 | count++; | ||
468 | last_startbit = rounddown(bit, BITS_PER_U64); | ||
469 | } | ||
470 | last_bit = roundup(bit + 1, BITS_PER_U64); | ||
471 | } | ||
472 | buf[1] = cpu_to_le32(last_bit); | ||
473 | buf[2] = cpu_to_le32(count); | ||
474 | |||
475 | rc = put_entry(buf, sizeof(u32), 3, fp); | ||
476 | if (rc) | ||
477 | return rc; | ||
478 | |||
479 | map = 0; | ||
480 | last_startbit = INT_MIN; | ||
481 | ebitmap_for_each_positive_bit(e, n, bit) { | ||
482 | if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) { | ||
483 | __le64 buf64[1]; | ||
484 | |||
485 | /* this is the very first bit */ | ||
486 | if (!map) { | ||
487 | last_startbit = rounddown(bit, BITS_PER_U64); | ||
488 | map = (u64)1 << (bit - last_startbit); | ||
489 | continue; | ||
490 | } | ||
491 | |||
492 | /* write the last node */ | ||
493 | buf[0] = cpu_to_le32(last_startbit); | ||
494 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
495 | if (rc) | ||
496 | return rc; | ||
497 | |||
498 | buf64[0] = cpu_to_le64(map); | ||
499 | rc = put_entry(buf64, sizeof(u64), 1, fp); | ||
500 | if (rc) | ||
501 | return rc; | ||
502 | |||
503 | /* set up for the next node */ | ||
504 | map = 0; | ||
505 | last_startbit = rounddown(bit, BITS_PER_U64); | ||
506 | } | ||
507 | map |= (u64)1 << (bit - last_startbit); | ||
508 | } | ||
509 | /* write the last node */ | ||
510 | if (map) { | ||
511 | __le64 buf64[1]; | ||
512 | |||
513 | /* write the last node */ | ||
514 | buf[0] = cpu_to_le32(last_startbit); | ||
515 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
516 | if (rc) | ||
517 | return rc; | ||
518 | |||
519 | buf64[0] = cpu_to_le64(map); | ||
520 | rc = put_entry(buf64, sizeof(u64), 1, fp); | ||
521 | if (rc) | ||
522 | return rc; | ||
523 | } | ||
524 | return 0; | ||
525 | } | ||
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index f283b4367f5..1f4e93c2ae8 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h | |||
@@ -123,6 +123,7 @@ int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); | |||
123 | int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); | 123 | int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); |
124 | void ebitmap_destroy(struct ebitmap *e); | 124 | void ebitmap_destroy(struct ebitmap *e); |
125 | int ebitmap_read(struct ebitmap *e, void *fp); | 125 | int ebitmap_read(struct ebitmap *e, void *fp); |
126 | int ebitmap_write(struct ebitmap *e, void *fp); | ||
126 | 127 | ||
127 | #ifdef CONFIG_NETLABEL | 128 | #ifdef CONFIG_NETLABEL |
128 | int ebitmap_netlbl_export(struct ebitmap *ebmap, | 129 | int ebitmap_netlbl_export(struct ebitmap *ebmap, |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index b5407f16c2a..1ef8e4e8988 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -39,13 +39,13 @@ int mls_compute_context_len(struct context *context) | |||
39 | struct ebitmap *e; | 39 | struct ebitmap *e; |
40 | struct ebitmap_node *node; | 40 | struct ebitmap_node *node; |
41 | 41 | ||
42 | if (!selinux_mls_enabled) | 42 | if (!policydb.mls_enabled) |
43 | return 0; | 43 | return 0; |
44 | 44 | ||
45 | len = 1; /* for the beginning ":" */ | 45 | len = 1; /* for the beginning ":" */ |
46 | for (l = 0; l < 2; l++) { | 46 | for (l = 0; l < 2; l++) { |
47 | int index_sens = context->range.level[l].sens; | 47 | int index_sens = context->range.level[l].sens; |
48 | len += strlen(policydb.p_sens_val_to_name[index_sens - 1]); | 48 | len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1)); |
49 | 49 | ||
50 | /* categories */ | 50 | /* categories */ |
51 | head = -2; | 51 | head = -2; |
@@ -55,17 +55,17 @@ int mls_compute_context_len(struct context *context) | |||
55 | if (i - prev > 1) { | 55 | if (i - prev > 1) { |
56 | /* one or more negative bits are skipped */ | 56 | /* one or more negative bits are skipped */ |
57 | if (head != prev) { | 57 | if (head != prev) { |
58 | nm = policydb.p_cat_val_to_name[prev]; | 58 | nm = sym_name(&policydb, SYM_CATS, prev); |
59 | len += strlen(nm) + 1; | 59 | len += strlen(nm) + 1; |
60 | } | 60 | } |
61 | nm = policydb.p_cat_val_to_name[i]; | 61 | nm = sym_name(&policydb, SYM_CATS, i); |
62 | len += strlen(nm) + 1; | 62 | len += strlen(nm) + 1; |
63 | head = i; | 63 | head = i; |
64 | } | 64 | } |
65 | prev = i; | 65 | prev = i; |
66 | } | 66 | } |
67 | if (prev != head) { | 67 | if (prev != head) { |
68 | nm = policydb.p_cat_val_to_name[prev]; | 68 | nm = sym_name(&policydb, SYM_CATS, prev); |
69 | len += strlen(nm) + 1; | 69 | len += strlen(nm) + 1; |
70 | } | 70 | } |
71 | if (l == 0) { | 71 | if (l == 0) { |
@@ -93,7 +93,7 @@ void mls_sid_to_context(struct context *context, | |||
93 | struct ebitmap *e; | 93 | struct ebitmap *e; |
94 | struct ebitmap_node *node; | 94 | struct ebitmap_node *node; |
95 | 95 | ||
96 | if (!selinux_mls_enabled) | 96 | if (!policydb.mls_enabled) |
97 | return; | 97 | return; |
98 | 98 | ||
99 | scontextp = *scontext; | 99 | scontextp = *scontext; |
@@ -102,8 +102,8 @@ void mls_sid_to_context(struct context *context, | |||
102 | scontextp++; | 102 | scontextp++; |
103 | 103 | ||
104 | for (l = 0; l < 2; l++) { | 104 | for (l = 0; l < 2; l++) { |
105 | strcpy(scontextp, | 105 | strcpy(scontextp, sym_name(&policydb, SYM_LEVELS, |
106 | policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); | 106 | context->range.level[l].sens - 1)); |
107 | scontextp += strlen(scontextp); | 107 | scontextp += strlen(scontextp); |
108 | 108 | ||
109 | /* categories */ | 109 | /* categories */ |
@@ -118,7 +118,7 @@ void mls_sid_to_context(struct context *context, | |||
118 | *scontextp++ = '.'; | 118 | *scontextp++ = '.'; |
119 | else | 119 | else |
120 | *scontextp++ = ','; | 120 | *scontextp++ = ','; |
121 | nm = policydb.p_cat_val_to_name[prev]; | 121 | nm = sym_name(&policydb, SYM_CATS, prev); |
122 | strcpy(scontextp, nm); | 122 | strcpy(scontextp, nm); |
123 | scontextp += strlen(nm); | 123 | scontextp += strlen(nm); |
124 | } | 124 | } |
@@ -126,7 +126,7 @@ void mls_sid_to_context(struct context *context, | |||
126 | *scontextp++ = ':'; | 126 | *scontextp++ = ':'; |
127 | else | 127 | else |
128 | *scontextp++ = ','; | 128 | *scontextp++ = ','; |
129 | nm = policydb.p_cat_val_to_name[i]; | 129 | nm = sym_name(&policydb, SYM_CATS, i); |
130 | strcpy(scontextp, nm); | 130 | strcpy(scontextp, nm); |
131 | scontextp += strlen(nm); | 131 | scontextp += strlen(nm); |
132 | head = i; | 132 | head = i; |
@@ -139,7 +139,7 @@ void mls_sid_to_context(struct context *context, | |||
139 | *scontextp++ = '.'; | 139 | *scontextp++ = '.'; |
140 | else | 140 | else |
141 | *scontextp++ = ','; | 141 | *scontextp++ = ','; |
142 | nm = policydb.p_cat_val_to_name[prev]; | 142 | nm = sym_name(&policydb, SYM_CATS, prev); |
143 | strcpy(scontextp, nm); | 143 | strcpy(scontextp, nm); |
144 | scontextp += strlen(nm); | 144 | scontextp += strlen(nm); |
145 | } | 145 | } |
@@ -166,7 +166,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l) | |||
166 | if (!l->sens || l->sens > p->p_levels.nprim) | 166 | if (!l->sens || l->sens > p->p_levels.nprim) |
167 | return 0; | 167 | return 0; |
168 | levdatum = hashtab_search(p->p_levels.table, | 168 | levdatum = hashtab_search(p->p_levels.table, |
169 | p->p_sens_val_to_name[l->sens - 1]); | 169 | sym_name(p, SYM_LEVELS, l->sens - 1)); |
170 | if (!levdatum) | 170 | if (!levdatum) |
171 | return 0; | 171 | return 0; |
172 | 172 | ||
@@ -200,7 +200,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
200 | { | 200 | { |
201 | struct user_datum *usrdatum; | 201 | struct user_datum *usrdatum; |
202 | 202 | ||
203 | if (!selinux_mls_enabled) | 203 | if (!p->mls_enabled) |
204 | return 1; | 204 | return 1; |
205 | 205 | ||
206 | if (!mls_range_isvalid(p, &c->range)) | 206 | if (!mls_range_isvalid(p, &c->range)) |
@@ -253,9 +253,9 @@ int mls_context_to_sid(struct policydb *pol, | |||
253 | struct cat_datum *catdatum, *rngdatum; | 253 | struct cat_datum *catdatum, *rngdatum; |
254 | int l, rc = -EINVAL; | 254 | int l, rc = -EINVAL; |
255 | 255 | ||
256 | if (!selinux_mls_enabled) { | 256 | if (!pol->mls_enabled) { |
257 | if (def_sid != SECSID_NULL && oldc) | 257 | if (def_sid != SECSID_NULL && oldc) |
258 | *scontext += strlen(*scontext)+1; | 258 | *scontext += strlen(*scontext) + 1; |
259 | return 0; | 259 | return 0; |
260 | } | 260 | } |
261 | 261 | ||
@@ -387,7 +387,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
387 | char *tmpstr, *freestr; | 387 | char *tmpstr, *freestr; |
388 | int rc; | 388 | int rc; |
389 | 389 | ||
390 | if (!selinux_mls_enabled) | 390 | if (!policydb.mls_enabled) |
391 | return -EINVAL; | 391 | return -EINVAL; |
392 | 392 | ||
393 | /* we need freestr because mls_context_to_sid will change | 393 | /* we need freestr because mls_context_to_sid will change |
@@ -407,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
407 | /* | 407 | /* |
408 | * Copies the MLS range `range' into `context'. | 408 | * Copies the MLS range `range' into `context'. |
409 | */ | 409 | */ |
410 | static inline int mls_range_set(struct context *context, | 410 | int mls_range_set(struct context *context, |
411 | struct mls_range *range) | 411 | struct mls_range *range) |
412 | { | 412 | { |
413 | int l, rc = 0; | 413 | int l, rc = 0; |
@@ -427,7 +427,7 @@ static inline int mls_range_set(struct context *context, | |||
427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, |
428 | struct context *usercon) | 428 | struct context *usercon) |
429 | { | 429 | { |
430 | if (selinux_mls_enabled) { | 430 | if (policydb.mls_enabled) { |
431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); | 431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); |
432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); | 432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); |
433 | struct mls_level *user_low = &(user->range.level[0]); | 433 | struct mls_level *user_low = &(user->range.level[0]); |
@@ -477,12 +477,13 @@ int mls_convert_context(struct policydb *oldp, | |||
477 | struct ebitmap_node *node; | 477 | struct ebitmap_node *node; |
478 | int l, i; | 478 | int l, i; |
479 | 479 | ||
480 | if (!selinux_mls_enabled) | 480 | if (!policydb.mls_enabled) |
481 | return 0; | 481 | return 0; |
482 | 482 | ||
483 | for (l = 0; l < 2; l++) { | 483 | for (l = 0; l < 2; l++) { |
484 | levdatum = hashtab_search(newp->p_levels.table, | 484 | levdatum = hashtab_search(newp->p_levels.table, |
485 | oldp->p_sens_val_to_name[c->range.level[l].sens - 1]); | 485 | sym_name(oldp, SYM_LEVELS, |
486 | c->range.level[l].sens - 1)); | ||
486 | 487 | ||
487 | if (!levdatum) | 488 | if (!levdatum) |
488 | return -EINVAL; | 489 | return -EINVAL; |
@@ -493,7 +494,7 @@ int mls_convert_context(struct policydb *oldp, | |||
493 | int rc; | 494 | int rc; |
494 | 495 | ||
495 | catdatum = hashtab_search(newp->p_cats.table, | 496 | catdatum = hashtab_search(newp->p_cats.table, |
496 | oldp->p_cat_val_to_name[i]); | 497 | sym_name(oldp, SYM_CATS, i)); |
497 | if (!catdatum) | 498 | if (!catdatum) |
498 | return -EINVAL; | 499 | return -EINVAL; |
499 | rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); | 500 | rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); |
@@ -513,26 +514,24 @@ int mls_compute_sid(struct context *scontext, | |||
513 | u32 specified, | 514 | u32 specified, |
514 | struct context *newcontext) | 515 | struct context *newcontext) |
515 | { | 516 | { |
516 | struct range_trans *rtr; | 517 | struct range_trans rtr; |
518 | struct mls_range *r; | ||
517 | 519 | ||
518 | if (!selinux_mls_enabled) | 520 | if (!policydb.mls_enabled) |
519 | return 0; | 521 | return 0; |
520 | 522 | ||
521 | switch (specified) { | 523 | switch (specified) { |
522 | case AVTAB_TRANSITION: | 524 | case AVTAB_TRANSITION: |
523 | /* Look for a range transition rule. */ | 525 | /* Look for a range transition rule. */ |
524 | for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { | 526 | rtr.source_type = scontext->type; |
525 | if (rtr->source_type == scontext->type && | 527 | rtr.target_type = tcontext->type; |
526 | rtr->target_type == tcontext->type && | 528 | rtr.target_class = tclass; |
527 | rtr->target_class == tclass) { | 529 | r = hashtab_search(policydb.range_tr, &rtr); |
528 | /* Set the range from the rule */ | 530 | if (r) |
529 | return mls_range_set(newcontext, | 531 | return mls_range_set(newcontext, r); |
530 | &rtr->target_range); | ||
531 | } | ||
532 | } | ||
533 | /* Fallthrough */ | 532 | /* Fallthrough */ |
534 | case AVTAB_CHANGE: | 533 | case AVTAB_CHANGE: |
535 | if (tclass == SECCLASS_PROCESS) | 534 | if (tclass == policydb.process_class) |
536 | /* Use the process MLS attributes. */ | 535 | /* Use the process MLS attributes. */ |
537 | return mls_context_cpy(newcontext, scontext); | 536 | return mls_context_cpy(newcontext, scontext); |
538 | else | 537 | else |
@@ -541,8 +540,8 @@ int mls_compute_sid(struct context *scontext, | |||
541 | case AVTAB_MEMBER: | 540 | case AVTAB_MEMBER: |
542 | /* Use the process effective MLS attributes. */ | 541 | /* Use the process effective MLS attributes. */ |
543 | return mls_context_cpy_low(newcontext, scontext); | 542 | return mls_context_cpy_low(newcontext, scontext); |
544 | default: | 543 | |
545 | return -EINVAL; | 544 | /* fall through */ |
546 | } | 545 | } |
547 | return -EINVAL; | 546 | return -EINVAL; |
548 | } | 547 | } |
@@ -561,7 +560,7 @@ int mls_compute_sid(struct context *scontext, | |||
561 | void mls_export_netlbl_lvl(struct context *context, | 560 | void mls_export_netlbl_lvl(struct context *context, |
562 | struct netlbl_lsm_secattr *secattr) | 561 | struct netlbl_lsm_secattr *secattr) |
563 | { | 562 | { |
564 | if (!selinux_mls_enabled) | 563 | if (!policydb.mls_enabled) |
565 | return; | 564 | return; |
566 | 565 | ||
567 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; | 566 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; |
@@ -581,7 +580,7 @@ void mls_export_netlbl_lvl(struct context *context, | |||
581 | void mls_import_netlbl_lvl(struct context *context, | 580 | void mls_import_netlbl_lvl(struct context *context, |
582 | struct netlbl_lsm_secattr *secattr) | 581 | struct netlbl_lsm_secattr *secattr) |
583 | { | 582 | { |
584 | if (!selinux_mls_enabled) | 583 | if (!policydb.mls_enabled) |
585 | return; | 584 | return; |
586 | 585 | ||
587 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; | 586 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; |
@@ -603,7 +602,7 @@ int mls_export_netlbl_cat(struct context *context, | |||
603 | { | 602 | { |
604 | int rc; | 603 | int rc; |
605 | 604 | ||
606 | if (!selinux_mls_enabled) | 605 | if (!policydb.mls_enabled) |
607 | return 0; | 606 | return 0; |
608 | 607 | ||
609 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, | 608 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
@@ -631,7 +630,7 @@ int mls_import_netlbl_cat(struct context *context, | |||
631 | { | 630 | { |
632 | int rc; | 631 | int rc; |
633 | 632 | ||
634 | if (!selinux_mls_enabled) | 633 | if (!policydb.mls_enabled) |
635 | return 0; | 634 | return 0; |
636 | 635 | ||
637 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, | 636 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 1276715aaa8..cd9152632e5 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
@@ -39,6 +39,8 @@ int mls_context_to_sid(struct policydb *p, | |||
39 | 39 | ||
40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); | 40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); |
41 | 41 | ||
42 | int mls_range_set(struct context *context, struct mls_range *range); | ||
43 | |||
42 | int mls_convert_context(struct policydb *oldp, | 44 | int mls_convert_context(struct policydb *oldp, |
43 | struct policydb *newp, | 45 | struct policydb *newp, |
44 | struct context *context); | 46 | struct context *context); |
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h index b6e943a2106..03bed52a805 100644 --- a/security/selinux/ss/mls_types.h +++ b/security/selinux/ss/mls_types.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define _SS_MLS_TYPES_H_ | 15 | #define _SS_MLS_TYPES_H_ |
16 | 16 | ||
17 | #include "security.h" | 17 | #include "security.h" |
18 | #include "ebitmap.h" | ||
18 | 19 | ||
19 | struct mls_level { | 20 | struct mls_level { |
20 | u32 sens; /* sensitivity */ | 21 | u32 sens; /* sensitivity */ |
@@ -27,18 +28,12 @@ struct mls_range { | |||
27 | 28 | ||
28 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) | 29 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) |
29 | { | 30 | { |
30 | if (!selinux_mls_enabled) | ||
31 | return 1; | ||
32 | |||
33 | return ((l1->sens == l2->sens) && | 31 | return ((l1->sens == l2->sens) && |
34 | ebitmap_cmp(&l1->cat, &l2->cat)); | 32 | ebitmap_cmp(&l1->cat, &l2->cat)); |
35 | } | 33 | } |
36 | 34 | ||
37 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) | 35 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) |
38 | { | 36 | { |
39 | if (!selinux_mls_enabled) | ||
40 | return 1; | ||
41 | |||
42 | return ((l1->sens >= l2->sens) && | 37 | return ((l1->sens >= l2->sens) && |
43 | ebitmap_contains(&l1->cat, &l2->cat)); | 38 | ebitmap_contains(&l1->cat, &l2->cat)); |
44 | } | 39 | } |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 72e4a54973a..be9de387283 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -31,16 +31,18 @@ | |||
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
33 | #include <linux/audit.h> | 33 | #include <linux/audit.h> |
34 | #include <linux/flex_array.h> | ||
34 | #include "security.h" | 35 | #include "security.h" |
35 | 36 | ||
36 | #include "policydb.h" | 37 | #include "policydb.h" |
37 | #include "conditional.h" | 38 | #include "conditional.h" |
38 | #include "mls.h" | 39 | #include "mls.h" |
40 | #include "services.h" | ||
39 | 41 | ||
40 | #define _DEBUG_HASHES | 42 | #define _DEBUG_HASHES |
41 | 43 | ||
42 | #ifdef DEBUG_HASHES | 44 | #ifdef DEBUG_HASHES |
43 | static char *symtab_name[SYM_NUM] = { | 45 | static const char *symtab_name[SYM_NUM] = { |
44 | "common prefixes", | 46 | "common prefixes", |
45 | "classes", | 47 | "classes", |
46 | "roles", | 48 | "roles", |
@@ -52,8 +54,6 @@ static char *symtab_name[SYM_NUM] = { | |||
52 | }; | 54 | }; |
53 | #endif | 55 | #endif |
54 | 56 | ||
55 | int selinux_mls_enabled; | ||
56 | |||
57 | static unsigned int symtab_sizes[SYM_NUM] = { | 57 | static unsigned int symtab_sizes[SYM_NUM] = { |
58 | 2, | 58 | 2, |
59 | 32, | 59 | 32, |
@@ -148,33 +148,55 @@ static int roles_init(struct policydb *p) | |||
148 | int rc; | 148 | int rc; |
149 | struct role_datum *role; | 149 | struct role_datum *role; |
150 | 150 | ||
151 | rc = -ENOMEM; | ||
151 | role = kzalloc(sizeof(*role), GFP_KERNEL); | 152 | role = kzalloc(sizeof(*role), GFP_KERNEL); |
152 | if (!role) { | 153 | if (!role) |
153 | rc = -ENOMEM; | ||
154 | goto out; | 154 | goto out; |
155 | } | 155 | |
156 | rc = -EINVAL; | ||
156 | role->value = ++p->p_roles.nprim; | 157 | role->value = ++p->p_roles.nprim; |
157 | if (role->value != OBJECT_R_VAL) { | 158 | if (role->value != OBJECT_R_VAL) |
158 | rc = -EINVAL; | 159 | goto out; |
159 | goto out_free_role; | 160 | |
160 | } | 161 | rc = -ENOMEM; |
161 | key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL); | 162 | key = kstrdup(OBJECT_R, GFP_KERNEL); |
162 | if (!key) { | 163 | if (!key) |
163 | rc = -ENOMEM; | 164 | goto out; |
164 | goto out_free_role; | 165 | |
165 | } | ||
166 | strcpy(key, OBJECT_R); | ||
167 | rc = hashtab_insert(p->p_roles.table, key, role); | 166 | rc = hashtab_insert(p->p_roles.table, key, role); |
168 | if (rc) | 167 | if (rc) |
169 | goto out_free_key; | 168 | goto out; |
170 | out: | ||
171 | return rc; | ||
172 | 169 | ||
173 | out_free_key: | 170 | return 0; |
171 | out: | ||
174 | kfree(key); | 172 | kfree(key); |
175 | out_free_role: | ||
176 | kfree(role); | 173 | kfree(role); |
177 | goto out; | 174 | return rc; |
175 | } | ||
176 | |||
177 | static u32 rangetr_hash(struct hashtab *h, const void *k) | ||
178 | { | ||
179 | const struct range_trans *key = k; | ||
180 | return (key->source_type + (key->target_type << 3) + | ||
181 | (key->target_class << 5)) & (h->size - 1); | ||
182 | } | ||
183 | |||
184 | static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2) | ||
185 | { | ||
186 | const struct range_trans *key1 = k1, *key2 = k2; | ||
187 | int v; | ||
188 | |||
189 | v = key1->source_type - key2->source_type; | ||
190 | if (v) | ||
191 | return v; | ||
192 | |||
193 | v = key1->target_type - key2->target_type; | ||
194 | if (v) | ||
195 | return v; | ||
196 | |||
197 | v = key1->target_class - key2->target_class; | ||
198 | |||
199 | return v; | ||
178 | } | 200 | } |
179 | 201 | ||
180 | /* | 202 | /* |
@@ -189,31 +211,33 @@ static int policydb_init(struct policydb *p) | |||
189 | for (i = 0; i < SYM_NUM; i++) { | 211 | for (i = 0; i < SYM_NUM; i++) { |
190 | rc = symtab_init(&p->symtab[i], symtab_sizes[i]); | 212 | rc = symtab_init(&p->symtab[i], symtab_sizes[i]); |
191 | if (rc) | 213 | if (rc) |
192 | goto out_free_symtab; | 214 | goto out; |
193 | } | 215 | } |
194 | 216 | ||
195 | rc = avtab_init(&p->te_avtab); | 217 | rc = avtab_init(&p->te_avtab); |
196 | if (rc) | 218 | if (rc) |
197 | goto out_free_symtab; | 219 | goto out; |
198 | 220 | ||
199 | rc = roles_init(p); | 221 | rc = roles_init(p); |
200 | if (rc) | 222 | if (rc) |
201 | goto out_free_symtab; | 223 | goto out; |
202 | 224 | ||
203 | rc = cond_policydb_init(p); | 225 | rc = cond_policydb_init(p); |
204 | if (rc) | 226 | if (rc) |
205 | goto out_free_symtab; | 227 | goto out; |
228 | |||
229 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); | ||
230 | if (!p->range_tr) | ||
231 | goto out; | ||
206 | 232 | ||
207 | ebitmap_init(&p->policycaps); | 233 | ebitmap_init(&p->policycaps); |
208 | ebitmap_init(&p->permissive_map); | 234 | ebitmap_init(&p->permissive_map); |
209 | 235 | ||
236 | return 0; | ||
210 | out: | 237 | out: |
211 | return rc; | ||
212 | |||
213 | out_free_symtab: | ||
214 | for (i = 0; i < SYM_NUM; i++) | 238 | for (i = 0; i < SYM_NUM; i++) |
215 | hashtab_destroy(p->symtab[i].table); | 239 | hashtab_destroy(p->symtab[i].table); |
216 | goto out; | 240 | return rc; |
217 | } | 241 | } |
218 | 242 | ||
219 | /* | 243 | /* |
@@ -230,12 +254,17 @@ static int common_index(void *key, void *datum, void *datap) | |||
230 | { | 254 | { |
231 | struct policydb *p; | 255 | struct policydb *p; |
232 | struct common_datum *comdatum; | 256 | struct common_datum *comdatum; |
257 | struct flex_array *fa; | ||
233 | 258 | ||
234 | comdatum = datum; | 259 | comdatum = datum; |
235 | p = datap; | 260 | p = datap; |
236 | if (!comdatum->value || comdatum->value > p->p_commons.nprim) | 261 | if (!comdatum->value || comdatum->value > p->p_commons.nprim) |
237 | return -EINVAL; | 262 | return -EINVAL; |
238 | p->p_common_val_to_name[comdatum->value - 1] = key; | 263 | |
264 | fa = p->sym_val_to_name[SYM_COMMONS]; | ||
265 | if (flex_array_put_ptr(fa, comdatum->value - 1, key, | ||
266 | GFP_KERNEL | __GFP_ZERO)) | ||
267 | BUG(); | ||
239 | return 0; | 268 | return 0; |
240 | } | 269 | } |
241 | 270 | ||
@@ -243,12 +272,16 @@ static int class_index(void *key, void *datum, void *datap) | |||
243 | { | 272 | { |
244 | struct policydb *p; | 273 | struct policydb *p; |
245 | struct class_datum *cladatum; | 274 | struct class_datum *cladatum; |
275 | struct flex_array *fa; | ||
246 | 276 | ||
247 | cladatum = datum; | 277 | cladatum = datum; |
248 | p = datap; | 278 | p = datap; |
249 | if (!cladatum->value || cladatum->value > p->p_classes.nprim) | 279 | if (!cladatum->value || cladatum->value > p->p_classes.nprim) |
250 | return -EINVAL; | 280 | return -EINVAL; |
251 | p->p_class_val_to_name[cladatum->value - 1] = key; | 281 | fa = p->sym_val_to_name[SYM_CLASSES]; |
282 | if (flex_array_put_ptr(fa, cladatum->value - 1, key, | ||
283 | GFP_KERNEL | __GFP_ZERO)) | ||
284 | BUG(); | ||
252 | p->class_val_to_struct[cladatum->value - 1] = cladatum; | 285 | p->class_val_to_struct[cladatum->value - 1] = cladatum; |
253 | return 0; | 286 | return 0; |
254 | } | 287 | } |
@@ -257,6 +290,7 @@ static int role_index(void *key, void *datum, void *datap) | |||
257 | { | 290 | { |
258 | struct policydb *p; | 291 | struct policydb *p; |
259 | struct role_datum *role; | 292 | struct role_datum *role; |
293 | struct flex_array *fa; | ||
260 | 294 | ||
261 | role = datum; | 295 | role = datum; |
262 | p = datap; | 296 | p = datap; |
@@ -264,7 +298,11 @@ static int role_index(void *key, void *datum, void *datap) | |||
264 | || role->value > p->p_roles.nprim | 298 | || role->value > p->p_roles.nprim |
265 | || role->bounds > p->p_roles.nprim) | 299 | || role->bounds > p->p_roles.nprim) |
266 | return -EINVAL; | 300 | return -EINVAL; |
267 | p->p_role_val_to_name[role->value - 1] = key; | 301 | |
302 | fa = p->sym_val_to_name[SYM_ROLES]; | ||
303 | if (flex_array_put_ptr(fa, role->value - 1, key, | ||
304 | GFP_KERNEL | __GFP_ZERO)) | ||
305 | BUG(); | ||
268 | p->role_val_to_struct[role->value - 1] = role; | 306 | p->role_val_to_struct[role->value - 1] = role; |
269 | return 0; | 307 | return 0; |
270 | } | 308 | } |
@@ -273,6 +311,7 @@ static int type_index(void *key, void *datum, void *datap) | |||
273 | { | 311 | { |
274 | struct policydb *p; | 312 | struct policydb *p; |
275 | struct type_datum *typdatum; | 313 | struct type_datum *typdatum; |
314 | struct flex_array *fa; | ||
276 | 315 | ||
277 | typdatum = datum; | 316 | typdatum = datum; |
278 | p = datap; | 317 | p = datap; |
@@ -282,8 +321,15 @@ static int type_index(void *key, void *datum, void *datap) | |||
282 | || typdatum->value > p->p_types.nprim | 321 | || typdatum->value > p->p_types.nprim |
283 | || typdatum->bounds > p->p_types.nprim) | 322 | || typdatum->bounds > p->p_types.nprim) |
284 | return -EINVAL; | 323 | return -EINVAL; |
285 | p->p_type_val_to_name[typdatum->value - 1] = key; | 324 | fa = p->sym_val_to_name[SYM_TYPES]; |
286 | p->type_val_to_struct[typdatum->value - 1] = typdatum; | 325 | if (flex_array_put_ptr(fa, typdatum->value - 1, key, |
326 | GFP_KERNEL | __GFP_ZERO)) | ||
327 | BUG(); | ||
328 | |||
329 | fa = p->type_val_to_struct_array; | ||
330 | if (flex_array_put_ptr(fa, typdatum->value - 1, typdatum, | ||
331 | GFP_KERNEL | __GFP_ZERO)) | ||
332 | BUG(); | ||
287 | } | 333 | } |
288 | 334 | ||
289 | return 0; | 335 | return 0; |
@@ -293,6 +339,7 @@ static int user_index(void *key, void *datum, void *datap) | |||
293 | { | 339 | { |
294 | struct policydb *p; | 340 | struct policydb *p; |
295 | struct user_datum *usrdatum; | 341 | struct user_datum *usrdatum; |
342 | struct flex_array *fa; | ||
296 | 343 | ||
297 | usrdatum = datum; | 344 | usrdatum = datum; |
298 | p = datap; | 345 | p = datap; |
@@ -300,7 +347,11 @@ static int user_index(void *key, void *datum, void *datap) | |||
300 | || usrdatum->value > p->p_users.nprim | 347 | || usrdatum->value > p->p_users.nprim |
301 | || usrdatum->bounds > p->p_users.nprim) | 348 | || usrdatum->bounds > p->p_users.nprim) |
302 | return -EINVAL; | 349 | return -EINVAL; |
303 | p->p_user_val_to_name[usrdatum->value - 1] = key; | 350 | |
351 | fa = p->sym_val_to_name[SYM_USERS]; | ||
352 | if (flex_array_put_ptr(fa, usrdatum->value - 1, key, | ||
353 | GFP_KERNEL | __GFP_ZERO)) | ||
354 | BUG(); | ||
304 | p->user_val_to_struct[usrdatum->value - 1] = usrdatum; | 355 | p->user_val_to_struct[usrdatum->value - 1] = usrdatum; |
305 | return 0; | 356 | return 0; |
306 | } | 357 | } |
@@ -309,6 +360,7 @@ static int sens_index(void *key, void *datum, void *datap) | |||
309 | { | 360 | { |
310 | struct policydb *p; | 361 | struct policydb *p; |
311 | struct level_datum *levdatum; | 362 | struct level_datum *levdatum; |
363 | struct flex_array *fa; | ||
312 | 364 | ||
313 | levdatum = datum; | 365 | levdatum = datum; |
314 | p = datap; | 366 | p = datap; |
@@ -317,7 +369,10 @@ static int sens_index(void *key, void *datum, void *datap) | |||
317 | if (!levdatum->level->sens || | 369 | if (!levdatum->level->sens || |
318 | levdatum->level->sens > p->p_levels.nprim) | 370 | levdatum->level->sens > p->p_levels.nprim) |
319 | return -EINVAL; | 371 | return -EINVAL; |
320 | p->p_sens_val_to_name[levdatum->level->sens - 1] = key; | 372 | fa = p->sym_val_to_name[SYM_LEVELS]; |
373 | if (flex_array_put_ptr(fa, levdatum->level->sens - 1, key, | ||
374 | GFP_KERNEL | __GFP_ZERO)) | ||
375 | BUG(); | ||
321 | } | 376 | } |
322 | 377 | ||
323 | return 0; | 378 | return 0; |
@@ -327,6 +382,7 @@ static int cat_index(void *key, void *datum, void *datap) | |||
327 | { | 382 | { |
328 | struct policydb *p; | 383 | struct policydb *p; |
329 | struct cat_datum *catdatum; | 384 | struct cat_datum *catdatum; |
385 | struct flex_array *fa; | ||
330 | 386 | ||
331 | catdatum = datum; | 387 | catdatum = datum; |
332 | p = datap; | 388 | p = datap; |
@@ -334,7 +390,10 @@ static int cat_index(void *key, void *datum, void *datap) | |||
334 | if (!catdatum->isalias) { | 390 | if (!catdatum->isalias) { |
335 | if (!catdatum->value || catdatum->value > p->p_cats.nprim) | 391 | if (!catdatum->value || catdatum->value > p->p_cats.nprim) |
336 | return -EINVAL; | 392 | return -EINVAL; |
337 | p->p_cat_val_to_name[catdatum->value - 1] = key; | 393 | fa = p->sym_val_to_name[SYM_CATS]; |
394 | if (flex_array_put_ptr(fa, catdatum->value - 1, key, | ||
395 | GFP_KERNEL | __GFP_ZERO)) | ||
396 | BUG(); | ||
338 | } | 397 | } |
339 | 398 | ||
340 | return 0; | 399 | return 0; |
@@ -352,47 +411,6 @@ static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) = | |||
352 | cat_index, | 411 | cat_index, |
353 | }; | 412 | }; |
354 | 413 | ||
355 | /* | ||
356 | * Define the common val_to_name array and the class | ||
357 | * val_to_name and val_to_struct arrays in a policy | ||
358 | * database structure. | ||
359 | * | ||
360 | * Caller must clean up upon failure. | ||
361 | */ | ||
362 | static int policydb_index_classes(struct policydb *p) | ||
363 | { | ||
364 | int rc; | ||
365 | |||
366 | p->p_common_val_to_name = | ||
367 | kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL); | ||
368 | if (!p->p_common_val_to_name) { | ||
369 | rc = -ENOMEM; | ||
370 | goto out; | ||
371 | } | ||
372 | |||
373 | rc = hashtab_map(p->p_commons.table, common_index, p); | ||
374 | if (rc) | ||
375 | goto out; | ||
376 | |||
377 | p->class_val_to_struct = | ||
378 | kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), GFP_KERNEL); | ||
379 | if (!p->class_val_to_struct) { | ||
380 | rc = -ENOMEM; | ||
381 | goto out; | ||
382 | } | ||
383 | |||
384 | p->p_class_val_to_name = | ||
385 | kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL); | ||
386 | if (!p->p_class_val_to_name) { | ||
387 | rc = -ENOMEM; | ||
388 | goto out; | ||
389 | } | ||
390 | |||
391 | rc = hashtab_map(p->p_classes.table, class_index, p); | ||
392 | out: | ||
393 | return rc; | ||
394 | } | ||
395 | |||
396 | #ifdef DEBUG_HASHES | 414 | #ifdef DEBUG_HASHES |
397 | static void symtab_hash_eval(struct symtab *s) | 415 | static void symtab_hash_eval(struct symtab *s) |
398 | { | 416 | { |
@@ -408,6 +426,20 @@ static void symtab_hash_eval(struct symtab *s) | |||
408 | info.slots_used, h->size, info.max_chain_len); | 426 | info.slots_used, h->size, info.max_chain_len); |
409 | } | 427 | } |
410 | } | 428 | } |
429 | |||
430 | static void rangetr_hash_eval(struct hashtab *h) | ||
431 | { | ||
432 | struct hashtab_info info; | ||
433 | |||
434 | hashtab_stat(h, &info); | ||
435 | printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, " | ||
436 | "longest chain length %d\n", h->nel, | ||
437 | info.slots_used, h->size, info.max_chain_len); | ||
438 | } | ||
439 | #else | ||
440 | static inline void rangetr_hash_eval(struct hashtab *h) | ||
441 | { | ||
442 | } | ||
411 | #endif | 443 | #endif |
412 | 444 | ||
413 | /* | 445 | /* |
@@ -416,13 +448,13 @@ static void symtab_hash_eval(struct symtab *s) | |||
416 | * | 448 | * |
417 | * Caller must clean up on failure. | 449 | * Caller must clean up on failure. |
418 | */ | 450 | */ |
419 | static int policydb_index_others(struct policydb *p) | 451 | static int policydb_index(struct policydb *p) |
420 | { | 452 | { |
421 | int i, rc = 0; | 453 | int i, rc; |
422 | 454 | ||
423 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", | 455 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", |
424 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); | 456 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); |
425 | if (selinux_mls_enabled) | 457 | if (p->mls_enabled) |
426 | printk(", %d sens, %d cats", p->p_levels.nprim, | 458 | printk(", %d sens, %d cats", p->p_levels.nprim, |
427 | p->p_cats.nprim); | 459 | p->p_cats.nprim); |
428 | printk("\n"); | 460 | printk("\n"); |
@@ -435,47 +467,63 @@ static int policydb_index_others(struct policydb *p) | |||
435 | symtab_hash_eval(p->symtab); | 467 | symtab_hash_eval(p->symtab); |
436 | #endif | 468 | #endif |
437 | 469 | ||
470 | rc = -ENOMEM; | ||
471 | p->class_val_to_struct = | ||
472 | kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), | ||
473 | GFP_KERNEL); | ||
474 | if (!p->class_val_to_struct) | ||
475 | goto out; | ||
476 | |||
477 | rc = -ENOMEM; | ||
438 | p->role_val_to_struct = | 478 | p->role_val_to_struct = |
439 | kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)), | 479 | kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)), |
440 | GFP_KERNEL); | 480 | GFP_KERNEL); |
441 | if (!p->role_val_to_struct) { | 481 | if (!p->role_val_to_struct) |
442 | rc = -ENOMEM; | ||
443 | goto out; | 482 | goto out; |
444 | } | ||
445 | 483 | ||
484 | rc = -ENOMEM; | ||
446 | p->user_val_to_struct = | 485 | p->user_val_to_struct = |
447 | kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)), | 486 | kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)), |
448 | GFP_KERNEL); | 487 | GFP_KERNEL); |
449 | if (!p->user_val_to_struct) { | 488 | if (!p->user_val_to_struct) |
450 | rc = -ENOMEM; | ||
451 | goto out; | 489 | goto out; |
452 | } | ||
453 | 490 | ||
454 | p->type_val_to_struct = | 491 | /* Yes, I want the sizeof the pointer, not the structure */ |
455 | kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)), | 492 | rc = -ENOMEM; |
456 | GFP_KERNEL); | 493 | p->type_val_to_struct_array = flex_array_alloc(sizeof(struct type_datum *), |
457 | if (!p->type_val_to_struct) { | 494 | p->p_types.nprim, |
458 | rc = -ENOMEM; | 495 | GFP_KERNEL | __GFP_ZERO); |
496 | if (!p->type_val_to_struct_array) | ||
459 | goto out; | 497 | goto out; |
460 | } | ||
461 | 498 | ||
462 | if (cond_init_bool_indexes(p)) { | 499 | rc = flex_array_prealloc(p->type_val_to_struct_array, 0, |
463 | rc = -ENOMEM; | 500 | p->p_types.nprim - 1, GFP_KERNEL | __GFP_ZERO); |
501 | if (rc) | ||
464 | goto out; | 502 | goto out; |
465 | } | ||
466 | 503 | ||
467 | for (i = SYM_ROLES; i < SYM_NUM; i++) { | 504 | rc = -ENOMEM; |
468 | p->sym_val_to_name[i] = | 505 | if (cond_init_bool_indexes(p)) |
469 | kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL); | 506 | goto out; |
470 | if (!p->sym_val_to_name[i]) { | 507 | |
471 | rc = -ENOMEM; | 508 | for (i = 0; i < SYM_NUM; i++) { |
509 | rc = -ENOMEM; | ||
510 | p->sym_val_to_name[i] = flex_array_alloc(sizeof(char *), | ||
511 | p->symtab[i].nprim, | ||
512 | GFP_KERNEL | __GFP_ZERO); | ||
513 | if (!p->sym_val_to_name[i]) | ||
472 | goto out; | 514 | goto out; |
473 | } | 515 | |
516 | rc = flex_array_prealloc(p->sym_val_to_name[i], | ||
517 | 0, p->symtab[i].nprim - 1, | ||
518 | GFP_KERNEL | __GFP_ZERO); | ||
519 | if (rc) | ||
520 | goto out; | ||
521 | |||
474 | rc = hashtab_map(p->symtab[i].table, index_f[i], p); | 522 | rc = hashtab_map(p->symtab[i].table, index_f[i], p); |
475 | if (rc) | 523 | if (rc) |
476 | goto out; | 524 | goto out; |
477 | } | 525 | } |
478 | 526 | rc = 0; | |
479 | out: | 527 | out: |
480 | return rc; | 528 | return rc; |
481 | } | 529 | } |
@@ -498,9 +546,11 @@ static int common_destroy(void *key, void *datum, void *p) | |||
498 | struct common_datum *comdatum; | 546 | struct common_datum *comdatum; |
499 | 547 | ||
500 | kfree(key); | 548 | kfree(key); |
501 | comdatum = datum; | 549 | if (datum) { |
502 | hashtab_map(comdatum->permissions.table, perm_destroy, NULL); | 550 | comdatum = datum; |
503 | hashtab_destroy(comdatum->permissions.table); | 551 | hashtab_map(comdatum->permissions.table, perm_destroy, NULL); |
552 | hashtab_destroy(comdatum->permissions.table); | ||
553 | } | ||
504 | kfree(datum); | 554 | kfree(datum); |
505 | return 0; | 555 | return 0; |
506 | } | 556 | } |
@@ -512,38 +562,40 @@ static int cls_destroy(void *key, void *datum, void *p) | |||
512 | struct constraint_expr *e, *etmp; | 562 | struct constraint_expr *e, *etmp; |
513 | 563 | ||
514 | kfree(key); | 564 | kfree(key); |
515 | cladatum = datum; | 565 | if (datum) { |
516 | hashtab_map(cladatum->permissions.table, perm_destroy, NULL); | 566 | cladatum = datum; |
517 | hashtab_destroy(cladatum->permissions.table); | 567 | hashtab_map(cladatum->permissions.table, perm_destroy, NULL); |
518 | constraint = cladatum->constraints; | 568 | hashtab_destroy(cladatum->permissions.table); |
519 | while (constraint) { | 569 | constraint = cladatum->constraints; |
520 | e = constraint->expr; | 570 | while (constraint) { |
521 | while (e) { | 571 | e = constraint->expr; |
522 | ebitmap_destroy(&e->names); | 572 | while (e) { |
523 | etmp = e; | 573 | ebitmap_destroy(&e->names); |
524 | e = e->next; | 574 | etmp = e; |
525 | kfree(etmp); | 575 | e = e->next; |
576 | kfree(etmp); | ||
577 | } | ||
578 | ctemp = constraint; | ||
579 | constraint = constraint->next; | ||
580 | kfree(ctemp); | ||
526 | } | 581 | } |
527 | ctemp = constraint; | 582 | |
528 | constraint = constraint->next; | 583 | constraint = cladatum->validatetrans; |
529 | kfree(ctemp); | 584 | while (constraint) { |
530 | } | 585 | e = constraint->expr; |
531 | 586 | while (e) { | |
532 | constraint = cladatum->validatetrans; | 587 | ebitmap_destroy(&e->names); |
533 | while (constraint) { | 588 | etmp = e; |
534 | e = constraint->expr; | 589 | e = e->next; |
535 | while (e) { | 590 | kfree(etmp); |
536 | ebitmap_destroy(&e->names); | 591 | } |
537 | etmp = e; | 592 | ctemp = constraint; |
538 | e = e->next; | 593 | constraint = constraint->next; |
539 | kfree(etmp); | 594 | kfree(ctemp); |
540 | } | 595 | } |
541 | ctemp = constraint; | ||
542 | constraint = constraint->next; | ||
543 | kfree(ctemp); | ||
544 | } | ||
545 | 596 | ||
546 | kfree(cladatum->comkey); | 597 | kfree(cladatum->comkey); |
598 | } | ||
547 | kfree(datum); | 599 | kfree(datum); |
548 | return 0; | 600 | return 0; |
549 | } | 601 | } |
@@ -553,9 +605,11 @@ static int role_destroy(void *key, void *datum, void *p) | |||
553 | struct role_datum *role; | 605 | struct role_datum *role; |
554 | 606 | ||
555 | kfree(key); | 607 | kfree(key); |
556 | role = datum; | 608 | if (datum) { |
557 | ebitmap_destroy(&role->dominates); | 609 | role = datum; |
558 | ebitmap_destroy(&role->types); | 610 | ebitmap_destroy(&role->dominates); |
611 | ebitmap_destroy(&role->types); | ||
612 | } | ||
559 | kfree(datum); | 613 | kfree(datum); |
560 | return 0; | 614 | return 0; |
561 | } | 615 | } |
@@ -572,11 +626,13 @@ static int user_destroy(void *key, void *datum, void *p) | |||
572 | struct user_datum *usrdatum; | 626 | struct user_datum *usrdatum; |
573 | 627 | ||
574 | kfree(key); | 628 | kfree(key); |
575 | usrdatum = datum; | 629 | if (datum) { |
576 | ebitmap_destroy(&usrdatum->roles); | 630 | usrdatum = datum; |
577 | ebitmap_destroy(&usrdatum->range.level[0].cat); | 631 | ebitmap_destroy(&usrdatum->roles); |
578 | ebitmap_destroy(&usrdatum->range.level[1].cat); | 632 | ebitmap_destroy(&usrdatum->range.level[0].cat); |
579 | ebitmap_destroy(&usrdatum->dfltlevel.cat); | 633 | ebitmap_destroy(&usrdatum->range.level[1].cat); |
634 | ebitmap_destroy(&usrdatum->dfltlevel.cat); | ||
635 | } | ||
580 | kfree(datum); | 636 | kfree(datum); |
581 | return 0; | 637 | return 0; |
582 | } | 638 | } |
@@ -586,9 +642,11 @@ static int sens_destroy(void *key, void *datum, void *p) | |||
586 | struct level_datum *levdatum; | 642 | struct level_datum *levdatum; |
587 | 643 | ||
588 | kfree(key); | 644 | kfree(key); |
589 | levdatum = datum; | 645 | if (datum) { |
590 | ebitmap_destroy(&levdatum->level->cat); | 646 | levdatum = datum; |
591 | kfree(levdatum->level); | 647 | ebitmap_destroy(&levdatum->level->cat); |
648 | kfree(levdatum->level); | ||
649 | } | ||
592 | kfree(datum); | 650 | kfree(datum); |
593 | return 0; | 651 | return 0; |
594 | } | 652 | } |
@@ -612,8 +670,22 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | |||
612 | cat_destroy, | 670 | cat_destroy, |
613 | }; | 671 | }; |
614 | 672 | ||
673 | static int range_tr_destroy(void *key, void *datum, void *p) | ||
674 | { | ||
675 | struct mls_range *rt = datum; | ||
676 | kfree(key); | ||
677 | ebitmap_destroy(&rt->level[0].cat); | ||
678 | ebitmap_destroy(&rt->level[1].cat); | ||
679 | kfree(datum); | ||
680 | cond_resched(); | ||
681 | return 0; | ||
682 | } | ||
683 | |||
615 | static void ocontext_destroy(struct ocontext *c, int i) | 684 | static void ocontext_destroy(struct ocontext *c, int i) |
616 | { | 685 | { |
686 | if (!c) | ||
687 | return; | ||
688 | |||
617 | context_destroy(&c->context[0]); | 689 | context_destroy(&c->context[0]); |
618 | context_destroy(&c->context[1]); | 690 | context_destroy(&c->context[1]); |
619 | if (i == OCON_ISID || i == OCON_FS || | 691 | if (i == OCON_ISID || i == OCON_FS || |
@@ -632,7 +704,6 @@ void policydb_destroy(struct policydb *p) | |||
632 | int i; | 704 | int i; |
633 | struct role_allow *ra, *lra = NULL; | 705 | struct role_allow *ra, *lra = NULL; |
634 | struct role_trans *tr, *ltr = NULL; | 706 | struct role_trans *tr, *ltr = NULL; |
635 | struct range_trans *rt, *lrt = NULL; | ||
636 | 707 | ||
637 | for (i = 0; i < SYM_NUM; i++) { | 708 | for (i = 0; i < SYM_NUM; i++) { |
638 | cond_resched(); | 709 | cond_resched(); |
@@ -640,13 +711,16 @@ void policydb_destroy(struct policydb *p) | |||
640 | hashtab_destroy(p->symtab[i].table); | 711 | hashtab_destroy(p->symtab[i].table); |
641 | } | 712 | } |
642 | 713 | ||
643 | for (i = 0; i < SYM_NUM; i++) | 714 | for (i = 0; i < SYM_NUM; i++) { |
644 | kfree(p->sym_val_to_name[i]); | 715 | if (p->sym_val_to_name[i]) |
716 | flex_array_free(p->sym_val_to_name[i]); | ||
717 | } | ||
645 | 718 | ||
646 | kfree(p->class_val_to_struct); | 719 | kfree(p->class_val_to_struct); |
647 | kfree(p->role_val_to_struct); | 720 | kfree(p->role_val_to_struct); |
648 | kfree(p->user_val_to_struct); | 721 | kfree(p->user_val_to_struct); |
649 | kfree(p->type_val_to_struct); | 722 | if (p->type_val_to_struct_array) |
723 | flex_array_free(p->type_val_to_struct_array); | ||
650 | 724 | ||
651 | avtab_destroy(&p->te_avtab); | 725 | avtab_destroy(&p->te_avtab); |
652 | 726 | ||
@@ -693,27 +767,20 @@ void policydb_destroy(struct policydb *p) | |||
693 | } | 767 | } |
694 | kfree(lra); | 768 | kfree(lra); |
695 | 769 | ||
696 | for (rt = p->range_tr; rt; rt = rt->next) { | 770 | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
697 | cond_resched(); | 771 | hashtab_destroy(p->range_tr); |
698 | if (lrt) { | 772 | |
699 | ebitmap_destroy(&lrt->target_range.level[0].cat); | 773 | if (p->type_attr_map_array) { |
700 | ebitmap_destroy(&lrt->target_range.level[1].cat); | 774 | for (i = 0; i < p->p_types.nprim; i++) { |
701 | kfree(lrt); | 775 | struct ebitmap *e; |
702 | } | ||
703 | lrt = rt; | ||
704 | } | ||
705 | if (lrt) { | ||
706 | ebitmap_destroy(&lrt->target_range.level[0].cat); | ||
707 | ebitmap_destroy(&lrt->target_range.level[1].cat); | ||
708 | kfree(lrt); | ||
709 | } | ||
710 | 776 | ||
711 | if (p->type_attr_map) { | 777 | e = flex_array_get(p->type_attr_map_array, i); |
712 | for (i = 0; i < p->p_types.nprim; i++) | 778 | if (!e) |
713 | ebitmap_destroy(&p->type_attr_map[i]); | 779 | continue; |
780 | ebitmap_destroy(e); | ||
781 | } | ||
782 | flex_array_free(p->type_attr_map_array); | ||
714 | } | 783 | } |
715 | kfree(p->type_attr_map); | ||
716 | kfree(p->undefined_perms); | ||
717 | ebitmap_destroy(&p->policycaps); | 784 | ebitmap_destroy(&p->policycaps); |
718 | ebitmap_destroy(&p->permissive_map); | 785 | ebitmap_destroy(&p->permissive_map); |
719 | 786 | ||
@@ -737,19 +804,21 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) | |||
737 | 804 | ||
738 | head = p->ocontexts[OCON_ISID]; | 805 | head = p->ocontexts[OCON_ISID]; |
739 | for (c = head; c; c = c->next) { | 806 | for (c = head; c; c = c->next) { |
807 | rc = -EINVAL; | ||
740 | if (!c->context[0].user) { | 808 | if (!c->context[0].user) { |
741 | printk(KERN_ERR "SELinux: SID %s was never " | 809 | printk(KERN_ERR "SELinux: SID %s was never defined.\n", |
742 | "defined.\n", c->u.name); | 810 | c->u.name); |
743 | rc = -EINVAL; | ||
744 | goto out; | 811 | goto out; |
745 | } | 812 | } |
746 | if (sidtab_insert(s, c->sid[0], &c->context[0])) { | 813 | |
747 | printk(KERN_ERR "SELinux: unable to load initial " | 814 | rc = sidtab_insert(s, c->sid[0], &c->context[0]); |
748 | "SID %s.\n", c->u.name); | 815 | if (rc) { |
749 | rc = -EINVAL; | 816 | printk(KERN_ERR "SELinux: unable to load initial SID %s.\n", |
817 | c->u.name); | ||
750 | goto out; | 818 | goto out; |
751 | } | 819 | } |
752 | } | 820 | } |
821 | rc = 0; | ||
753 | out: | 822 | out: |
754 | return rc; | 823 | return rc; |
755 | } | 824 | } |
@@ -798,8 +867,7 @@ int policydb_context_isvalid(struct policydb *p, struct context *c) | |||
798 | * Role must be authorized for the type. | 867 | * Role must be authorized for the type. |
799 | */ | 868 | */ |
800 | role = p->role_val_to_struct[c->role - 1]; | 869 | role = p->role_val_to_struct[c->role - 1]; |
801 | if (!ebitmap_get_bit(&role->types, | 870 | if (!ebitmap_get_bit(&role->types, c->type - 1)) |
802 | c->type - 1)) | ||
803 | /* role may not be associated with type */ | 871 | /* role may not be associated with type */ |
804 | return 0; | 872 | return 0; |
805 | 873 | ||
@@ -810,8 +878,7 @@ int policydb_context_isvalid(struct policydb *p, struct context *c) | |||
810 | if (!usrdatum) | 878 | if (!usrdatum) |
811 | return 0; | 879 | return 0; |
812 | 880 | ||
813 | if (!ebitmap_get_bit(&usrdatum->roles, | 881 | if (!ebitmap_get_bit(&usrdatum->roles, c->role - 1)) |
814 | c->role - 1)) | ||
815 | /* user may not be associated with role */ | 882 | /* user may not be associated with role */ |
816 | return 0; | 883 | return 0; |
817 | } | 884 | } |
@@ -833,20 +900,22 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) | |||
833 | int rc; | 900 | int rc; |
834 | 901 | ||
835 | rc = next_entry(buf, fp, sizeof(u32)); | 902 | rc = next_entry(buf, fp, sizeof(u32)); |
836 | if (rc < 0) | 903 | if (rc) |
837 | goto out; | 904 | goto out; |
838 | 905 | ||
906 | rc = -EINVAL; | ||
839 | items = le32_to_cpu(buf[0]); | 907 | items = le32_to_cpu(buf[0]); |
840 | if (items > ARRAY_SIZE(buf)) { | 908 | if (items > ARRAY_SIZE(buf)) { |
841 | printk(KERN_ERR "SELinux: mls: range overflow\n"); | 909 | printk(KERN_ERR "SELinux: mls: range overflow\n"); |
842 | rc = -EINVAL; | ||
843 | goto out; | 910 | goto out; |
844 | } | 911 | } |
912 | |||
845 | rc = next_entry(buf, fp, sizeof(u32) * items); | 913 | rc = next_entry(buf, fp, sizeof(u32) * items); |
846 | if (rc < 0) { | 914 | if (rc) { |
847 | printk(KERN_ERR "SELinux: mls: truncated range\n"); | 915 | printk(KERN_ERR "SELinux: mls: truncated range\n"); |
848 | goto out; | 916 | goto out; |
849 | } | 917 | } |
918 | |||
850 | r->level[0].sens = le32_to_cpu(buf[0]); | 919 | r->level[0].sens = le32_to_cpu(buf[0]); |
851 | if (items > 1) | 920 | if (items > 1) |
852 | r->level[1].sens = le32_to_cpu(buf[1]); | 921 | r->level[1].sens = le32_to_cpu(buf[1]); |
@@ -855,15 +924,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) | |||
855 | 924 | ||
856 | rc = ebitmap_read(&r->level[0].cat, fp); | 925 | rc = ebitmap_read(&r->level[0].cat, fp); |
857 | if (rc) { | 926 | if (rc) { |
858 | printk(KERN_ERR "SELinux: mls: error reading low " | 927 | printk(KERN_ERR "SELinux: mls: error reading low categories\n"); |
859 | "categories\n"); | ||
860 | goto out; | 928 | goto out; |
861 | } | 929 | } |
862 | if (items > 1) { | 930 | if (items > 1) { |
863 | rc = ebitmap_read(&r->level[1].cat, fp); | 931 | rc = ebitmap_read(&r->level[1].cat, fp); |
864 | if (rc) { | 932 | if (rc) { |
865 | printk(KERN_ERR "SELinux: mls: error reading high " | 933 | printk(KERN_ERR "SELinux: mls: error reading high categories\n"); |
866 | "categories\n"); | ||
867 | goto bad_high; | 934 | goto bad_high; |
868 | } | 935 | } |
869 | } else { | 936 | } else { |
@@ -874,12 +941,11 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) | |||
874 | } | 941 | } |
875 | } | 942 | } |
876 | 943 | ||
877 | rc = 0; | 944 | return 0; |
878 | out: | ||
879 | return rc; | ||
880 | bad_high: | 945 | bad_high: |
881 | ebitmap_destroy(&r->level[0].cat); | 946 | ebitmap_destroy(&r->level[0].cat); |
882 | goto out; | 947 | out: |
948 | return rc; | ||
883 | } | 949 | } |
884 | 950 | ||
885 | /* | 951 | /* |
@@ -894,7 +960,7 @@ static int context_read_and_validate(struct context *c, | |||
894 | int rc; | 960 | int rc; |
895 | 961 | ||
896 | rc = next_entry(buf, fp, sizeof buf); | 962 | rc = next_entry(buf, fp, sizeof buf); |
897 | if (rc < 0) { | 963 | if (rc) { |
898 | printk(KERN_ERR "SELinux: context truncated\n"); | 964 | printk(KERN_ERR "SELinux: context truncated\n"); |
899 | goto out; | 965 | goto out; |
900 | } | 966 | } |
@@ -902,19 +968,20 @@ static int context_read_and_validate(struct context *c, | |||
902 | c->role = le32_to_cpu(buf[1]); | 968 | c->role = le32_to_cpu(buf[1]); |
903 | c->type = le32_to_cpu(buf[2]); | 969 | c->type = le32_to_cpu(buf[2]); |
904 | if (p->policyvers >= POLICYDB_VERSION_MLS) { | 970 | if (p->policyvers >= POLICYDB_VERSION_MLS) { |
905 | if (mls_read_range_helper(&c->range, fp)) { | 971 | rc = mls_read_range_helper(&c->range, fp); |
906 | printk(KERN_ERR "SELinux: error reading MLS range of " | 972 | if (rc) { |
907 | "context\n"); | 973 | printk(KERN_ERR "SELinux: error reading MLS range of context\n"); |
908 | rc = -EINVAL; | ||
909 | goto out; | 974 | goto out; |
910 | } | 975 | } |
911 | } | 976 | } |
912 | 977 | ||
978 | rc = -EINVAL; | ||
913 | if (!policydb_context_isvalid(p, c)) { | 979 | if (!policydb_context_isvalid(p, c)) { |
914 | printk(KERN_ERR "SELinux: invalid security context\n"); | 980 | printk(KERN_ERR "SELinux: invalid security context\n"); |
915 | context_destroy(c); | 981 | context_destroy(c); |
916 | rc = -EINVAL; | 982 | goto out; |
917 | } | 983 | } |
984 | rc = 0; | ||
918 | out: | 985 | out: |
919 | return rc; | 986 | return rc; |
920 | } | 987 | } |
@@ -933,37 +1000,36 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) | |||
933 | __le32 buf[2]; | 1000 | __le32 buf[2]; |
934 | u32 len; | 1001 | u32 len; |
935 | 1002 | ||
1003 | rc = -ENOMEM; | ||
936 | perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL); | 1004 | perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL); |
937 | if (!perdatum) { | 1005 | if (!perdatum) |
938 | rc = -ENOMEM; | 1006 | goto bad; |
939 | goto out; | ||
940 | } | ||
941 | 1007 | ||
942 | rc = next_entry(buf, fp, sizeof buf); | 1008 | rc = next_entry(buf, fp, sizeof buf); |
943 | if (rc < 0) | 1009 | if (rc) |
944 | goto bad; | 1010 | goto bad; |
945 | 1011 | ||
946 | len = le32_to_cpu(buf[0]); | 1012 | len = le32_to_cpu(buf[0]); |
947 | perdatum->value = le32_to_cpu(buf[1]); | 1013 | perdatum->value = le32_to_cpu(buf[1]); |
948 | 1014 | ||
1015 | rc = -ENOMEM; | ||
949 | key = kmalloc(len + 1, GFP_KERNEL); | 1016 | key = kmalloc(len + 1, GFP_KERNEL); |
950 | if (!key) { | 1017 | if (!key) |
951 | rc = -ENOMEM; | ||
952 | goto bad; | 1018 | goto bad; |
953 | } | 1019 | |
954 | rc = next_entry(key, fp, len); | 1020 | rc = next_entry(key, fp, len); |
955 | if (rc < 0) | 1021 | if (rc) |
956 | goto bad; | 1022 | goto bad; |
957 | key[len] = '\0'; | 1023 | key[len] = '\0'; |
958 | 1024 | ||
959 | rc = hashtab_insert(h, key, perdatum); | 1025 | rc = hashtab_insert(h, key, perdatum); |
960 | if (rc) | 1026 | if (rc) |
961 | goto bad; | 1027 | goto bad; |
962 | out: | 1028 | |
963 | return rc; | 1029 | return 0; |
964 | bad: | 1030 | bad: |
965 | perm_destroy(key, perdatum, NULL); | 1031 | perm_destroy(key, perdatum, NULL); |
966 | goto out; | 1032 | return rc; |
967 | } | 1033 | } |
968 | 1034 | ||
969 | static int common_read(struct policydb *p, struct hashtab *h, void *fp) | 1035 | static int common_read(struct policydb *p, struct hashtab *h, void *fp) |
@@ -974,14 +1040,13 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
974 | u32 len, nel; | 1040 | u32 len, nel; |
975 | int i, rc; | 1041 | int i, rc; |
976 | 1042 | ||
1043 | rc = -ENOMEM; | ||
977 | comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL); | 1044 | comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL); |
978 | if (!comdatum) { | 1045 | if (!comdatum) |
979 | rc = -ENOMEM; | 1046 | goto bad; |
980 | goto out; | ||
981 | } | ||
982 | 1047 | ||
983 | rc = next_entry(buf, fp, sizeof buf); | 1048 | rc = next_entry(buf, fp, sizeof buf); |
984 | if (rc < 0) | 1049 | if (rc) |
985 | goto bad; | 1050 | goto bad; |
986 | 1051 | ||
987 | len = le32_to_cpu(buf[0]); | 1052 | len = le32_to_cpu(buf[0]); |
@@ -993,13 +1058,13 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
993 | comdatum->permissions.nprim = le32_to_cpu(buf[2]); | 1058 | comdatum->permissions.nprim = le32_to_cpu(buf[2]); |
994 | nel = le32_to_cpu(buf[3]); | 1059 | nel = le32_to_cpu(buf[3]); |
995 | 1060 | ||
1061 | rc = -ENOMEM; | ||
996 | key = kmalloc(len + 1, GFP_KERNEL); | 1062 | key = kmalloc(len + 1, GFP_KERNEL); |
997 | if (!key) { | 1063 | if (!key) |
998 | rc = -ENOMEM; | ||
999 | goto bad; | 1064 | goto bad; |
1000 | } | 1065 | |
1001 | rc = next_entry(key, fp, len); | 1066 | rc = next_entry(key, fp, len); |
1002 | if (rc < 0) | 1067 | if (rc) |
1003 | goto bad; | 1068 | goto bad; |
1004 | key[len] = '\0'; | 1069 | key[len] = '\0'; |
1005 | 1070 | ||
@@ -1012,11 +1077,10 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1012 | rc = hashtab_insert(h, key, comdatum); | 1077 | rc = hashtab_insert(h, key, comdatum); |
1013 | if (rc) | 1078 | if (rc) |
1014 | goto bad; | 1079 | goto bad; |
1015 | out: | 1080 | return 0; |
1016 | return rc; | ||
1017 | bad: | 1081 | bad: |
1018 | common_destroy(key, comdatum, NULL); | 1082 | common_destroy(key, comdatum, NULL); |
1019 | goto out; | 1083 | return rc; |
1020 | } | 1084 | } |
1021 | 1085 | ||
1022 | static int read_cons_helper(struct constraint_node **nodep, int ncons, | 1086 | static int read_cons_helper(struct constraint_node **nodep, int ncons, |
@@ -1040,7 +1104,7 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, | |||
1040 | *nodep = c; | 1104 | *nodep = c; |
1041 | 1105 | ||
1042 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | 1106 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); |
1043 | if (rc < 0) | 1107 | if (rc) |
1044 | return rc; | 1108 | return rc; |
1045 | c->permissions = le32_to_cpu(buf[0]); | 1109 | c->permissions = le32_to_cpu(buf[0]); |
1046 | nexpr = le32_to_cpu(buf[1]); | 1110 | nexpr = le32_to_cpu(buf[1]); |
@@ -1057,7 +1121,7 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, | |||
1057 | c->expr = e; | 1121 | c->expr = e; |
1058 | 1122 | ||
1059 | rc = next_entry(buf, fp, (sizeof(u32) * 3)); | 1123 | rc = next_entry(buf, fp, (sizeof(u32) * 3)); |
1060 | if (rc < 0) | 1124 | if (rc) |
1061 | return rc; | 1125 | return rc; |
1062 | e->expr_type = le32_to_cpu(buf[0]); | 1126 | e->expr_type = le32_to_cpu(buf[0]); |
1063 | e->attr = le32_to_cpu(buf[1]); | 1127 | e->attr = le32_to_cpu(buf[1]); |
@@ -1085,8 +1149,9 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, | |||
1085 | if (depth == (CEXPR_MAXDEPTH - 1)) | 1149 | if (depth == (CEXPR_MAXDEPTH - 1)) |
1086 | return -EINVAL; | 1150 | return -EINVAL; |
1087 | depth++; | 1151 | depth++; |
1088 | if (ebitmap_read(&e->names, fp)) | 1152 | rc = ebitmap_read(&e->names, fp); |
1089 | return -EINVAL; | 1153 | if (rc) |
1154 | return rc; | ||
1090 | break; | 1155 | break; |
1091 | default: | 1156 | default: |
1092 | return -EINVAL; | 1157 | return -EINVAL; |
@@ -1109,14 +1174,13 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1109 | u32 len, len2, ncons, nel; | 1174 | u32 len, len2, ncons, nel; |
1110 | int i, rc; | 1175 | int i, rc; |
1111 | 1176 | ||
1177 | rc = -ENOMEM; | ||
1112 | cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL); | 1178 | cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL); |
1113 | if (!cladatum) { | 1179 | if (!cladatum) |
1114 | rc = -ENOMEM; | 1180 | goto bad; |
1115 | goto out; | ||
1116 | } | ||
1117 | 1181 | ||
1118 | rc = next_entry(buf, fp, sizeof(u32)*6); | 1182 | rc = next_entry(buf, fp, sizeof(u32)*6); |
1119 | if (rc < 0) | 1183 | if (rc) |
1120 | goto bad; | 1184 | goto bad; |
1121 | 1185 | ||
1122 | len = le32_to_cpu(buf[0]); | 1186 | len = le32_to_cpu(buf[0]); |
@@ -1131,33 +1195,30 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1131 | 1195 | ||
1132 | ncons = le32_to_cpu(buf[5]); | 1196 | ncons = le32_to_cpu(buf[5]); |
1133 | 1197 | ||
1198 | rc = -ENOMEM; | ||
1134 | key = kmalloc(len + 1, GFP_KERNEL); | 1199 | key = kmalloc(len + 1, GFP_KERNEL); |
1135 | if (!key) { | 1200 | if (!key) |
1136 | rc = -ENOMEM; | ||
1137 | goto bad; | 1201 | goto bad; |
1138 | } | 1202 | |
1139 | rc = next_entry(key, fp, len); | 1203 | rc = next_entry(key, fp, len); |
1140 | if (rc < 0) | 1204 | if (rc) |
1141 | goto bad; | 1205 | goto bad; |
1142 | key[len] = '\0'; | 1206 | key[len] = '\0'; |
1143 | 1207 | ||
1144 | if (len2) { | 1208 | if (len2) { |
1209 | rc = -ENOMEM; | ||
1145 | cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); | 1210 | cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); |
1146 | if (!cladatum->comkey) { | 1211 | if (!cladatum->comkey) |
1147 | rc = -ENOMEM; | ||
1148 | goto bad; | 1212 | goto bad; |
1149 | } | ||
1150 | rc = next_entry(cladatum->comkey, fp, len2); | 1213 | rc = next_entry(cladatum->comkey, fp, len2); |
1151 | if (rc < 0) | 1214 | if (rc) |
1152 | goto bad; | 1215 | goto bad; |
1153 | cladatum->comkey[len2] = '\0'; | 1216 | cladatum->comkey[len2] = '\0'; |
1154 | 1217 | ||
1155 | cladatum->comdatum = hashtab_search(p->p_commons.table, | 1218 | rc = -EINVAL; |
1156 | cladatum->comkey); | 1219 | cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); |
1157 | if (!cladatum->comdatum) { | 1220 | if (!cladatum->comdatum) { |
1158 | printk(KERN_ERR "SELinux: unknown common %s\n", | 1221 | printk(KERN_ERR "SELinux: unknown common %s\n", cladatum->comkey); |
1159 | cladatum->comkey); | ||
1160 | rc = -EINVAL; | ||
1161 | goto bad; | 1222 | goto bad; |
1162 | } | 1223 | } |
1163 | } | 1224 | } |
@@ -1174,7 +1235,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1174 | if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) { | 1235 | if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) { |
1175 | /* grab the validatetrans rules */ | 1236 | /* grab the validatetrans rules */ |
1176 | rc = next_entry(buf, fp, sizeof(u32)); | 1237 | rc = next_entry(buf, fp, sizeof(u32)); |
1177 | if (rc < 0) | 1238 | if (rc) |
1178 | goto bad; | 1239 | goto bad; |
1179 | ncons = le32_to_cpu(buf[0]); | 1240 | ncons = le32_to_cpu(buf[0]); |
1180 | rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp); | 1241 | rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp); |
@@ -1186,12 +1247,10 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1186 | if (rc) | 1247 | if (rc) |
1187 | goto bad; | 1248 | goto bad; |
1188 | 1249 | ||
1189 | rc = 0; | 1250 | return 0; |
1190 | out: | ||
1191 | return rc; | ||
1192 | bad: | 1251 | bad: |
1193 | cls_destroy(key, cladatum, NULL); | 1252 | cls_destroy(key, cladatum, NULL); |
1194 | goto out; | 1253 | return rc; |
1195 | } | 1254 | } |
1196 | 1255 | ||
1197 | static int role_read(struct policydb *p, struct hashtab *h, void *fp) | 1256 | static int role_read(struct policydb *p, struct hashtab *h, void *fp) |
@@ -1202,17 +1261,16 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1202 | __le32 buf[3]; | 1261 | __le32 buf[3]; |
1203 | u32 len; | 1262 | u32 len; |
1204 | 1263 | ||
1264 | rc = -ENOMEM; | ||
1205 | role = kzalloc(sizeof(*role), GFP_KERNEL); | 1265 | role = kzalloc(sizeof(*role), GFP_KERNEL); |
1206 | if (!role) { | 1266 | if (!role) |
1207 | rc = -ENOMEM; | 1267 | goto bad; |
1208 | goto out; | ||
1209 | } | ||
1210 | 1268 | ||
1211 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1269 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
1212 | to_read = 3; | 1270 | to_read = 3; |
1213 | 1271 | ||
1214 | rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); | 1272 | rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); |
1215 | if (rc < 0) | 1273 | if (rc) |
1216 | goto bad; | 1274 | goto bad; |
1217 | 1275 | ||
1218 | len = le32_to_cpu(buf[0]); | 1276 | len = le32_to_cpu(buf[0]); |
@@ -1220,13 +1278,13 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1220 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1278 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
1221 | role->bounds = le32_to_cpu(buf[2]); | 1279 | role->bounds = le32_to_cpu(buf[2]); |
1222 | 1280 | ||
1281 | rc = -ENOMEM; | ||
1223 | key = kmalloc(len + 1, GFP_KERNEL); | 1282 | key = kmalloc(len + 1, GFP_KERNEL); |
1224 | if (!key) { | 1283 | if (!key) |
1225 | rc = -ENOMEM; | ||
1226 | goto bad; | 1284 | goto bad; |
1227 | } | 1285 | |
1228 | rc = next_entry(key, fp, len); | 1286 | rc = next_entry(key, fp, len); |
1229 | if (rc < 0) | 1287 | if (rc) |
1230 | goto bad; | 1288 | goto bad; |
1231 | key[len] = '\0'; | 1289 | key[len] = '\0'; |
1232 | 1290 | ||
@@ -1239,10 +1297,10 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1239 | goto bad; | 1297 | goto bad; |
1240 | 1298 | ||
1241 | if (strcmp(key, OBJECT_R) == 0) { | 1299 | if (strcmp(key, OBJECT_R) == 0) { |
1300 | rc = -EINVAL; | ||
1242 | if (role->value != OBJECT_R_VAL) { | 1301 | if (role->value != OBJECT_R_VAL) { |
1243 | printk(KERN_ERR "SELinux: Role %s has wrong value %d\n", | 1302 | printk(KERN_ERR "SELinux: Role %s has wrong value %d\n", |
1244 | OBJECT_R, role->value); | 1303 | OBJECT_R, role->value); |
1245 | rc = -EINVAL; | ||
1246 | goto bad; | 1304 | goto bad; |
1247 | } | 1305 | } |
1248 | rc = 0; | 1306 | rc = 0; |
@@ -1252,11 +1310,10 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1252 | rc = hashtab_insert(h, key, role); | 1310 | rc = hashtab_insert(h, key, role); |
1253 | if (rc) | 1311 | if (rc) |
1254 | goto bad; | 1312 | goto bad; |
1255 | out: | 1313 | return 0; |
1256 | return rc; | ||
1257 | bad: | 1314 | bad: |
1258 | role_destroy(key, role, NULL); | 1315 | role_destroy(key, role, NULL); |
1259 | goto out; | 1316 | return rc; |
1260 | } | 1317 | } |
1261 | 1318 | ||
1262 | static int type_read(struct policydb *p, struct hashtab *h, void *fp) | 1319 | static int type_read(struct policydb *p, struct hashtab *h, void *fp) |
@@ -1267,17 +1324,16 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1267 | __le32 buf[4]; | 1324 | __le32 buf[4]; |
1268 | u32 len; | 1325 | u32 len; |
1269 | 1326 | ||
1327 | rc = -ENOMEM; | ||
1270 | typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); | 1328 | typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); |
1271 | if (!typdatum) { | 1329 | if (!typdatum) |
1272 | rc = -ENOMEM; | 1330 | goto bad; |
1273 | return rc; | ||
1274 | } | ||
1275 | 1331 | ||
1276 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1332 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
1277 | to_read = 4; | 1333 | to_read = 4; |
1278 | 1334 | ||
1279 | rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); | 1335 | rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); |
1280 | if (rc < 0) | 1336 | if (rc) |
1281 | goto bad; | 1337 | goto bad; |
1282 | 1338 | ||
1283 | len = le32_to_cpu(buf[0]); | 1339 | len = le32_to_cpu(buf[0]); |
@@ -1295,24 +1351,22 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1295 | typdatum->primary = le32_to_cpu(buf[2]); | 1351 | typdatum->primary = le32_to_cpu(buf[2]); |
1296 | } | 1352 | } |
1297 | 1353 | ||
1354 | rc = -ENOMEM; | ||
1298 | key = kmalloc(len + 1, GFP_KERNEL); | 1355 | key = kmalloc(len + 1, GFP_KERNEL); |
1299 | if (!key) { | 1356 | if (!key) |
1300 | rc = -ENOMEM; | ||
1301 | goto bad; | 1357 | goto bad; |
1302 | } | ||
1303 | rc = next_entry(key, fp, len); | 1358 | rc = next_entry(key, fp, len); |
1304 | if (rc < 0) | 1359 | if (rc) |
1305 | goto bad; | 1360 | goto bad; |
1306 | key[len] = '\0'; | 1361 | key[len] = '\0'; |
1307 | 1362 | ||
1308 | rc = hashtab_insert(h, key, typdatum); | 1363 | rc = hashtab_insert(h, key, typdatum); |
1309 | if (rc) | 1364 | if (rc) |
1310 | goto bad; | 1365 | goto bad; |
1311 | out: | 1366 | return 0; |
1312 | return rc; | ||
1313 | bad: | 1367 | bad: |
1314 | type_destroy(key, typdatum, NULL); | 1368 | type_destroy(key, typdatum, NULL); |
1315 | goto out; | 1369 | return rc; |
1316 | } | 1370 | } |
1317 | 1371 | ||
1318 | 1372 | ||
@@ -1328,22 +1382,18 @@ static int mls_read_level(struct mls_level *lp, void *fp) | |||
1328 | memset(lp, 0, sizeof(*lp)); | 1382 | memset(lp, 0, sizeof(*lp)); |
1329 | 1383 | ||
1330 | rc = next_entry(buf, fp, sizeof buf); | 1384 | rc = next_entry(buf, fp, sizeof buf); |
1331 | if (rc < 0) { | 1385 | if (rc) { |
1332 | printk(KERN_ERR "SELinux: mls: truncated level\n"); | 1386 | printk(KERN_ERR "SELinux: mls: truncated level\n"); |
1333 | goto bad; | 1387 | return rc; |
1334 | } | 1388 | } |
1335 | lp->sens = le32_to_cpu(buf[0]); | 1389 | lp->sens = le32_to_cpu(buf[0]); |
1336 | 1390 | ||
1337 | if (ebitmap_read(&lp->cat, fp)) { | 1391 | rc = ebitmap_read(&lp->cat, fp); |
1338 | printk(KERN_ERR "SELinux: mls: error reading level " | 1392 | if (rc) { |
1339 | "categories\n"); | 1393 | printk(KERN_ERR "SELinux: mls: error reading level categories\n"); |
1340 | goto bad; | 1394 | return rc; |
1341 | } | 1395 | } |
1342 | |||
1343 | return 0; | 1396 | return 0; |
1344 | |||
1345 | bad: | ||
1346 | return -EINVAL; | ||
1347 | } | 1397 | } |
1348 | 1398 | ||
1349 | static int user_read(struct policydb *p, struct hashtab *h, void *fp) | 1399 | static int user_read(struct policydb *p, struct hashtab *h, void *fp) |
@@ -1354,17 +1404,16 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1354 | __le32 buf[3]; | 1404 | __le32 buf[3]; |
1355 | u32 len; | 1405 | u32 len; |
1356 | 1406 | ||
1407 | rc = -ENOMEM; | ||
1357 | usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); | 1408 | usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); |
1358 | if (!usrdatum) { | 1409 | if (!usrdatum) |
1359 | rc = -ENOMEM; | 1410 | goto bad; |
1360 | goto out; | ||
1361 | } | ||
1362 | 1411 | ||
1363 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1412 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
1364 | to_read = 3; | 1413 | to_read = 3; |
1365 | 1414 | ||
1366 | rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); | 1415 | rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); |
1367 | if (rc < 0) | 1416 | if (rc) |
1368 | goto bad; | 1417 | goto bad; |
1369 | 1418 | ||
1370 | len = le32_to_cpu(buf[0]); | 1419 | len = le32_to_cpu(buf[0]); |
@@ -1372,13 +1421,12 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1372 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | 1421 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) |
1373 | usrdatum->bounds = le32_to_cpu(buf[2]); | 1422 | usrdatum->bounds = le32_to_cpu(buf[2]); |
1374 | 1423 | ||
1424 | rc = -ENOMEM; | ||
1375 | key = kmalloc(len + 1, GFP_KERNEL); | 1425 | key = kmalloc(len + 1, GFP_KERNEL); |
1376 | if (!key) { | 1426 | if (!key) |
1377 | rc = -ENOMEM; | ||
1378 | goto bad; | 1427 | goto bad; |
1379 | } | ||
1380 | rc = next_entry(key, fp, len); | 1428 | rc = next_entry(key, fp, len); |
1381 | if (rc < 0) | 1429 | if (rc) |
1382 | goto bad; | 1430 | goto bad; |
1383 | key[len] = '\0'; | 1431 | key[len] = '\0'; |
1384 | 1432 | ||
@@ -1398,11 +1446,10 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1398 | rc = hashtab_insert(h, key, usrdatum); | 1446 | rc = hashtab_insert(h, key, usrdatum); |
1399 | if (rc) | 1447 | if (rc) |
1400 | goto bad; | 1448 | goto bad; |
1401 | out: | 1449 | return 0; |
1402 | return rc; | ||
1403 | bad: | 1450 | bad: |
1404 | user_destroy(key, usrdatum, NULL); | 1451 | user_destroy(key, usrdatum, NULL); |
1405 | goto out; | 1452 | return rc; |
1406 | } | 1453 | } |
1407 | 1454 | ||
1408 | static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | 1455 | static int sens_read(struct policydb *p, struct hashtab *h, void *fp) |
@@ -1413,47 +1460,43 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1413 | __le32 buf[2]; | 1460 | __le32 buf[2]; |
1414 | u32 len; | 1461 | u32 len; |
1415 | 1462 | ||
1463 | rc = -ENOMEM; | ||
1416 | levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); | 1464 | levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); |
1417 | if (!levdatum) { | 1465 | if (!levdatum) |
1418 | rc = -ENOMEM; | 1466 | goto bad; |
1419 | goto out; | ||
1420 | } | ||
1421 | 1467 | ||
1422 | rc = next_entry(buf, fp, sizeof buf); | 1468 | rc = next_entry(buf, fp, sizeof buf); |
1423 | if (rc < 0) | 1469 | if (rc) |
1424 | goto bad; | 1470 | goto bad; |
1425 | 1471 | ||
1426 | len = le32_to_cpu(buf[0]); | 1472 | len = le32_to_cpu(buf[0]); |
1427 | levdatum->isalias = le32_to_cpu(buf[1]); | 1473 | levdatum->isalias = le32_to_cpu(buf[1]); |
1428 | 1474 | ||
1475 | rc = -ENOMEM; | ||
1429 | key = kmalloc(len + 1, GFP_ATOMIC); | 1476 | key = kmalloc(len + 1, GFP_ATOMIC); |
1430 | if (!key) { | 1477 | if (!key) |
1431 | rc = -ENOMEM; | ||
1432 | goto bad; | 1478 | goto bad; |
1433 | } | ||
1434 | rc = next_entry(key, fp, len); | 1479 | rc = next_entry(key, fp, len); |
1435 | if (rc < 0) | 1480 | if (rc) |
1436 | goto bad; | 1481 | goto bad; |
1437 | key[len] = '\0'; | 1482 | key[len] = '\0'; |
1438 | 1483 | ||
1484 | rc = -ENOMEM; | ||
1439 | levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); | 1485 | levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); |
1440 | if (!levdatum->level) { | 1486 | if (!levdatum->level) |
1441 | rc = -ENOMEM; | ||
1442 | goto bad; | 1487 | goto bad; |
1443 | } | 1488 | |
1444 | if (mls_read_level(levdatum->level, fp)) { | 1489 | rc = mls_read_level(levdatum->level, fp); |
1445 | rc = -EINVAL; | 1490 | if (rc) |
1446 | goto bad; | 1491 | goto bad; |
1447 | } | ||
1448 | 1492 | ||
1449 | rc = hashtab_insert(h, key, levdatum); | 1493 | rc = hashtab_insert(h, key, levdatum); |
1450 | if (rc) | 1494 | if (rc) |
1451 | goto bad; | 1495 | goto bad; |
1452 | out: | 1496 | return 0; |
1453 | return rc; | ||
1454 | bad: | 1497 | bad: |
1455 | sens_destroy(key, levdatum, NULL); | 1498 | sens_destroy(key, levdatum, NULL); |
1456 | goto out; | 1499 | return rc; |
1457 | } | 1500 | } |
1458 | 1501 | ||
1459 | static int cat_read(struct policydb *p, struct hashtab *h, void *fp) | 1502 | static int cat_read(struct policydb *p, struct hashtab *h, void *fp) |
@@ -1464,39 +1507,35 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1464 | __le32 buf[3]; | 1507 | __le32 buf[3]; |
1465 | u32 len; | 1508 | u32 len; |
1466 | 1509 | ||
1510 | rc = -ENOMEM; | ||
1467 | catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); | 1511 | catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); |
1468 | if (!catdatum) { | 1512 | if (!catdatum) |
1469 | rc = -ENOMEM; | 1513 | goto bad; |
1470 | goto out; | ||
1471 | } | ||
1472 | 1514 | ||
1473 | rc = next_entry(buf, fp, sizeof buf); | 1515 | rc = next_entry(buf, fp, sizeof buf); |
1474 | if (rc < 0) | 1516 | if (rc) |
1475 | goto bad; | 1517 | goto bad; |
1476 | 1518 | ||
1477 | len = le32_to_cpu(buf[0]); | 1519 | len = le32_to_cpu(buf[0]); |
1478 | catdatum->value = le32_to_cpu(buf[1]); | 1520 | catdatum->value = le32_to_cpu(buf[1]); |
1479 | catdatum->isalias = le32_to_cpu(buf[2]); | 1521 | catdatum->isalias = le32_to_cpu(buf[2]); |
1480 | 1522 | ||
1523 | rc = -ENOMEM; | ||
1481 | key = kmalloc(len + 1, GFP_ATOMIC); | 1524 | key = kmalloc(len + 1, GFP_ATOMIC); |
1482 | if (!key) { | 1525 | if (!key) |
1483 | rc = -ENOMEM; | ||
1484 | goto bad; | 1526 | goto bad; |
1485 | } | ||
1486 | rc = next_entry(key, fp, len); | 1527 | rc = next_entry(key, fp, len); |
1487 | if (rc < 0) | 1528 | if (rc) |
1488 | goto bad; | 1529 | goto bad; |
1489 | key[len] = '\0'; | 1530 | key[len] = '\0'; |
1490 | 1531 | ||
1491 | rc = hashtab_insert(h, key, catdatum); | 1532 | rc = hashtab_insert(h, key, catdatum); |
1492 | if (rc) | 1533 | if (rc) |
1493 | goto bad; | 1534 | goto bad; |
1494 | out: | 1535 | return 0; |
1495 | return rc; | ||
1496 | |||
1497 | bad: | 1536 | bad: |
1498 | cat_destroy(key, catdatum, NULL); | 1537 | cat_destroy(key, catdatum, NULL); |
1499 | goto out; | 1538 | return rc; |
1500 | } | 1539 | } |
1501 | 1540 | ||
1502 | static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) = | 1541 | static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) = |
@@ -1537,9 +1576,9 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap) | |||
1537 | printk(KERN_ERR | 1576 | printk(KERN_ERR |
1538 | "SELinux: boundary violated policy: " | 1577 | "SELinux: boundary violated policy: " |
1539 | "user=%s role=%s bounds=%s\n", | 1578 | "user=%s role=%s bounds=%s\n", |
1540 | p->p_user_val_to_name[user->value - 1], | 1579 | sym_name(p, SYM_USERS, user->value - 1), |
1541 | p->p_role_val_to_name[bit], | 1580 | sym_name(p, SYM_ROLES, bit), |
1542 | p->p_user_val_to_name[upper->value - 1]); | 1581 | sym_name(p, SYM_USERS, upper->value - 1)); |
1543 | 1582 | ||
1544 | return -EINVAL; | 1583 | return -EINVAL; |
1545 | } | 1584 | } |
@@ -1574,9 +1613,9 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap) | |||
1574 | printk(KERN_ERR | 1613 | printk(KERN_ERR |
1575 | "SELinux: boundary violated policy: " | 1614 | "SELinux: boundary violated policy: " |
1576 | "role=%s type=%s bounds=%s\n", | 1615 | "role=%s type=%s bounds=%s\n", |
1577 | p->p_role_val_to_name[role->value - 1], | 1616 | sym_name(p, SYM_ROLES, role->value - 1), |
1578 | p->p_type_val_to_name[bit], | 1617 | sym_name(p, SYM_TYPES, bit), |
1579 | p->p_role_val_to_name[upper->value - 1]); | 1618 | sym_name(p, SYM_ROLES, upper->value - 1)); |
1580 | 1619 | ||
1581 | return -EINVAL; | 1620 | return -EINVAL; |
1582 | } | 1621 | } |
@@ -1587,11 +1626,11 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap) | |||
1587 | 1626 | ||
1588 | static int type_bounds_sanity_check(void *key, void *datum, void *datap) | 1627 | static int type_bounds_sanity_check(void *key, void *datum, void *datap) |
1589 | { | 1628 | { |
1590 | struct type_datum *upper, *type; | 1629 | struct type_datum *upper; |
1591 | struct policydb *p = datap; | 1630 | struct policydb *p = datap; |
1592 | int depth = 0; | 1631 | int depth = 0; |
1593 | 1632 | ||
1594 | upper = type = datum; | 1633 | upper = datum; |
1595 | while (upper->bounds) { | 1634 | while (upper->bounds) { |
1596 | if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { | 1635 | if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { |
1597 | printk(KERN_ERR "SELinux: type %s: " | 1636 | printk(KERN_ERR "SELinux: type %s: " |
@@ -1600,12 +1639,15 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) | |||
1600 | return -EINVAL; | 1639 | return -EINVAL; |
1601 | } | 1640 | } |
1602 | 1641 | ||
1603 | upper = p->type_val_to_struct[upper->bounds - 1]; | 1642 | upper = flex_array_get_ptr(p->type_val_to_struct_array, |
1643 | upper->bounds - 1); | ||
1644 | BUG_ON(!upper); | ||
1645 | |||
1604 | if (upper->attribute) { | 1646 | if (upper->attribute) { |
1605 | printk(KERN_ERR "SELinux: type %s: " | 1647 | printk(KERN_ERR "SELinux: type %s: " |
1606 | "bounded by attribute %s", | 1648 | "bounded by attribute %s", |
1607 | (char *) key, | 1649 | (char *) key, |
1608 | p->p_type_val_to_name[upper->value - 1]); | 1650 | sym_name(p, SYM_TYPES, upper->value - 1)); |
1609 | return -EINVAL; | 1651 | return -EINVAL; |
1610 | } | 1652 | } |
1611 | } | 1653 | } |
@@ -1640,6 +1682,367 @@ static int policydb_bounds_sanity_check(struct policydb *p) | |||
1640 | 1682 | ||
1641 | extern int ss_initialized; | 1683 | extern int ss_initialized; |
1642 | 1684 | ||
1685 | u16 string_to_security_class(struct policydb *p, const char *name) | ||
1686 | { | ||
1687 | struct class_datum *cladatum; | ||
1688 | |||
1689 | cladatum = hashtab_search(p->p_classes.table, name); | ||
1690 | if (!cladatum) | ||
1691 | return 0; | ||
1692 | |||
1693 | return cladatum->value; | ||
1694 | } | ||
1695 | |||
1696 | u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) | ||
1697 | { | ||
1698 | struct class_datum *cladatum; | ||
1699 | struct perm_datum *perdatum = NULL; | ||
1700 | struct common_datum *comdatum; | ||
1701 | |||
1702 | if (!tclass || tclass > p->p_classes.nprim) | ||
1703 | return 0; | ||
1704 | |||
1705 | cladatum = p->class_val_to_struct[tclass-1]; | ||
1706 | comdatum = cladatum->comdatum; | ||
1707 | if (comdatum) | ||
1708 | perdatum = hashtab_search(comdatum->permissions.table, | ||
1709 | name); | ||
1710 | if (!perdatum) | ||
1711 | perdatum = hashtab_search(cladatum->permissions.table, | ||
1712 | name); | ||
1713 | if (!perdatum) | ||
1714 | return 0; | ||
1715 | |||
1716 | return 1U << (perdatum->value-1); | ||
1717 | } | ||
1718 | |||
1719 | static int range_read(struct policydb *p, void *fp) | ||
1720 | { | ||
1721 | struct range_trans *rt = NULL; | ||
1722 | struct mls_range *r = NULL; | ||
1723 | int i, rc; | ||
1724 | __le32 buf[2]; | ||
1725 | u32 nel; | ||
1726 | |||
1727 | if (p->policyvers < POLICYDB_VERSION_MLS) | ||
1728 | return 0; | ||
1729 | |||
1730 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1731 | if (rc) | ||
1732 | goto out; | ||
1733 | |||
1734 | nel = le32_to_cpu(buf[0]); | ||
1735 | for (i = 0; i < nel; i++) { | ||
1736 | rc = -ENOMEM; | ||
1737 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | ||
1738 | if (!rt) | ||
1739 | goto out; | ||
1740 | |||
1741 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | ||
1742 | if (rc) | ||
1743 | goto out; | ||
1744 | |||
1745 | rt->source_type = le32_to_cpu(buf[0]); | ||
1746 | rt->target_type = le32_to_cpu(buf[1]); | ||
1747 | if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) { | ||
1748 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1749 | if (rc) | ||
1750 | goto out; | ||
1751 | rt->target_class = le32_to_cpu(buf[0]); | ||
1752 | } else | ||
1753 | rt->target_class = p->process_class; | ||
1754 | |||
1755 | rc = -EINVAL; | ||
1756 | if (!policydb_type_isvalid(p, rt->source_type) || | ||
1757 | !policydb_type_isvalid(p, rt->target_type) || | ||
1758 | !policydb_class_isvalid(p, rt->target_class)) | ||
1759 | goto out; | ||
1760 | |||
1761 | rc = -ENOMEM; | ||
1762 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
1763 | if (!r) | ||
1764 | goto out; | ||
1765 | |||
1766 | rc = mls_read_range_helper(r, fp); | ||
1767 | if (rc) | ||
1768 | goto out; | ||
1769 | |||
1770 | rc = -EINVAL; | ||
1771 | if (!mls_range_isvalid(p, r)) { | ||
1772 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | ||
1773 | goto out; | ||
1774 | } | ||
1775 | |||
1776 | rc = hashtab_insert(p->range_tr, rt, r); | ||
1777 | if (rc) | ||
1778 | goto out; | ||
1779 | |||
1780 | rt = NULL; | ||
1781 | r = NULL; | ||
1782 | } | ||
1783 | rangetr_hash_eval(p->range_tr); | ||
1784 | rc = 0; | ||
1785 | out: | ||
1786 | kfree(rt); | ||
1787 | kfree(r); | ||
1788 | return rc; | ||
1789 | } | ||
1790 | |||
1791 | static int genfs_read(struct policydb *p, void *fp) | ||
1792 | { | ||
1793 | int i, j, rc; | ||
1794 | u32 nel, nel2, len, len2; | ||
1795 | __le32 buf[1]; | ||
1796 | struct ocontext *l, *c; | ||
1797 | struct ocontext *newc = NULL; | ||
1798 | struct genfs *genfs_p, *genfs; | ||
1799 | struct genfs *newgenfs = NULL; | ||
1800 | |||
1801 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1802 | if (rc) | ||
1803 | goto out; | ||
1804 | nel = le32_to_cpu(buf[0]); | ||
1805 | |||
1806 | for (i = 0; i < nel; i++) { | ||
1807 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1808 | if (rc) | ||
1809 | goto out; | ||
1810 | len = le32_to_cpu(buf[0]); | ||
1811 | |||
1812 | rc = -ENOMEM; | ||
1813 | newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); | ||
1814 | if (!newgenfs) | ||
1815 | goto out; | ||
1816 | |||
1817 | rc = -ENOMEM; | ||
1818 | newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); | ||
1819 | if (!newgenfs->fstype) | ||
1820 | goto out; | ||
1821 | |||
1822 | rc = next_entry(newgenfs->fstype, fp, len); | ||
1823 | if (rc) | ||
1824 | goto out; | ||
1825 | |||
1826 | newgenfs->fstype[len] = 0; | ||
1827 | |||
1828 | for (genfs_p = NULL, genfs = p->genfs; genfs; | ||
1829 | genfs_p = genfs, genfs = genfs->next) { | ||
1830 | rc = -EINVAL; | ||
1831 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { | ||
1832 | printk(KERN_ERR "SELinux: dup genfs fstype %s\n", | ||
1833 | newgenfs->fstype); | ||
1834 | goto out; | ||
1835 | } | ||
1836 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) | ||
1837 | break; | ||
1838 | } | ||
1839 | newgenfs->next = genfs; | ||
1840 | if (genfs_p) | ||
1841 | genfs_p->next = newgenfs; | ||
1842 | else | ||
1843 | p->genfs = newgenfs; | ||
1844 | genfs = newgenfs; | ||
1845 | newgenfs = NULL; | ||
1846 | |||
1847 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1848 | if (rc) | ||
1849 | goto out; | ||
1850 | |||
1851 | nel2 = le32_to_cpu(buf[0]); | ||
1852 | for (j = 0; j < nel2; j++) { | ||
1853 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1854 | if (rc) | ||
1855 | goto out; | ||
1856 | len = le32_to_cpu(buf[0]); | ||
1857 | |||
1858 | rc = -ENOMEM; | ||
1859 | newc = kzalloc(sizeof(*newc), GFP_KERNEL); | ||
1860 | if (!newc) | ||
1861 | goto out; | ||
1862 | |||
1863 | rc = -ENOMEM; | ||
1864 | newc->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
1865 | if (!newc->u.name) | ||
1866 | goto out; | ||
1867 | |||
1868 | rc = next_entry(newc->u.name, fp, len); | ||
1869 | if (rc) | ||
1870 | goto out; | ||
1871 | newc->u.name[len] = 0; | ||
1872 | |||
1873 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1874 | if (rc) | ||
1875 | goto out; | ||
1876 | |||
1877 | newc->v.sclass = le32_to_cpu(buf[0]); | ||
1878 | rc = context_read_and_validate(&newc->context[0], p, fp); | ||
1879 | if (rc) | ||
1880 | goto out; | ||
1881 | |||
1882 | for (l = NULL, c = genfs->head; c; | ||
1883 | l = c, c = c->next) { | ||
1884 | rc = -EINVAL; | ||
1885 | if (!strcmp(newc->u.name, c->u.name) && | ||
1886 | (!c->v.sclass || !newc->v.sclass || | ||
1887 | newc->v.sclass == c->v.sclass)) { | ||
1888 | printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n", | ||
1889 | genfs->fstype, c->u.name); | ||
1890 | goto out; | ||
1891 | } | ||
1892 | len = strlen(newc->u.name); | ||
1893 | len2 = strlen(c->u.name); | ||
1894 | if (len > len2) | ||
1895 | break; | ||
1896 | } | ||
1897 | |||
1898 | newc->next = c; | ||
1899 | if (l) | ||
1900 | l->next = newc; | ||
1901 | else | ||
1902 | genfs->head = newc; | ||
1903 | newc = NULL; | ||
1904 | } | ||
1905 | } | ||
1906 | rc = 0; | ||
1907 | out: | ||
1908 | if (newgenfs) | ||
1909 | kfree(newgenfs->fstype); | ||
1910 | kfree(newgenfs); | ||
1911 | ocontext_destroy(newc, OCON_FSUSE); | ||
1912 | |||
1913 | return rc; | ||
1914 | } | ||
1915 | |||
1916 | static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | ||
1917 | void *fp) | ||
1918 | { | ||
1919 | int i, j, rc; | ||
1920 | u32 nel, len; | ||
1921 | __le32 buf[3]; | ||
1922 | struct ocontext *l, *c; | ||
1923 | u32 nodebuf[8]; | ||
1924 | |||
1925 | for (i = 0; i < info->ocon_num; i++) { | ||
1926 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1927 | if (rc) | ||
1928 | goto out; | ||
1929 | nel = le32_to_cpu(buf[0]); | ||
1930 | |||
1931 | l = NULL; | ||
1932 | for (j = 0; j < nel; j++) { | ||
1933 | rc = -ENOMEM; | ||
1934 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
1935 | if (!c) | ||
1936 | goto out; | ||
1937 | if (l) | ||
1938 | l->next = c; | ||
1939 | else | ||
1940 | p->ocontexts[i] = c; | ||
1941 | l = c; | ||
1942 | |||
1943 | switch (i) { | ||
1944 | case OCON_ISID: | ||
1945 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1946 | if (rc) | ||
1947 | goto out; | ||
1948 | |||
1949 | c->sid[0] = le32_to_cpu(buf[0]); | ||
1950 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1951 | if (rc) | ||
1952 | goto out; | ||
1953 | break; | ||
1954 | case OCON_FS: | ||
1955 | case OCON_NETIF: | ||
1956 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1957 | if (rc) | ||
1958 | goto out; | ||
1959 | len = le32_to_cpu(buf[0]); | ||
1960 | |||
1961 | rc = -ENOMEM; | ||
1962 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
1963 | if (!c->u.name) | ||
1964 | goto out; | ||
1965 | |||
1966 | rc = next_entry(c->u.name, fp, len); | ||
1967 | if (rc) | ||
1968 | goto out; | ||
1969 | |||
1970 | c->u.name[len] = 0; | ||
1971 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1972 | if (rc) | ||
1973 | goto out; | ||
1974 | rc = context_read_and_validate(&c->context[1], p, fp); | ||
1975 | if (rc) | ||
1976 | goto out; | ||
1977 | break; | ||
1978 | case OCON_PORT: | ||
1979 | rc = next_entry(buf, fp, sizeof(u32)*3); | ||
1980 | if (rc) | ||
1981 | goto out; | ||
1982 | c->u.port.protocol = le32_to_cpu(buf[0]); | ||
1983 | c->u.port.low_port = le32_to_cpu(buf[1]); | ||
1984 | c->u.port.high_port = le32_to_cpu(buf[2]); | ||
1985 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1986 | if (rc) | ||
1987 | goto out; | ||
1988 | break; | ||
1989 | case OCON_NODE: | ||
1990 | rc = next_entry(nodebuf, fp, sizeof(u32) * 2); | ||
1991 | if (rc) | ||
1992 | goto out; | ||
1993 | c->u.node.addr = nodebuf[0]; /* network order */ | ||
1994 | c->u.node.mask = nodebuf[1]; /* network order */ | ||
1995 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1996 | if (rc) | ||
1997 | goto out; | ||
1998 | break; | ||
1999 | case OCON_FSUSE: | ||
2000 | rc = next_entry(buf, fp, sizeof(u32)*2); | ||
2001 | if (rc) | ||
2002 | goto out; | ||
2003 | |||
2004 | rc = -EINVAL; | ||
2005 | c->v.behavior = le32_to_cpu(buf[0]); | ||
2006 | if (c->v.behavior > SECURITY_FS_USE_NONE) | ||
2007 | goto out; | ||
2008 | |||
2009 | rc = -ENOMEM; | ||
2010 | len = le32_to_cpu(buf[1]); | ||
2011 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
2012 | if (!c->u.name) | ||
2013 | goto out; | ||
2014 | |||
2015 | rc = next_entry(c->u.name, fp, len); | ||
2016 | if (rc) | ||
2017 | goto out; | ||
2018 | c->u.name[len] = 0; | ||
2019 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
2020 | if (rc) | ||
2021 | goto out; | ||
2022 | break; | ||
2023 | case OCON_NODE6: { | ||
2024 | int k; | ||
2025 | |||
2026 | rc = next_entry(nodebuf, fp, sizeof(u32) * 8); | ||
2027 | if (rc) | ||
2028 | goto out; | ||
2029 | for (k = 0; k < 4; k++) | ||
2030 | c->u.node6.addr[k] = nodebuf[k]; | ||
2031 | for (k = 0; k < 4; k++) | ||
2032 | c->u.node6.mask[k] = nodebuf[k+4]; | ||
2033 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
2034 | if (rc) | ||
2035 | goto out; | ||
2036 | break; | ||
2037 | } | ||
2038 | } | ||
2039 | } | ||
2040 | } | ||
2041 | rc = 0; | ||
2042 | out: | ||
2043 | return rc; | ||
2044 | } | ||
2045 | |||
1643 | /* | 2046 | /* |
1644 | * Read the configuration data from a policy database binary | 2047 | * Read the configuration data from a policy database binary |
1645 | * representation file into a policy database structure. | 2048 | * representation file into a policy database structure. |
@@ -1648,27 +2051,23 @@ int policydb_read(struct policydb *p, void *fp) | |||
1648 | { | 2051 | { |
1649 | struct role_allow *ra, *lra; | 2052 | struct role_allow *ra, *lra; |
1650 | struct role_trans *tr, *ltr; | 2053 | struct role_trans *tr, *ltr; |
1651 | struct ocontext *l, *c, *newc; | ||
1652 | struct genfs *genfs_p, *genfs, *newgenfs; | ||
1653 | int i, j, rc; | 2054 | int i, j, rc; |
1654 | __le32 buf[4]; | 2055 | __le32 buf[4]; |
1655 | u32 nodebuf[8]; | 2056 | u32 len, nprim, nel; |
1656 | u32 len, len2, config, nprim, nel, nel2; | 2057 | |
1657 | char *policydb_str; | 2058 | char *policydb_str; |
1658 | struct policydb_compat_info *info; | 2059 | struct policydb_compat_info *info; |
1659 | struct range_trans *rt, *lrt; | ||
1660 | |||
1661 | config = 0; | ||
1662 | 2060 | ||
1663 | rc = policydb_init(p); | 2061 | rc = policydb_init(p); |
1664 | if (rc) | 2062 | if (rc) |
1665 | goto out; | 2063 | return rc; |
1666 | 2064 | ||
1667 | /* Read the magic number and string length. */ | 2065 | /* Read the magic number and string length. */ |
1668 | rc = next_entry(buf, fp, sizeof(u32) * 2); | 2066 | rc = next_entry(buf, fp, sizeof(u32) * 2); |
1669 | if (rc < 0) | 2067 | if (rc) |
1670 | goto bad; | 2068 | goto bad; |
1671 | 2069 | ||
2070 | rc = -EINVAL; | ||
1672 | if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { | 2071 | if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { |
1673 | printk(KERN_ERR "SELinux: policydb magic number 0x%x does " | 2072 | printk(KERN_ERR "SELinux: policydb magic number 0x%x does " |
1674 | "not match expected magic number 0x%x\n", | 2073 | "not match expected magic number 0x%x\n", |
@@ -1676,6 +2075,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1676 | goto bad; | 2075 | goto bad; |
1677 | } | 2076 | } |
1678 | 2077 | ||
2078 | rc = -EINVAL; | ||
1679 | len = le32_to_cpu(buf[1]); | 2079 | len = le32_to_cpu(buf[1]); |
1680 | if (len != strlen(POLICYDB_STRING)) { | 2080 | if (len != strlen(POLICYDB_STRING)) { |
1681 | printk(KERN_ERR "SELinux: policydb string length %d does not " | 2081 | printk(KERN_ERR "SELinux: policydb string length %d does not " |
@@ -1683,19 +2083,23 @@ int policydb_read(struct policydb *p, void *fp) | |||
1683 | len, strlen(POLICYDB_STRING)); | 2083 | len, strlen(POLICYDB_STRING)); |
1684 | goto bad; | 2084 | goto bad; |
1685 | } | 2085 | } |
2086 | |||
2087 | rc = -ENOMEM; | ||
1686 | policydb_str = kmalloc(len + 1, GFP_KERNEL); | 2088 | policydb_str = kmalloc(len + 1, GFP_KERNEL); |
1687 | if (!policydb_str) { | 2089 | if (!policydb_str) { |
1688 | printk(KERN_ERR "SELinux: unable to allocate memory for policydb " | 2090 | printk(KERN_ERR "SELinux: unable to allocate memory for policydb " |
1689 | "string of length %d\n", len); | 2091 | "string of length %d\n", len); |
1690 | rc = -ENOMEM; | ||
1691 | goto bad; | 2092 | goto bad; |
1692 | } | 2093 | } |
2094 | |||
1693 | rc = next_entry(policydb_str, fp, len); | 2095 | rc = next_entry(policydb_str, fp, len); |
1694 | if (rc < 0) { | 2096 | if (rc) { |
1695 | printk(KERN_ERR "SELinux: truncated policydb string identifier\n"); | 2097 | printk(KERN_ERR "SELinux: truncated policydb string identifier\n"); |
1696 | kfree(policydb_str); | 2098 | kfree(policydb_str); |
1697 | goto bad; | 2099 | goto bad; |
1698 | } | 2100 | } |
2101 | |||
2102 | rc = -EINVAL; | ||
1699 | policydb_str[len] = '\0'; | 2103 | policydb_str[len] = '\0'; |
1700 | if (strcmp(policydb_str, POLICYDB_STRING)) { | 2104 | if (strcmp(policydb_str, POLICYDB_STRING)) { |
1701 | printk(KERN_ERR "SELinux: policydb string %s does not match " | 2105 | printk(KERN_ERR "SELinux: policydb string %s does not match " |
@@ -1707,11 +2111,12 @@ int policydb_read(struct policydb *p, void *fp) | |||
1707 | kfree(policydb_str); | 2111 | kfree(policydb_str); |
1708 | policydb_str = NULL; | 2112 | policydb_str = NULL; |
1709 | 2113 | ||
1710 | /* Read the version, config, and table sizes. */ | 2114 | /* Read the version and table sizes. */ |
1711 | rc = next_entry(buf, fp, sizeof(u32)*4); | 2115 | rc = next_entry(buf, fp, sizeof(u32)*4); |
1712 | if (rc < 0) | 2116 | if (rc) |
1713 | goto bad; | 2117 | goto bad; |
1714 | 2118 | ||
2119 | rc = -EINVAL; | ||
1715 | p->policyvers = le32_to_cpu(buf[0]); | 2120 | p->policyvers = le32_to_cpu(buf[0]); |
1716 | if (p->policyvers < POLICYDB_VERSION_MIN || | 2121 | if (p->policyvers < POLICYDB_VERSION_MIN || |
1717 | p->policyvers > POLICYDB_VERSION_MAX) { | 2122 | p->policyvers > POLICYDB_VERSION_MAX) { |
@@ -1722,38 +2127,32 @@ int policydb_read(struct policydb *p, void *fp) | |||
1722 | } | 2127 | } |
1723 | 2128 | ||
1724 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { | 2129 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
1725 | if (ss_initialized && !selinux_mls_enabled) { | 2130 | p->mls_enabled = 1; |
1726 | printk(KERN_ERR "SELinux: Cannot switch between non-MLS" | ||
1727 | " and MLS policies\n"); | ||
1728 | goto bad; | ||
1729 | } | ||
1730 | selinux_mls_enabled = 1; | ||
1731 | config |= POLICYDB_CONFIG_MLS; | ||
1732 | 2131 | ||
2132 | rc = -EINVAL; | ||
1733 | if (p->policyvers < POLICYDB_VERSION_MLS) { | 2133 | if (p->policyvers < POLICYDB_VERSION_MLS) { |
1734 | printk(KERN_ERR "SELinux: security policydb version %d " | 2134 | printk(KERN_ERR "SELinux: security policydb version %d " |
1735 | "(MLS) not backwards compatible\n", | 2135 | "(MLS) not backwards compatible\n", |
1736 | p->policyvers); | 2136 | p->policyvers); |
1737 | goto bad; | 2137 | goto bad; |
1738 | } | 2138 | } |
1739 | } else { | ||
1740 | if (ss_initialized && selinux_mls_enabled) { | ||
1741 | printk(KERN_ERR "SELinux: Cannot switch between MLS and" | ||
1742 | " non-MLS policies\n"); | ||
1743 | goto bad; | ||
1744 | } | ||
1745 | } | 2139 | } |
1746 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); | 2140 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); |
1747 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); | 2141 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); |
1748 | 2142 | ||
1749 | if (p->policyvers >= POLICYDB_VERSION_POLCAP && | 2143 | if (p->policyvers >= POLICYDB_VERSION_POLCAP) { |
1750 | ebitmap_read(&p->policycaps, fp) != 0) | 2144 | rc = ebitmap_read(&p->policycaps, fp); |
1751 | goto bad; | 2145 | if (rc) |
2146 | goto bad; | ||
2147 | } | ||
1752 | 2148 | ||
1753 | if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && | 2149 | if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) { |
1754 | ebitmap_read(&p->permissive_map, fp) != 0) | 2150 | rc = ebitmap_read(&p->permissive_map, fp); |
1755 | goto bad; | 2151 | if (rc) |
2152 | goto bad; | ||
2153 | } | ||
1756 | 2154 | ||
2155 | rc = -EINVAL; | ||
1757 | info = policydb_lookup_compat(p->policyvers); | 2156 | info = policydb_lookup_compat(p->policyvers); |
1758 | if (!info) { | 2157 | if (!info) { |
1759 | printk(KERN_ERR "SELinux: unable to find policy compat info " | 2158 | printk(KERN_ERR "SELinux: unable to find policy compat info " |
@@ -1761,6 +2160,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1761 | goto bad; | 2160 | goto bad; |
1762 | } | 2161 | } |
1763 | 2162 | ||
2163 | rc = -EINVAL; | ||
1764 | if (le32_to_cpu(buf[2]) != info->sym_num || | 2164 | if (le32_to_cpu(buf[2]) != info->sym_num || |
1765 | le32_to_cpu(buf[3]) != info->ocon_num) { | 2165 | le32_to_cpu(buf[3]) != info->ocon_num) { |
1766 | printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do " | 2166 | printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do " |
@@ -1772,7 +2172,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1772 | 2172 | ||
1773 | for (i = 0; i < info->sym_num; i++) { | 2173 | for (i = 0; i < info->sym_num; i++) { |
1774 | rc = next_entry(buf, fp, sizeof(u32)*2); | 2174 | rc = next_entry(buf, fp, sizeof(u32)*2); |
1775 | if (rc < 0) | 2175 | if (rc) |
1776 | goto bad; | 2176 | goto bad; |
1777 | nprim = le32_to_cpu(buf[0]); | 2177 | nprim = le32_to_cpu(buf[0]); |
1778 | nel = le32_to_cpu(buf[1]); | 2178 | nel = le32_to_cpu(buf[1]); |
@@ -1796,356 +2196,965 @@ int policydb_read(struct policydb *p, void *fp) | |||
1796 | } | 2196 | } |
1797 | 2197 | ||
1798 | rc = next_entry(buf, fp, sizeof(u32)); | 2198 | rc = next_entry(buf, fp, sizeof(u32)); |
1799 | if (rc < 0) | 2199 | if (rc) |
1800 | goto bad; | 2200 | goto bad; |
1801 | nel = le32_to_cpu(buf[0]); | 2201 | nel = le32_to_cpu(buf[0]); |
1802 | ltr = NULL; | 2202 | ltr = NULL; |
1803 | for (i = 0; i < nel; i++) { | 2203 | for (i = 0; i < nel; i++) { |
2204 | rc = -ENOMEM; | ||
1804 | tr = kzalloc(sizeof(*tr), GFP_KERNEL); | 2205 | tr = kzalloc(sizeof(*tr), GFP_KERNEL); |
1805 | if (!tr) { | 2206 | if (!tr) |
1806 | rc = -ENOMEM; | ||
1807 | goto bad; | 2207 | goto bad; |
1808 | } | ||
1809 | if (ltr) | 2208 | if (ltr) |
1810 | ltr->next = tr; | 2209 | ltr->next = tr; |
1811 | else | 2210 | else |
1812 | p->role_tr = tr; | 2211 | p->role_tr = tr; |
1813 | rc = next_entry(buf, fp, sizeof(u32)*3); | 2212 | rc = next_entry(buf, fp, sizeof(u32)*3); |
1814 | if (rc < 0) | 2213 | if (rc) |
1815 | goto bad; | 2214 | goto bad; |
2215 | |||
2216 | rc = -EINVAL; | ||
1816 | tr->role = le32_to_cpu(buf[0]); | 2217 | tr->role = le32_to_cpu(buf[0]); |
1817 | tr->type = le32_to_cpu(buf[1]); | 2218 | tr->type = le32_to_cpu(buf[1]); |
1818 | tr->new_role = le32_to_cpu(buf[2]); | 2219 | tr->new_role = le32_to_cpu(buf[2]); |
1819 | if (!policydb_role_isvalid(p, tr->role) || | 2220 | if (!policydb_role_isvalid(p, tr->role) || |
1820 | !policydb_type_isvalid(p, tr->type) || | 2221 | !policydb_type_isvalid(p, tr->type) || |
1821 | !policydb_role_isvalid(p, tr->new_role)) { | 2222 | !policydb_role_isvalid(p, tr->new_role)) |
1822 | rc = -EINVAL; | ||
1823 | goto bad; | 2223 | goto bad; |
1824 | } | ||
1825 | ltr = tr; | 2224 | ltr = tr; |
1826 | } | 2225 | } |
1827 | 2226 | ||
1828 | rc = next_entry(buf, fp, sizeof(u32)); | 2227 | rc = next_entry(buf, fp, sizeof(u32)); |
1829 | if (rc < 0) | 2228 | if (rc) |
1830 | goto bad; | 2229 | goto bad; |
1831 | nel = le32_to_cpu(buf[0]); | 2230 | nel = le32_to_cpu(buf[0]); |
1832 | lra = NULL; | 2231 | lra = NULL; |
1833 | for (i = 0; i < nel; i++) { | 2232 | for (i = 0; i < nel; i++) { |
2233 | rc = -ENOMEM; | ||
1834 | ra = kzalloc(sizeof(*ra), GFP_KERNEL); | 2234 | ra = kzalloc(sizeof(*ra), GFP_KERNEL); |
1835 | if (!ra) { | 2235 | if (!ra) |
1836 | rc = -ENOMEM; | ||
1837 | goto bad; | 2236 | goto bad; |
1838 | } | ||
1839 | if (lra) | 2237 | if (lra) |
1840 | lra->next = ra; | 2238 | lra->next = ra; |
1841 | else | 2239 | else |
1842 | p->role_allow = ra; | 2240 | p->role_allow = ra; |
1843 | rc = next_entry(buf, fp, sizeof(u32)*2); | 2241 | rc = next_entry(buf, fp, sizeof(u32)*2); |
1844 | if (rc < 0) | 2242 | if (rc) |
1845 | goto bad; | 2243 | goto bad; |
2244 | |||
2245 | rc = -EINVAL; | ||
1846 | ra->role = le32_to_cpu(buf[0]); | 2246 | ra->role = le32_to_cpu(buf[0]); |
1847 | ra->new_role = le32_to_cpu(buf[1]); | 2247 | ra->new_role = le32_to_cpu(buf[1]); |
1848 | if (!policydb_role_isvalid(p, ra->role) || | 2248 | if (!policydb_role_isvalid(p, ra->role) || |
1849 | !policydb_role_isvalid(p, ra->new_role)) { | 2249 | !policydb_role_isvalid(p, ra->new_role)) |
1850 | rc = -EINVAL; | ||
1851 | goto bad; | 2250 | goto bad; |
1852 | } | ||
1853 | lra = ra; | 2251 | lra = ra; |
1854 | } | 2252 | } |
1855 | 2253 | ||
1856 | rc = policydb_index_classes(p); | 2254 | rc = policydb_index(p); |
2255 | if (rc) | ||
2256 | goto bad; | ||
2257 | |||
2258 | rc = -EINVAL; | ||
2259 | p->process_class = string_to_security_class(p, "process"); | ||
2260 | if (!p->process_class) | ||
2261 | goto bad; | ||
2262 | |||
2263 | rc = -EINVAL; | ||
2264 | p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition"); | ||
2265 | p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition"); | ||
2266 | if (!p->process_trans_perms) | ||
2267 | goto bad; | ||
2268 | |||
2269 | rc = ocontext_read(p, info, fp); | ||
1857 | if (rc) | 2270 | if (rc) |
1858 | goto bad; | 2271 | goto bad; |
1859 | 2272 | ||
1860 | rc = policydb_index_others(p); | 2273 | rc = genfs_read(p, fp); |
1861 | if (rc) | 2274 | if (rc) |
1862 | goto bad; | 2275 | goto bad; |
1863 | 2276 | ||
1864 | for (i = 0; i < info->ocon_num; i++) { | 2277 | rc = range_read(p, fp); |
1865 | rc = next_entry(buf, fp, sizeof(u32)); | 2278 | if (rc) |
1866 | if (rc < 0) | 2279 | goto bad; |
1867 | goto bad; | 2280 | |
1868 | nel = le32_to_cpu(buf[0]); | 2281 | rc = -ENOMEM; |
1869 | l = NULL; | 2282 | p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap), |
1870 | for (j = 0; j < nel; j++) { | 2283 | p->p_types.nprim, |
1871 | c = kzalloc(sizeof(*c), GFP_KERNEL); | 2284 | GFP_KERNEL | __GFP_ZERO); |
1872 | if (!c) { | 2285 | if (!p->type_attr_map_array) |
1873 | rc = -ENOMEM; | 2286 | goto bad; |
2287 | |||
2288 | /* preallocate so we don't have to worry about the put ever failing */ | ||
2289 | rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1, | ||
2290 | GFP_KERNEL | __GFP_ZERO); | ||
2291 | if (rc) | ||
2292 | goto bad; | ||
2293 | |||
2294 | for (i = 0; i < p->p_types.nprim; i++) { | ||
2295 | struct ebitmap *e = flex_array_get(p->type_attr_map_array, i); | ||
2296 | |||
2297 | BUG_ON(!e); | ||
2298 | ebitmap_init(e); | ||
2299 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { | ||
2300 | rc = ebitmap_read(e, fp); | ||
2301 | if (rc) | ||
1874 | goto bad; | 2302 | goto bad; |
2303 | } | ||
2304 | /* add the type itself as the degenerate case */ | ||
2305 | rc = ebitmap_set_bit(e, i, 1); | ||
2306 | if (rc) | ||
2307 | goto bad; | ||
2308 | } | ||
2309 | |||
2310 | rc = policydb_bounds_sanity_check(p); | ||
2311 | if (rc) | ||
2312 | goto bad; | ||
2313 | |||
2314 | rc = 0; | ||
2315 | out: | ||
2316 | return rc; | ||
2317 | bad: | ||
2318 | policydb_destroy(p); | ||
2319 | goto out; | ||
2320 | } | ||
2321 | |||
2322 | /* | ||
2323 | * Write a MLS level structure to a policydb binary | ||
2324 | * representation file. | ||
2325 | */ | ||
2326 | static int mls_write_level(struct mls_level *l, void *fp) | ||
2327 | { | ||
2328 | __le32 buf[1]; | ||
2329 | int rc; | ||
2330 | |||
2331 | buf[0] = cpu_to_le32(l->sens); | ||
2332 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2333 | if (rc) | ||
2334 | return rc; | ||
2335 | |||
2336 | rc = ebitmap_write(&l->cat, fp); | ||
2337 | if (rc) | ||
2338 | return rc; | ||
2339 | |||
2340 | return 0; | ||
2341 | } | ||
2342 | |||
2343 | /* | ||
2344 | * Write a MLS range structure to a policydb binary | ||
2345 | * representation file. | ||
2346 | */ | ||
2347 | static int mls_write_range_helper(struct mls_range *r, void *fp) | ||
2348 | { | ||
2349 | __le32 buf[3]; | ||
2350 | size_t items; | ||
2351 | int rc, eq; | ||
2352 | |||
2353 | eq = mls_level_eq(&r->level[1], &r->level[0]); | ||
2354 | |||
2355 | if (eq) | ||
2356 | items = 2; | ||
2357 | else | ||
2358 | items = 3; | ||
2359 | buf[0] = cpu_to_le32(items-1); | ||
2360 | buf[1] = cpu_to_le32(r->level[0].sens); | ||
2361 | if (!eq) | ||
2362 | buf[2] = cpu_to_le32(r->level[1].sens); | ||
2363 | |||
2364 | BUG_ON(items > (sizeof(buf)/sizeof(buf[0]))); | ||
2365 | |||
2366 | rc = put_entry(buf, sizeof(u32), items, fp); | ||
2367 | if (rc) | ||
2368 | return rc; | ||
2369 | |||
2370 | rc = ebitmap_write(&r->level[0].cat, fp); | ||
2371 | if (rc) | ||
2372 | return rc; | ||
2373 | if (!eq) { | ||
2374 | rc = ebitmap_write(&r->level[1].cat, fp); | ||
2375 | if (rc) | ||
2376 | return rc; | ||
2377 | } | ||
2378 | |||
2379 | return 0; | ||
2380 | } | ||
2381 | |||
2382 | static int sens_write(void *vkey, void *datum, void *ptr) | ||
2383 | { | ||
2384 | char *key = vkey; | ||
2385 | struct level_datum *levdatum = datum; | ||
2386 | struct policy_data *pd = ptr; | ||
2387 | void *fp = pd->fp; | ||
2388 | __le32 buf[2]; | ||
2389 | size_t len; | ||
2390 | int rc; | ||
2391 | |||
2392 | len = strlen(key); | ||
2393 | buf[0] = cpu_to_le32(len); | ||
2394 | buf[1] = cpu_to_le32(levdatum->isalias); | ||
2395 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
2396 | if (rc) | ||
2397 | return rc; | ||
2398 | |||
2399 | rc = put_entry(key, 1, len, fp); | ||
2400 | if (rc) | ||
2401 | return rc; | ||
2402 | |||
2403 | rc = mls_write_level(levdatum->level, fp); | ||
2404 | if (rc) | ||
2405 | return rc; | ||
2406 | |||
2407 | return 0; | ||
2408 | } | ||
2409 | |||
2410 | static int cat_write(void *vkey, void *datum, void *ptr) | ||
2411 | { | ||
2412 | char *key = vkey; | ||
2413 | struct cat_datum *catdatum = datum; | ||
2414 | struct policy_data *pd = ptr; | ||
2415 | void *fp = pd->fp; | ||
2416 | __le32 buf[3]; | ||
2417 | size_t len; | ||
2418 | int rc; | ||
2419 | |||
2420 | len = strlen(key); | ||
2421 | buf[0] = cpu_to_le32(len); | ||
2422 | buf[1] = cpu_to_le32(catdatum->value); | ||
2423 | buf[2] = cpu_to_le32(catdatum->isalias); | ||
2424 | rc = put_entry(buf, sizeof(u32), 3, fp); | ||
2425 | if (rc) | ||
2426 | return rc; | ||
2427 | |||
2428 | rc = put_entry(key, 1, len, fp); | ||
2429 | if (rc) | ||
2430 | return rc; | ||
2431 | |||
2432 | return 0; | ||
2433 | } | ||
2434 | |||
2435 | static int role_trans_write(struct role_trans *r, void *fp) | ||
2436 | { | ||
2437 | struct role_trans *tr; | ||
2438 | u32 buf[3]; | ||
2439 | size_t nel; | ||
2440 | int rc; | ||
2441 | |||
2442 | nel = 0; | ||
2443 | for (tr = r; tr; tr = tr->next) | ||
2444 | nel++; | ||
2445 | buf[0] = cpu_to_le32(nel); | ||
2446 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2447 | if (rc) | ||
2448 | return rc; | ||
2449 | for (tr = r; tr; tr = tr->next) { | ||
2450 | buf[0] = cpu_to_le32(tr->role); | ||
2451 | buf[1] = cpu_to_le32(tr->type); | ||
2452 | buf[2] = cpu_to_le32(tr->new_role); | ||
2453 | rc = put_entry(buf, sizeof(u32), 3, fp); | ||
2454 | if (rc) | ||
2455 | return rc; | ||
2456 | } | ||
2457 | |||
2458 | return 0; | ||
2459 | } | ||
2460 | |||
2461 | static int role_allow_write(struct role_allow *r, void *fp) | ||
2462 | { | ||
2463 | struct role_allow *ra; | ||
2464 | u32 buf[2]; | ||
2465 | size_t nel; | ||
2466 | int rc; | ||
2467 | |||
2468 | nel = 0; | ||
2469 | for (ra = r; ra; ra = ra->next) | ||
2470 | nel++; | ||
2471 | buf[0] = cpu_to_le32(nel); | ||
2472 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2473 | if (rc) | ||
2474 | return rc; | ||
2475 | for (ra = r; ra; ra = ra->next) { | ||
2476 | buf[0] = cpu_to_le32(ra->role); | ||
2477 | buf[1] = cpu_to_le32(ra->new_role); | ||
2478 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
2479 | if (rc) | ||
2480 | return rc; | ||
2481 | } | ||
2482 | return 0; | ||
2483 | } | ||
2484 | |||
2485 | /* | ||
2486 | * Write a security context structure | ||
2487 | * to a policydb binary representation file. | ||
2488 | */ | ||
2489 | static int context_write(struct policydb *p, struct context *c, | ||
2490 | void *fp) | ||
2491 | { | ||
2492 | int rc; | ||
2493 | __le32 buf[3]; | ||
2494 | |||
2495 | buf[0] = cpu_to_le32(c->user); | ||
2496 | buf[1] = cpu_to_le32(c->role); | ||
2497 | buf[2] = cpu_to_le32(c->type); | ||
2498 | |||
2499 | rc = put_entry(buf, sizeof(u32), 3, fp); | ||
2500 | if (rc) | ||
2501 | return rc; | ||
2502 | |||
2503 | rc = mls_write_range_helper(&c->range, fp); | ||
2504 | if (rc) | ||
2505 | return rc; | ||
2506 | |||
2507 | return 0; | ||
2508 | } | ||
2509 | |||
2510 | /* | ||
2511 | * The following *_write functions are used to | ||
2512 | * write the symbol data to a policy database | ||
2513 | * binary representation file. | ||
2514 | */ | ||
2515 | |||
2516 | static int perm_write(void *vkey, void *datum, void *fp) | ||
2517 | { | ||
2518 | char *key = vkey; | ||
2519 | struct perm_datum *perdatum = datum; | ||
2520 | __le32 buf[2]; | ||
2521 | size_t len; | ||
2522 | int rc; | ||
2523 | |||
2524 | len = strlen(key); | ||
2525 | buf[0] = cpu_to_le32(len); | ||
2526 | buf[1] = cpu_to_le32(perdatum->value); | ||
2527 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
2528 | if (rc) | ||
2529 | return rc; | ||
2530 | |||
2531 | rc = put_entry(key, 1, len, fp); | ||
2532 | if (rc) | ||
2533 | return rc; | ||
2534 | |||
2535 | return 0; | ||
2536 | } | ||
2537 | |||
2538 | static int common_write(void *vkey, void *datum, void *ptr) | ||
2539 | { | ||
2540 | char *key = vkey; | ||
2541 | struct common_datum *comdatum = datum; | ||
2542 | struct policy_data *pd = ptr; | ||
2543 | void *fp = pd->fp; | ||
2544 | __le32 buf[4]; | ||
2545 | size_t len; | ||
2546 | int rc; | ||
2547 | |||
2548 | len = strlen(key); | ||
2549 | buf[0] = cpu_to_le32(len); | ||
2550 | buf[1] = cpu_to_le32(comdatum->value); | ||
2551 | buf[2] = cpu_to_le32(comdatum->permissions.nprim); | ||
2552 | buf[3] = cpu_to_le32(comdatum->permissions.table->nel); | ||
2553 | rc = put_entry(buf, sizeof(u32), 4, fp); | ||
2554 | if (rc) | ||
2555 | return rc; | ||
2556 | |||
2557 | rc = put_entry(key, 1, len, fp); | ||
2558 | if (rc) | ||
2559 | return rc; | ||
2560 | |||
2561 | rc = hashtab_map(comdatum->permissions.table, perm_write, fp); | ||
2562 | if (rc) | ||
2563 | return rc; | ||
2564 | |||
2565 | return 0; | ||
2566 | } | ||
2567 | |||
2568 | static int write_cons_helper(struct policydb *p, struct constraint_node *node, | ||
2569 | void *fp) | ||
2570 | { | ||
2571 | struct constraint_node *c; | ||
2572 | struct constraint_expr *e; | ||
2573 | __le32 buf[3]; | ||
2574 | u32 nel; | ||
2575 | int rc; | ||
2576 | |||
2577 | for (c = node; c; c = c->next) { | ||
2578 | nel = 0; | ||
2579 | for (e = c->expr; e; e = e->next) | ||
2580 | nel++; | ||
2581 | buf[0] = cpu_to_le32(c->permissions); | ||
2582 | buf[1] = cpu_to_le32(nel); | ||
2583 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
2584 | if (rc) | ||
2585 | return rc; | ||
2586 | for (e = c->expr; e; e = e->next) { | ||
2587 | buf[0] = cpu_to_le32(e->expr_type); | ||
2588 | buf[1] = cpu_to_le32(e->attr); | ||
2589 | buf[2] = cpu_to_le32(e->op); | ||
2590 | rc = put_entry(buf, sizeof(u32), 3, fp); | ||
2591 | if (rc) | ||
2592 | return rc; | ||
2593 | |||
2594 | switch (e->expr_type) { | ||
2595 | case CEXPR_NAMES: | ||
2596 | rc = ebitmap_write(&e->names, fp); | ||
2597 | if (rc) | ||
2598 | return rc; | ||
2599 | break; | ||
2600 | default: | ||
2601 | break; | ||
1875 | } | 2602 | } |
1876 | if (l) | 2603 | } |
1877 | l->next = c; | 2604 | } |
1878 | else | 2605 | |
1879 | p->ocontexts[i] = c; | 2606 | return 0; |
1880 | l = c; | 2607 | } |
1881 | rc = -EINVAL; | 2608 | |
2609 | static int class_write(void *vkey, void *datum, void *ptr) | ||
2610 | { | ||
2611 | char *key = vkey; | ||
2612 | struct class_datum *cladatum = datum; | ||
2613 | struct policy_data *pd = ptr; | ||
2614 | void *fp = pd->fp; | ||
2615 | struct policydb *p = pd->p; | ||
2616 | struct constraint_node *c; | ||
2617 | __le32 buf[6]; | ||
2618 | u32 ncons; | ||
2619 | size_t len, len2; | ||
2620 | int rc; | ||
2621 | |||
2622 | len = strlen(key); | ||
2623 | if (cladatum->comkey) | ||
2624 | len2 = strlen(cladatum->comkey); | ||
2625 | else | ||
2626 | len2 = 0; | ||
2627 | |||
2628 | ncons = 0; | ||
2629 | for (c = cladatum->constraints; c; c = c->next) | ||
2630 | ncons++; | ||
2631 | |||
2632 | buf[0] = cpu_to_le32(len); | ||
2633 | buf[1] = cpu_to_le32(len2); | ||
2634 | buf[2] = cpu_to_le32(cladatum->value); | ||
2635 | buf[3] = cpu_to_le32(cladatum->permissions.nprim); | ||
2636 | if (cladatum->permissions.table) | ||
2637 | buf[4] = cpu_to_le32(cladatum->permissions.table->nel); | ||
2638 | else | ||
2639 | buf[4] = 0; | ||
2640 | buf[5] = cpu_to_le32(ncons); | ||
2641 | rc = put_entry(buf, sizeof(u32), 6, fp); | ||
2642 | if (rc) | ||
2643 | return rc; | ||
2644 | |||
2645 | rc = put_entry(key, 1, len, fp); | ||
2646 | if (rc) | ||
2647 | return rc; | ||
2648 | |||
2649 | if (cladatum->comkey) { | ||
2650 | rc = put_entry(cladatum->comkey, 1, len2, fp); | ||
2651 | if (rc) | ||
2652 | return rc; | ||
2653 | } | ||
2654 | |||
2655 | rc = hashtab_map(cladatum->permissions.table, perm_write, fp); | ||
2656 | if (rc) | ||
2657 | return rc; | ||
2658 | |||
2659 | rc = write_cons_helper(p, cladatum->constraints, fp); | ||
2660 | if (rc) | ||
2661 | return rc; | ||
2662 | |||
2663 | /* write out the validatetrans rule */ | ||
2664 | ncons = 0; | ||
2665 | for (c = cladatum->validatetrans; c; c = c->next) | ||
2666 | ncons++; | ||
2667 | |||
2668 | buf[0] = cpu_to_le32(ncons); | ||
2669 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2670 | if (rc) | ||
2671 | return rc; | ||
2672 | |||
2673 | rc = write_cons_helper(p, cladatum->validatetrans, fp); | ||
2674 | if (rc) | ||
2675 | return rc; | ||
2676 | |||
2677 | return 0; | ||
2678 | } | ||
2679 | |||
2680 | static int role_write(void *vkey, void *datum, void *ptr) | ||
2681 | { | ||
2682 | char *key = vkey; | ||
2683 | struct role_datum *role = datum; | ||
2684 | struct policy_data *pd = ptr; | ||
2685 | void *fp = pd->fp; | ||
2686 | struct policydb *p = pd->p; | ||
2687 | __le32 buf[3]; | ||
2688 | size_t items, len; | ||
2689 | int rc; | ||
2690 | |||
2691 | len = strlen(key); | ||
2692 | items = 0; | ||
2693 | buf[items++] = cpu_to_le32(len); | ||
2694 | buf[items++] = cpu_to_le32(role->value); | ||
2695 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | ||
2696 | buf[items++] = cpu_to_le32(role->bounds); | ||
2697 | |||
2698 | BUG_ON(items > (sizeof(buf)/sizeof(buf[0]))); | ||
2699 | |||
2700 | rc = put_entry(buf, sizeof(u32), items, fp); | ||
2701 | if (rc) | ||
2702 | return rc; | ||
2703 | |||
2704 | rc = put_entry(key, 1, len, fp); | ||
2705 | if (rc) | ||
2706 | return rc; | ||
2707 | |||
2708 | rc = ebitmap_write(&role->dominates, fp); | ||
2709 | if (rc) | ||
2710 | return rc; | ||
2711 | |||
2712 | rc = ebitmap_write(&role->types, fp); | ||
2713 | if (rc) | ||
2714 | return rc; | ||
2715 | |||
2716 | return 0; | ||
2717 | } | ||
2718 | |||
2719 | static int type_write(void *vkey, void *datum, void *ptr) | ||
2720 | { | ||
2721 | char *key = vkey; | ||
2722 | struct type_datum *typdatum = datum; | ||
2723 | struct policy_data *pd = ptr; | ||
2724 | struct policydb *p = pd->p; | ||
2725 | void *fp = pd->fp; | ||
2726 | __le32 buf[4]; | ||
2727 | int rc; | ||
2728 | size_t items, len; | ||
2729 | |||
2730 | len = strlen(key); | ||
2731 | items = 0; | ||
2732 | buf[items++] = cpu_to_le32(len); | ||
2733 | buf[items++] = cpu_to_le32(typdatum->value); | ||
2734 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) { | ||
2735 | u32 properties = 0; | ||
2736 | |||
2737 | if (typdatum->primary) | ||
2738 | properties |= TYPEDATUM_PROPERTY_PRIMARY; | ||
2739 | |||
2740 | if (typdatum->attribute) | ||
2741 | properties |= TYPEDATUM_PROPERTY_ATTRIBUTE; | ||
2742 | |||
2743 | buf[items++] = cpu_to_le32(properties); | ||
2744 | buf[items++] = cpu_to_le32(typdatum->bounds); | ||
2745 | } else { | ||
2746 | buf[items++] = cpu_to_le32(typdatum->primary); | ||
2747 | } | ||
2748 | BUG_ON(items > (sizeof(buf) / sizeof(buf[0]))); | ||
2749 | rc = put_entry(buf, sizeof(u32), items, fp); | ||
2750 | if (rc) | ||
2751 | return rc; | ||
2752 | |||
2753 | rc = put_entry(key, 1, len, fp); | ||
2754 | if (rc) | ||
2755 | return rc; | ||
2756 | |||
2757 | return 0; | ||
2758 | } | ||
2759 | |||
2760 | static int user_write(void *vkey, void *datum, void *ptr) | ||
2761 | { | ||
2762 | char *key = vkey; | ||
2763 | struct user_datum *usrdatum = datum; | ||
2764 | struct policy_data *pd = ptr; | ||
2765 | struct policydb *p = pd->p; | ||
2766 | void *fp = pd->fp; | ||
2767 | __le32 buf[3]; | ||
2768 | size_t items, len; | ||
2769 | int rc; | ||
2770 | |||
2771 | len = strlen(key); | ||
2772 | items = 0; | ||
2773 | buf[items++] = cpu_to_le32(len); | ||
2774 | buf[items++] = cpu_to_le32(usrdatum->value); | ||
2775 | if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) | ||
2776 | buf[items++] = cpu_to_le32(usrdatum->bounds); | ||
2777 | BUG_ON(items > (sizeof(buf) / sizeof(buf[0]))); | ||
2778 | rc = put_entry(buf, sizeof(u32), items, fp); | ||
2779 | if (rc) | ||
2780 | return rc; | ||
2781 | |||
2782 | rc = put_entry(key, 1, len, fp); | ||
2783 | if (rc) | ||
2784 | return rc; | ||
2785 | |||
2786 | rc = ebitmap_write(&usrdatum->roles, fp); | ||
2787 | if (rc) | ||
2788 | return rc; | ||
2789 | |||
2790 | rc = mls_write_range_helper(&usrdatum->range, fp); | ||
2791 | if (rc) | ||
2792 | return rc; | ||
2793 | |||
2794 | rc = mls_write_level(&usrdatum->dfltlevel, fp); | ||
2795 | if (rc) | ||
2796 | return rc; | ||
2797 | |||
2798 | return 0; | ||
2799 | } | ||
2800 | |||
2801 | static int (*write_f[SYM_NUM]) (void *key, void *datum, | ||
2802 | void *datap) = | ||
2803 | { | ||
2804 | common_write, | ||
2805 | class_write, | ||
2806 | role_write, | ||
2807 | type_write, | ||
2808 | user_write, | ||
2809 | cond_write_bool, | ||
2810 | sens_write, | ||
2811 | cat_write, | ||
2812 | }; | ||
2813 | |||
2814 | static int ocontext_write(struct policydb *p, struct policydb_compat_info *info, | ||
2815 | void *fp) | ||
2816 | { | ||
2817 | unsigned int i, j, rc; | ||
2818 | size_t nel, len; | ||
2819 | __le32 buf[3]; | ||
2820 | u32 nodebuf[8]; | ||
2821 | struct ocontext *c; | ||
2822 | for (i = 0; i < info->ocon_num; i++) { | ||
2823 | nel = 0; | ||
2824 | for (c = p->ocontexts[i]; c; c = c->next) | ||
2825 | nel++; | ||
2826 | buf[0] = cpu_to_le32(nel); | ||
2827 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2828 | if (rc) | ||
2829 | return rc; | ||
2830 | for (c = p->ocontexts[i]; c; c = c->next) { | ||
1882 | switch (i) { | 2831 | switch (i) { |
1883 | case OCON_ISID: | 2832 | case OCON_ISID: |
1884 | rc = next_entry(buf, fp, sizeof(u32)); | 2833 | buf[0] = cpu_to_le32(c->sid[0]); |
1885 | if (rc < 0) | 2834 | rc = put_entry(buf, sizeof(u32), 1, fp); |
1886 | goto bad; | 2835 | if (rc) |
1887 | c->sid[0] = le32_to_cpu(buf[0]); | 2836 | return rc; |
1888 | rc = context_read_and_validate(&c->context[0], p, fp); | 2837 | rc = context_write(p, &c->context[0], fp); |
1889 | if (rc) | 2838 | if (rc) |
1890 | goto bad; | 2839 | return rc; |
1891 | break; | 2840 | break; |
1892 | case OCON_FS: | 2841 | case OCON_FS: |
1893 | case OCON_NETIF: | 2842 | case OCON_NETIF: |
1894 | rc = next_entry(buf, fp, sizeof(u32)); | 2843 | len = strlen(c->u.name); |
1895 | if (rc < 0) | 2844 | buf[0] = cpu_to_le32(len); |
1896 | goto bad; | 2845 | rc = put_entry(buf, sizeof(u32), 1, fp); |
1897 | len = le32_to_cpu(buf[0]); | ||
1898 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | ||
1899 | if (!c->u.name) { | ||
1900 | rc = -ENOMEM; | ||
1901 | goto bad; | ||
1902 | } | ||
1903 | rc = next_entry(c->u.name, fp, len); | ||
1904 | if (rc < 0) | ||
1905 | goto bad; | ||
1906 | c->u.name[len] = 0; | ||
1907 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1908 | if (rc) | 2846 | if (rc) |
1909 | goto bad; | 2847 | return rc; |
1910 | rc = context_read_and_validate(&c->context[1], p, fp); | 2848 | rc = put_entry(c->u.name, 1, len, fp); |
2849 | if (rc) | ||
2850 | return rc; | ||
2851 | rc = context_write(p, &c->context[0], fp); | ||
1911 | if (rc) | 2852 | if (rc) |
1912 | goto bad; | 2853 | return rc; |
2854 | rc = context_write(p, &c->context[1], fp); | ||
2855 | if (rc) | ||
2856 | return rc; | ||
1913 | break; | 2857 | break; |
1914 | case OCON_PORT: | 2858 | case OCON_PORT: |
1915 | rc = next_entry(buf, fp, sizeof(u32)*3); | 2859 | buf[0] = cpu_to_le32(c->u.port.protocol); |
1916 | if (rc < 0) | 2860 | buf[1] = cpu_to_le32(c->u.port.low_port); |
1917 | goto bad; | 2861 | buf[2] = cpu_to_le32(c->u.port.high_port); |
1918 | c->u.port.protocol = le32_to_cpu(buf[0]); | 2862 | rc = put_entry(buf, sizeof(u32), 3, fp); |
1919 | c->u.port.low_port = le32_to_cpu(buf[1]); | 2863 | if (rc) |
1920 | c->u.port.high_port = le32_to_cpu(buf[2]); | 2864 | return rc; |
1921 | rc = context_read_and_validate(&c->context[0], p, fp); | 2865 | rc = context_write(p, &c->context[0], fp); |
1922 | if (rc) | 2866 | if (rc) |
1923 | goto bad; | 2867 | return rc; |
1924 | break; | 2868 | break; |
1925 | case OCON_NODE: | 2869 | case OCON_NODE: |
1926 | rc = next_entry(nodebuf, fp, sizeof(u32) * 2); | 2870 | nodebuf[0] = c->u.node.addr; /* network order */ |
1927 | if (rc < 0) | 2871 | nodebuf[1] = c->u.node.mask; /* network order */ |
1928 | goto bad; | 2872 | rc = put_entry(nodebuf, sizeof(u32), 2, fp); |
1929 | c->u.node.addr = nodebuf[0]; /* network order */ | 2873 | if (rc) |
1930 | c->u.node.mask = nodebuf[1]; /* network order */ | 2874 | return rc; |
1931 | rc = context_read_and_validate(&c->context[0], p, fp); | 2875 | rc = context_write(p, &c->context[0], fp); |
1932 | if (rc) | 2876 | if (rc) |
1933 | goto bad; | 2877 | return rc; |
1934 | break; | 2878 | break; |
1935 | case OCON_FSUSE: | 2879 | case OCON_FSUSE: |
1936 | rc = next_entry(buf, fp, sizeof(u32)*2); | 2880 | buf[0] = cpu_to_le32(c->v.behavior); |
1937 | if (rc < 0) | 2881 | len = strlen(c->u.name); |
1938 | goto bad; | 2882 | buf[1] = cpu_to_le32(len); |
1939 | c->v.behavior = le32_to_cpu(buf[0]); | 2883 | rc = put_entry(buf, sizeof(u32), 2, fp); |
1940 | if (c->v.behavior > SECURITY_FS_USE_NONE) | 2884 | if (rc) |
1941 | goto bad; | 2885 | return rc; |
1942 | len = le32_to_cpu(buf[1]); | 2886 | rc = put_entry(c->u.name, 1, len, fp); |
1943 | c->u.name = kmalloc(len + 1, GFP_KERNEL); | 2887 | if (rc) |
1944 | if (!c->u.name) { | 2888 | return rc; |
1945 | rc = -ENOMEM; | 2889 | rc = context_write(p, &c->context[0], fp); |
1946 | goto bad; | ||
1947 | } | ||
1948 | rc = next_entry(c->u.name, fp, len); | ||
1949 | if (rc < 0) | ||
1950 | goto bad; | ||
1951 | c->u.name[len] = 0; | ||
1952 | rc = context_read_and_validate(&c->context[0], p, fp); | ||
1953 | if (rc) | 2890 | if (rc) |
1954 | goto bad; | 2891 | return rc; |
1955 | break; | 2892 | break; |
1956 | case OCON_NODE6: { | 2893 | case OCON_NODE6: |
1957 | int k; | 2894 | for (j = 0; j < 4; j++) |
1958 | 2895 | nodebuf[j] = c->u.node6.addr[j]; /* network order */ | |
1959 | rc = next_entry(nodebuf, fp, sizeof(u32) * 8); | 2896 | for (j = 0; j < 4; j++) |
1960 | if (rc < 0) | 2897 | nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */ |
1961 | goto bad; | 2898 | rc = put_entry(nodebuf, sizeof(u32), 8, fp); |
1962 | for (k = 0; k < 4; k++) | 2899 | if (rc) |
1963 | c->u.node6.addr[k] = nodebuf[k]; | 2900 | return rc; |
1964 | for (k = 0; k < 4; k++) | 2901 | rc = context_write(p, &c->context[0], fp); |
1965 | c->u.node6.mask[k] = nodebuf[k+4]; | 2902 | if (rc) |
1966 | if (context_read_and_validate(&c->context[0], p, fp)) | 2903 | return rc; |
1967 | goto bad; | ||
1968 | break; | 2904 | break; |
1969 | } | 2905 | } |
1970 | } | ||
1971 | } | 2906 | } |
1972 | } | 2907 | } |
2908 | return 0; | ||
2909 | } | ||
1973 | 2910 | ||
1974 | rc = next_entry(buf, fp, sizeof(u32)); | 2911 | static int genfs_write(struct policydb *p, void *fp) |
1975 | if (rc < 0) | 2912 | { |
1976 | goto bad; | 2913 | struct genfs *genfs; |
1977 | nel = le32_to_cpu(buf[0]); | 2914 | struct ocontext *c; |
1978 | genfs_p = NULL; | 2915 | size_t len; |
1979 | rc = -EINVAL; | 2916 | __le32 buf[1]; |
1980 | for (i = 0; i < nel; i++) { | 2917 | int rc; |
1981 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1982 | if (rc < 0) | ||
1983 | goto bad; | ||
1984 | len = le32_to_cpu(buf[0]); | ||
1985 | newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); | ||
1986 | if (!newgenfs) { | ||
1987 | rc = -ENOMEM; | ||
1988 | goto bad; | ||
1989 | } | ||
1990 | 2918 | ||
1991 | newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); | 2919 | len = 0; |
1992 | if (!newgenfs->fstype) { | 2920 | for (genfs = p->genfs; genfs; genfs = genfs->next) |
1993 | rc = -ENOMEM; | 2921 | len++; |
1994 | kfree(newgenfs); | 2922 | buf[0] = cpu_to_le32(len); |
1995 | goto bad; | 2923 | rc = put_entry(buf, sizeof(u32), 1, fp); |
1996 | } | 2924 | if (rc) |
1997 | rc = next_entry(newgenfs->fstype, fp, len); | 2925 | return rc; |
1998 | if (rc < 0) { | 2926 | for (genfs = p->genfs; genfs; genfs = genfs->next) { |
1999 | kfree(newgenfs->fstype); | 2927 | len = strlen(genfs->fstype); |
2000 | kfree(newgenfs); | 2928 | buf[0] = cpu_to_le32(len); |
2001 | goto bad; | 2929 | rc = put_entry(buf, sizeof(u32), 1, fp); |
2002 | } | 2930 | if (rc) |
2003 | newgenfs->fstype[len] = 0; | 2931 | return rc; |
2004 | for (genfs_p = NULL, genfs = p->genfs; genfs; | 2932 | rc = put_entry(genfs->fstype, 1, len, fp); |
2005 | genfs_p = genfs, genfs = genfs->next) { | 2933 | if (rc) |
2006 | if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { | 2934 | return rc; |
2007 | printk(KERN_ERR "SELinux: dup genfs " | 2935 | len = 0; |
2008 | "fstype %s\n", newgenfs->fstype); | 2936 | for (c = genfs->head; c; c = c->next) |
2009 | kfree(newgenfs->fstype); | 2937 | len++; |
2010 | kfree(newgenfs); | 2938 | buf[0] = cpu_to_le32(len); |
2011 | goto bad; | 2939 | rc = put_entry(buf, sizeof(u32), 1, fp); |
2012 | } | 2940 | if (rc) |
2013 | if (strcmp(newgenfs->fstype, genfs->fstype) < 0) | 2941 | return rc; |
2014 | break; | 2942 | for (c = genfs->head; c; c = c->next) { |
2943 | len = strlen(c->u.name); | ||
2944 | buf[0] = cpu_to_le32(len); | ||
2945 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2946 | if (rc) | ||
2947 | return rc; | ||
2948 | rc = put_entry(c->u.name, 1, len, fp); | ||
2949 | if (rc) | ||
2950 | return rc; | ||
2951 | buf[0] = cpu_to_le32(c->v.sclass); | ||
2952 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2953 | if (rc) | ||
2954 | return rc; | ||
2955 | rc = context_write(p, &c->context[0], fp); | ||
2956 | if (rc) | ||
2957 | return rc; | ||
2015 | } | 2958 | } |
2016 | newgenfs->next = genfs; | 2959 | } |
2017 | if (genfs_p) | 2960 | return 0; |
2018 | genfs_p->next = newgenfs; | 2961 | } |
2019 | else | ||
2020 | p->genfs = newgenfs; | ||
2021 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2022 | if (rc < 0) | ||
2023 | goto bad; | ||
2024 | nel2 = le32_to_cpu(buf[0]); | ||
2025 | for (j = 0; j < nel2; j++) { | ||
2026 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2027 | if (rc < 0) | ||
2028 | goto bad; | ||
2029 | len = le32_to_cpu(buf[0]); | ||
2030 | 2962 | ||
2031 | newc = kzalloc(sizeof(*newc), GFP_KERNEL); | 2963 | static int range_count(void *key, void *data, void *ptr) |
2032 | if (!newc) { | 2964 | { |
2033 | rc = -ENOMEM; | 2965 | int *cnt = ptr; |
2034 | goto bad; | 2966 | *cnt = *cnt + 1; |
2035 | } | ||
2036 | 2967 | ||
2037 | newc->u.name = kmalloc(len + 1, GFP_KERNEL); | 2968 | return 0; |
2038 | if (!newc->u.name) { | 2969 | } |
2039 | rc = -ENOMEM; | ||
2040 | goto bad_newc; | ||
2041 | } | ||
2042 | rc = next_entry(newc->u.name, fp, len); | ||
2043 | if (rc < 0) | ||
2044 | goto bad_newc; | ||
2045 | newc->u.name[len] = 0; | ||
2046 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2047 | if (rc < 0) | ||
2048 | goto bad_newc; | ||
2049 | newc->v.sclass = le32_to_cpu(buf[0]); | ||
2050 | if (context_read_and_validate(&newc->context[0], p, fp)) | ||
2051 | goto bad_newc; | ||
2052 | for (l = NULL, c = newgenfs->head; c; | ||
2053 | l = c, c = c->next) { | ||
2054 | if (!strcmp(newc->u.name, c->u.name) && | ||
2055 | (!c->v.sclass || !newc->v.sclass || | ||
2056 | newc->v.sclass == c->v.sclass)) { | ||
2057 | printk(KERN_ERR "SELinux: dup genfs " | ||
2058 | "entry (%s,%s)\n", | ||
2059 | newgenfs->fstype, c->u.name); | ||
2060 | goto bad_newc; | ||
2061 | } | ||
2062 | len = strlen(newc->u.name); | ||
2063 | len2 = strlen(c->u.name); | ||
2064 | if (len > len2) | ||
2065 | break; | ||
2066 | } | ||
2067 | 2970 | ||
2068 | newc->next = c; | 2971 | static int range_write_helper(void *key, void *data, void *ptr) |
2069 | if (l) | 2972 | { |
2070 | l->next = newc; | 2973 | __le32 buf[2]; |
2071 | else | 2974 | struct range_trans *rt = key; |
2072 | newgenfs->head = newc; | 2975 | struct mls_range *r = data; |
2073 | } | 2976 | struct policy_data *pd = ptr; |
2977 | void *fp = pd->fp; | ||
2978 | struct policydb *p = pd->p; | ||
2979 | int rc; | ||
2980 | |||
2981 | buf[0] = cpu_to_le32(rt->source_type); | ||
2982 | buf[1] = cpu_to_le32(rt->target_type); | ||
2983 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
2984 | if (rc) | ||
2985 | return rc; | ||
2986 | if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) { | ||
2987 | buf[0] = cpu_to_le32(rt->target_class); | ||
2988 | rc = put_entry(buf, sizeof(u32), 1, fp); | ||
2989 | if (rc) | ||
2990 | return rc; | ||
2074 | } | 2991 | } |
2992 | rc = mls_write_range_helper(r, fp); | ||
2993 | if (rc) | ||
2994 | return rc; | ||
2075 | 2995 | ||
2076 | if (p->policyvers >= POLICYDB_VERSION_MLS) { | 2996 | return 0; |
2077 | int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; | 2997 | } |
2078 | rc = next_entry(buf, fp, sizeof(u32)); | 2998 | |
2079 | if (rc < 0) | 2999 | static int range_write(struct policydb *p, void *fp) |
2080 | goto bad; | 3000 | { |
2081 | nel = le32_to_cpu(buf[0]); | 3001 | size_t nel; |
2082 | lrt = NULL; | 3002 | __le32 buf[1]; |
2083 | for (i = 0; i < nel; i++) { | 3003 | int rc; |
2084 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | 3004 | struct policy_data pd; |
2085 | if (!rt) { | 3005 | |
2086 | rc = -ENOMEM; | 3006 | pd.p = p; |
2087 | goto bad; | 3007 | pd.fp = fp; |
2088 | } | 3008 | |
2089 | if (lrt) | 3009 | /* count the number of entries in the hashtab */ |
2090 | lrt->next = rt; | 3010 | nel = 0; |
2091 | else | 3011 | rc = hashtab_map(p->range_tr, range_count, &nel); |
2092 | p->range_tr = rt; | 3012 | if (rc) |
2093 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | 3013 | return rc; |
2094 | if (rc < 0) | 3014 | |
2095 | goto bad; | 3015 | buf[0] = cpu_to_le32(nel); |
2096 | rt->source_type = le32_to_cpu(buf[0]); | 3016 | rc = put_entry(buf, sizeof(u32), 1, fp); |
2097 | rt->target_type = le32_to_cpu(buf[1]); | 3017 | if (rc) |
2098 | if (new_rangetr) { | 3018 | return rc; |
2099 | rc = next_entry(buf, fp, sizeof(u32)); | 3019 | |
2100 | if (rc < 0) | 3020 | /* actually write all of the entries */ |
2101 | goto bad; | 3021 | rc = hashtab_map(p->range_tr, range_write_helper, &pd); |
2102 | rt->target_class = le32_to_cpu(buf[0]); | 3022 | if (rc) |
2103 | } else | 3023 | return rc; |
2104 | rt->target_class = SECCLASS_PROCESS; | 3024 | |
2105 | if (!policydb_type_isvalid(p, rt->source_type) || | 3025 | return 0; |
2106 | !policydb_type_isvalid(p, rt->target_type) || | 3026 | } |
2107 | !policydb_class_isvalid(p, rt->target_class)) { | 3027 | |
2108 | rc = -EINVAL; | 3028 | /* |
2109 | goto bad; | 3029 | * Write the configuration data in a policy database |
2110 | } | 3030 | * structure to a policy database binary representation |
2111 | rc = mls_read_range_helper(&rt->target_range, fp); | 3031 | * file. |
2112 | if (rc) | 3032 | */ |
2113 | goto bad; | 3033 | int policydb_write(struct policydb *p, void *fp) |
2114 | if (!mls_range_isvalid(p, &rt->target_range)) { | 3034 | { |
2115 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | 3035 | unsigned int i, num_syms; |
2116 | goto bad; | 3036 | int rc; |
2117 | } | 3037 | __le32 buf[4]; |
2118 | lrt = rt; | 3038 | u32 config; |
2119 | } | 3039 | size_t len; |
3040 | struct policydb_compat_info *info; | ||
3041 | |||
3042 | /* | ||
3043 | * refuse to write policy older than compressed avtab | ||
3044 | * to simplify the writer. There are other tests dropped | ||
3045 | * since we assume this throughout the writer code. Be | ||
3046 | * careful if you ever try to remove this restriction | ||
3047 | */ | ||
3048 | if (p->policyvers < POLICYDB_VERSION_AVTAB) { | ||
3049 | printk(KERN_ERR "SELinux: refusing to write policy version %d." | ||
3050 | " Because it is less than version %d\n", p->policyvers, | ||
3051 | POLICYDB_VERSION_AVTAB); | ||
3052 | return -EINVAL; | ||
2120 | } | 3053 | } |
2121 | 3054 | ||
2122 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | 3055 | config = 0; |
2123 | if (!p->type_attr_map) | 3056 | if (p->mls_enabled) |
2124 | goto bad; | 3057 | config |= POLICYDB_CONFIG_MLS; |
2125 | 3058 | ||
2126 | for (i = 0; i < p->p_types.nprim; i++) { | 3059 | if (p->reject_unknown) |
2127 | ebitmap_init(&p->type_attr_map[i]); | 3060 | config |= REJECT_UNKNOWN; |
2128 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { | 3061 | if (p->allow_unknown) |
2129 | if (ebitmap_read(&p->type_attr_map[i], fp)) | 3062 | config |= ALLOW_UNKNOWN; |
2130 | goto bad; | 3063 | |
2131 | } | 3064 | /* Write the magic number and string identifiers. */ |
2132 | /* add the type itself as the degenerate case */ | 3065 | buf[0] = cpu_to_le32(POLICYDB_MAGIC); |
2133 | if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) | 3066 | len = strlen(POLICYDB_STRING); |
2134 | goto bad; | 3067 | buf[1] = cpu_to_le32(len); |
3068 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
3069 | if (rc) | ||
3070 | return rc; | ||
3071 | rc = put_entry(POLICYDB_STRING, 1, len, fp); | ||
3072 | if (rc) | ||
3073 | return rc; | ||
3074 | |||
3075 | /* Write the version, config, and table sizes. */ | ||
3076 | info = policydb_lookup_compat(p->policyvers); | ||
3077 | if (!info) { | ||
3078 | printk(KERN_ERR "SELinux: compatibility lookup failed for policy " | ||
3079 | "version %d", p->policyvers); | ||
3080 | return -EINVAL; | ||
2135 | } | 3081 | } |
2136 | 3082 | ||
2137 | rc = policydb_bounds_sanity_check(p); | 3083 | buf[0] = cpu_to_le32(p->policyvers); |
3084 | buf[1] = cpu_to_le32(config); | ||
3085 | buf[2] = cpu_to_le32(info->sym_num); | ||
3086 | buf[3] = cpu_to_le32(info->ocon_num); | ||
3087 | |||
3088 | rc = put_entry(buf, sizeof(u32), 4, fp); | ||
2138 | if (rc) | 3089 | if (rc) |
2139 | goto bad; | 3090 | return rc; |
2140 | 3091 | ||
2141 | rc = 0; | 3092 | if (p->policyvers >= POLICYDB_VERSION_POLCAP) { |
2142 | out: | 3093 | rc = ebitmap_write(&p->policycaps, fp); |
2143 | return rc; | 3094 | if (rc) |
2144 | bad_newc: | 3095 | return rc; |
2145 | ocontext_destroy(newc, OCON_FSUSE); | 3096 | } |
2146 | bad: | 3097 | |
2147 | if (!rc) | 3098 | if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) { |
2148 | rc = -EINVAL; | 3099 | rc = ebitmap_write(&p->permissive_map, fp); |
2149 | policydb_destroy(p); | 3100 | if (rc) |
2150 | goto out; | 3101 | return rc; |
3102 | } | ||
3103 | |||
3104 | num_syms = info->sym_num; | ||
3105 | for (i = 0; i < num_syms; i++) { | ||
3106 | struct policy_data pd; | ||
3107 | |||
3108 | pd.fp = fp; | ||
3109 | pd.p = p; | ||
3110 | |||
3111 | buf[0] = cpu_to_le32(p->symtab[i].nprim); | ||
3112 | buf[1] = cpu_to_le32(p->symtab[i].table->nel); | ||
3113 | |||
3114 | rc = put_entry(buf, sizeof(u32), 2, fp); | ||
3115 | if (rc) | ||
3116 | return rc; | ||
3117 | rc = hashtab_map(p->symtab[i].table, write_f[i], &pd); | ||
3118 | if (rc) | ||
3119 | return rc; | ||
3120 | } | ||
3121 | |||
3122 | rc = avtab_write(p, &p->te_avtab, fp); | ||
3123 | if (rc) | ||
3124 | return rc; | ||
3125 | |||
3126 | rc = cond_write_list(p, p->cond_list, fp); | ||
3127 | if (rc) | ||
3128 | return rc; | ||
3129 | |||
3130 | rc = role_trans_write(p->role_tr, fp); | ||
3131 | if (rc) | ||
3132 | return rc; | ||
3133 | |||
3134 | rc = role_allow_write(p->role_allow, fp); | ||
3135 | if (rc) | ||
3136 | return rc; | ||
3137 | |||
3138 | rc = ocontext_write(p, info, fp); | ||
3139 | if (rc) | ||
3140 | return rc; | ||
3141 | |||
3142 | rc = genfs_write(p, fp); | ||
3143 | if (rc) | ||
3144 | return rc; | ||
3145 | |||
3146 | rc = range_write(p, fp); | ||
3147 | if (rc) | ||
3148 | return rc; | ||
3149 | |||
3150 | for (i = 0; i < p->p_types.nprim; i++) { | ||
3151 | struct ebitmap *e = flex_array_get(p->type_attr_map_array, i); | ||
3152 | |||
3153 | BUG_ON(!e); | ||
3154 | rc = ebitmap_write(e, fp); | ||
3155 | if (rc) | ||
3156 | return rc; | ||
3157 | } | ||
3158 | |||
3159 | return 0; | ||
2151 | } | 3160 | } |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 55152d498b5..4e3ab9d0b31 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -24,9 +24,13 @@ | |||
24 | #ifndef _SS_POLICYDB_H_ | 24 | #ifndef _SS_POLICYDB_H_ |
25 | #define _SS_POLICYDB_H_ | 25 | #define _SS_POLICYDB_H_ |
26 | 26 | ||
27 | #include <linux/flex_array.h> | ||
28 | |||
27 | #include "symtab.h" | 29 | #include "symtab.h" |
28 | #include "avtab.h" | 30 | #include "avtab.h" |
29 | #include "sidtab.h" | 31 | #include "sidtab.h" |
32 | #include "ebitmap.h" | ||
33 | #include "mls_types.h" | ||
30 | #include "context.h" | 34 | #include "context.h" |
31 | #include "constraint.h" | 35 | #include "constraint.h" |
32 | 36 | ||
@@ -113,8 +117,6 @@ struct range_trans { | |||
113 | u32 source_type; | 117 | u32 source_type; |
114 | u32 target_type; | 118 | u32 target_type; |
115 | u32 target_class; | 119 | u32 target_class; |
116 | struct mls_range target_range; | ||
117 | struct range_trans *next; | ||
118 | }; | 120 | }; |
119 | 121 | ||
120 | /* Boolean data type */ | 122 | /* Boolean data type */ |
@@ -187,6 +189,8 @@ struct genfs { | |||
187 | 189 | ||
188 | /* The policy database */ | 190 | /* The policy database */ |
189 | struct policydb { | 191 | struct policydb { |
192 | int mls_enabled; | ||
193 | |||
190 | /* symbol tables */ | 194 | /* symbol tables */ |
191 | struct symtab symtab[SYM_NUM]; | 195 | struct symtab symtab[SYM_NUM]; |
192 | #define p_commons symtab[SYM_COMMONS] | 196 | #define p_commons symtab[SYM_COMMONS] |
@@ -199,21 +203,13 @@ struct policydb { | |||
199 | #define p_cats symtab[SYM_CATS] | 203 | #define p_cats symtab[SYM_CATS] |
200 | 204 | ||
201 | /* symbol names indexed by (value - 1) */ | 205 | /* symbol names indexed by (value - 1) */ |
202 | char **sym_val_to_name[SYM_NUM]; | 206 | struct flex_array *sym_val_to_name[SYM_NUM]; |
203 | #define p_common_val_to_name sym_val_to_name[SYM_COMMONS] | ||
204 | #define p_class_val_to_name sym_val_to_name[SYM_CLASSES] | ||
205 | #define p_role_val_to_name sym_val_to_name[SYM_ROLES] | ||
206 | #define p_type_val_to_name sym_val_to_name[SYM_TYPES] | ||
207 | #define p_user_val_to_name sym_val_to_name[SYM_USERS] | ||
208 | #define p_bool_val_to_name sym_val_to_name[SYM_BOOLS] | ||
209 | #define p_sens_val_to_name sym_val_to_name[SYM_LEVELS] | ||
210 | #define p_cat_val_to_name sym_val_to_name[SYM_CATS] | ||
211 | 207 | ||
212 | /* class, role, and user attributes indexed by (value - 1) */ | 208 | /* class, role, and user attributes indexed by (value - 1) */ |
213 | struct class_datum **class_val_to_struct; | 209 | struct class_datum **class_val_to_struct; |
214 | struct role_datum **role_val_to_struct; | 210 | struct role_datum **role_val_to_struct; |
215 | struct user_datum **user_val_to_struct; | 211 | struct user_datum **user_val_to_struct; |
216 | struct type_datum **type_val_to_struct; | 212 | struct flex_array *type_val_to_struct_array; |
217 | 213 | ||
218 | /* type enforcement access vectors and transitions */ | 214 | /* type enforcement access vectors and transitions */ |
219 | struct avtab te_avtab; | 215 | struct avtab te_avtab; |
@@ -240,21 +236,26 @@ struct policydb { | |||
240 | fixed labeling behavior. */ | 236 | fixed labeling behavior. */ |
241 | struct genfs *genfs; | 237 | struct genfs *genfs; |
242 | 238 | ||
243 | /* range transitions */ | 239 | /* range transitions table (range_trans_key -> mls_range) */ |
244 | struct range_trans *range_tr; | 240 | struct hashtab *range_tr; |
245 | 241 | ||
246 | /* type -> attribute reverse mapping */ | 242 | /* type -> attribute reverse mapping */ |
247 | struct ebitmap *type_attr_map; | 243 | struct flex_array *type_attr_map_array; |
248 | 244 | ||
249 | struct ebitmap policycaps; | 245 | struct ebitmap policycaps; |
250 | 246 | ||
251 | struct ebitmap permissive_map; | 247 | struct ebitmap permissive_map; |
252 | 248 | ||
249 | /* length of this policy when it was loaded */ | ||
250 | size_t len; | ||
251 | |||
253 | unsigned int policyvers; | 252 | unsigned int policyvers; |
254 | 253 | ||
255 | unsigned int reject_unknown : 1; | 254 | unsigned int reject_unknown : 1; |
256 | unsigned int allow_unknown : 1; | 255 | unsigned int allow_unknown : 1; |
257 | u32 *undefined_perms; | 256 | |
257 | u16 process_class; | ||
258 | u32 process_trans_perms; | ||
258 | }; | 259 | }; |
259 | 260 | ||
260 | extern void policydb_destroy(struct policydb *p); | 261 | extern void policydb_destroy(struct policydb *p); |
@@ -264,6 +265,7 @@ extern int policydb_class_isvalid(struct policydb *p, unsigned int class); | |||
264 | extern int policydb_type_isvalid(struct policydb *p, unsigned int type); | 265 | extern int policydb_type_isvalid(struct policydb *p, unsigned int type); |
265 | extern int policydb_role_isvalid(struct policydb *p, unsigned int role); | 266 | extern int policydb_role_isvalid(struct policydb *p, unsigned int role); |
266 | extern int policydb_read(struct policydb *p, void *fp); | 267 | extern int policydb_read(struct policydb *p, void *fp); |
268 | extern int policydb_write(struct policydb *p, void *fp); | ||
267 | 269 | ||
268 | #define PERM_SYMTAB_SIZE 32 | 270 | #define PERM_SYMTAB_SIZE 32 |
269 | 271 | ||
@@ -284,6 +286,11 @@ struct policy_file { | |||
284 | size_t len; | 286 | size_t len; |
285 | }; | 287 | }; |
286 | 288 | ||
289 | struct policy_data { | ||
290 | struct policydb *p; | ||
291 | void *fp; | ||
292 | }; | ||
293 | |||
287 | static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) | 294 | static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) |
288 | { | 295 | { |
289 | if (bytes > fp->len) | 296 | if (bytes > fp->len) |
@@ -295,5 +302,26 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) | |||
295 | return 0; | 302 | return 0; |
296 | } | 303 | } |
297 | 304 | ||
305 | static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp) | ||
306 | { | ||
307 | size_t len = bytes * num; | ||
308 | |||
309 | memcpy(fp->data, buf, len); | ||
310 | fp->data += len; | ||
311 | fp->len -= len; | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned int element_nr) | ||
317 | { | ||
318 | struct flex_array *fa = p->sym_val_to_name[sym_num]; | ||
319 | |||
320 | return flex_array_get_ptr(fa, element_nr); | ||
321 | } | ||
322 | |||
323 | extern u16 string_to_security_class(struct policydb *p, const char *name); | ||
324 | extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name); | ||
325 | |||
298 | #endif /* _SS_POLICYDB_H_ */ | 326 | #endif /* _SS_POLICYDB_H_ */ |
299 | 327 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 500e6f78e11..a03cfaf0ee0 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -22,6 +22,15 @@ | |||
22 | * | 22 | * |
23 | * Added validation of kernel classes and permissions | 23 | * Added validation of kernel classes and permissions |
24 | * | 24 | * |
25 | * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
26 | * | ||
27 | * Added support for bounds domain and audit messaged on masked permissions | ||
28 | * | ||
29 | * Updated: Guido Trentalancia <guido@trentalancia.com> | ||
30 | * | ||
31 | * Added support for runtime switching of the policy type | ||
32 | * | ||
33 | * Copyright (C) 2008, 2009 NEC Corporation | ||
25 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 34 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
26 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 35 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
27 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC | 36 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC |
@@ -41,6 +50,8 @@ | |||
41 | #include <linux/audit.h> | 50 | #include <linux/audit.h> |
42 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
43 | #include <linux/selinux.h> | 52 | #include <linux/selinux.h> |
53 | #include <linux/flex_array.h> | ||
54 | #include <linux/vmalloc.h> | ||
44 | #include <net/netlabel.h> | 55 | #include <net/netlabel.h> |
45 | 56 | ||
46 | #include "flask.h" | 57 | #include "flask.h" |
@@ -60,16 +71,10 @@ | |||
60 | #include "audit.h" | 71 | #include "audit.h" |
61 | 72 | ||
62 | extern void selnl_notify_policyload(u32 seqno); | 73 | extern void selnl_notify_policyload(u32 seqno); |
63 | unsigned int policydb_loaded_version; | ||
64 | 74 | ||
65 | int selinux_policycap_netpeer; | 75 | int selinux_policycap_netpeer; |
66 | int selinux_policycap_openperm; | 76 | int selinux_policycap_openperm; |
67 | 77 | ||
68 | /* | ||
69 | * This is declared in avc.c | ||
70 | */ | ||
71 | extern const struct selinux_class_perm selinux_class_perm; | ||
72 | |||
73 | static DEFINE_RWLOCK(policy_rwlock); | 78 | static DEFINE_RWLOCK(policy_rwlock); |
74 | 79 | ||
75 | static struct sidtab sidtab; | 80 | static struct sidtab sidtab; |
@@ -88,11 +93,156 @@ static u32 latest_granting; | |||
88 | static int context_struct_to_string(struct context *context, char **scontext, | 93 | static int context_struct_to_string(struct context *context, char **scontext, |
89 | u32 *scontext_len); | 94 | u32 *scontext_len); |
90 | 95 | ||
91 | static int context_struct_compute_av(struct context *scontext, | 96 | static void context_struct_compute_av(struct context *scontext, |
92 | struct context *tcontext, | 97 | struct context *tcontext, |
93 | u16 tclass, | 98 | u16 tclass, |
94 | u32 requested, | 99 | struct av_decision *avd); |
95 | struct av_decision *avd); | 100 | |
101 | struct selinux_mapping { | ||
102 | u16 value; /* policy value */ | ||
103 | unsigned num_perms; | ||
104 | u32 perms[sizeof(u32) * 8]; | ||
105 | }; | ||
106 | |||
107 | static struct selinux_mapping *current_mapping; | ||
108 | static u16 current_mapping_size; | ||
109 | |||
110 | static int selinux_set_mapping(struct policydb *pol, | ||
111 | struct security_class_mapping *map, | ||
112 | struct selinux_mapping **out_map_p, | ||
113 | u16 *out_map_size) | ||
114 | { | ||
115 | struct selinux_mapping *out_map = NULL; | ||
116 | size_t size = sizeof(struct selinux_mapping); | ||
117 | u16 i, j; | ||
118 | unsigned k; | ||
119 | bool print_unknown_handle = false; | ||
120 | |||
121 | /* Find number of classes in the input mapping */ | ||
122 | if (!map) | ||
123 | return -EINVAL; | ||
124 | i = 0; | ||
125 | while (map[i].name) | ||
126 | i++; | ||
127 | |||
128 | /* Allocate space for the class records, plus one for class zero */ | ||
129 | out_map = kcalloc(++i, size, GFP_ATOMIC); | ||
130 | if (!out_map) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | /* Store the raw class and permission values */ | ||
134 | j = 0; | ||
135 | while (map[j].name) { | ||
136 | struct security_class_mapping *p_in = map + (j++); | ||
137 | struct selinux_mapping *p_out = out_map + j; | ||
138 | |||
139 | /* An empty class string skips ahead */ | ||
140 | if (!strcmp(p_in->name, "")) { | ||
141 | p_out->num_perms = 0; | ||
142 | continue; | ||
143 | } | ||
144 | |||
145 | p_out->value = string_to_security_class(pol, p_in->name); | ||
146 | if (!p_out->value) { | ||
147 | printk(KERN_INFO | ||
148 | "SELinux: Class %s not defined in policy.\n", | ||
149 | p_in->name); | ||
150 | if (pol->reject_unknown) | ||
151 | goto err; | ||
152 | p_out->num_perms = 0; | ||
153 | print_unknown_handle = true; | ||
154 | continue; | ||
155 | } | ||
156 | |||
157 | k = 0; | ||
158 | while (p_in->perms && p_in->perms[k]) { | ||
159 | /* An empty permission string skips ahead */ | ||
160 | if (!*p_in->perms[k]) { | ||
161 | k++; | ||
162 | continue; | ||
163 | } | ||
164 | p_out->perms[k] = string_to_av_perm(pol, p_out->value, | ||
165 | p_in->perms[k]); | ||
166 | if (!p_out->perms[k]) { | ||
167 | printk(KERN_INFO | ||
168 | "SELinux: Permission %s in class %s not defined in policy.\n", | ||
169 | p_in->perms[k], p_in->name); | ||
170 | if (pol->reject_unknown) | ||
171 | goto err; | ||
172 | print_unknown_handle = true; | ||
173 | } | ||
174 | |||
175 | k++; | ||
176 | } | ||
177 | p_out->num_perms = k; | ||
178 | } | ||
179 | |||
180 | if (print_unknown_handle) | ||
181 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
182 | pol->allow_unknown ? "allowed" : "denied"); | ||
183 | |||
184 | *out_map_p = out_map; | ||
185 | *out_map_size = i; | ||
186 | return 0; | ||
187 | err: | ||
188 | kfree(out_map); | ||
189 | return -EINVAL; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Get real, policy values from mapped values | ||
194 | */ | ||
195 | |||
196 | static u16 unmap_class(u16 tclass) | ||
197 | { | ||
198 | if (tclass < current_mapping_size) | ||
199 | return current_mapping[tclass].value; | ||
200 | |||
201 | return tclass; | ||
202 | } | ||
203 | |||
204 | static void map_decision(u16 tclass, struct av_decision *avd, | ||
205 | int allow_unknown) | ||
206 | { | ||
207 | if (tclass < current_mapping_size) { | ||
208 | unsigned i, n = current_mapping[tclass].num_perms; | ||
209 | u32 result; | ||
210 | |||
211 | for (i = 0, result = 0; i < n; i++) { | ||
212 | if (avd->allowed & current_mapping[tclass].perms[i]) | ||
213 | result |= 1<<i; | ||
214 | if (allow_unknown && !current_mapping[tclass].perms[i]) | ||
215 | result |= 1<<i; | ||
216 | } | ||
217 | avd->allowed = result; | ||
218 | |||
219 | for (i = 0, result = 0; i < n; i++) | ||
220 | if (avd->auditallow & current_mapping[tclass].perms[i]) | ||
221 | result |= 1<<i; | ||
222 | avd->auditallow = result; | ||
223 | |||
224 | for (i = 0, result = 0; i < n; i++) { | ||
225 | if (avd->auditdeny & current_mapping[tclass].perms[i]) | ||
226 | result |= 1<<i; | ||
227 | if (!allow_unknown && !current_mapping[tclass].perms[i]) | ||
228 | result |= 1<<i; | ||
229 | } | ||
230 | /* | ||
231 | * In case the kernel has a bug and requests a permission | ||
232 | * between num_perms and the maximum permission number, we | ||
233 | * should audit that denial | ||
234 | */ | ||
235 | for (; i < (sizeof(u32)*8); i++) | ||
236 | result |= 1<<i; | ||
237 | avd->auditdeny = result; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | int security_mls_enabled(void) | ||
242 | { | ||
243 | return policydb.mls_enabled; | ||
244 | } | ||
245 | |||
96 | /* | 246 | /* |
97 | * Return the boolean value of a constraint expression | 247 | * Return the boolean value of a constraint expression |
98 | * when it is applied to the specified source and target | 248 | * when it is applied to the specified source and target |
@@ -126,15 +276,15 @@ static int constraint_expr_eval(struct context *scontext, | |||
126 | case CEXPR_AND: | 276 | case CEXPR_AND: |
127 | BUG_ON(sp < 1); | 277 | BUG_ON(sp < 1); |
128 | sp--; | 278 | sp--; |
129 | s[sp] &= s[sp+1]; | 279 | s[sp] &= s[sp + 1]; |
130 | break; | 280 | break; |
131 | case CEXPR_OR: | 281 | case CEXPR_OR: |
132 | BUG_ON(sp < 1); | 282 | BUG_ON(sp < 1); |
133 | sp--; | 283 | sp--; |
134 | s[sp] |= s[sp+1]; | 284 | s[sp] |= s[sp + 1]; |
135 | break; | 285 | break; |
136 | case CEXPR_ATTR: | 286 | case CEXPR_ATTR: |
137 | if (sp == (CEXPR_MAXDEPTH-1)) | 287 | if (sp == (CEXPR_MAXDEPTH - 1)) |
138 | return 0; | 288 | return 0; |
139 | switch (e->attr) { | 289 | switch (e->attr) { |
140 | case CEXPR_USER: | 290 | case CEXPR_USER: |
@@ -279,24 +429,119 @@ mls_ops: | |||
279 | } | 429 | } |
280 | 430 | ||
281 | /* | 431 | /* |
432 | * security_dump_masked_av - dumps masked permissions during | ||
433 | * security_compute_av due to RBAC, MLS/Constraint and Type bounds. | ||
434 | */ | ||
435 | static int dump_masked_av_helper(void *k, void *d, void *args) | ||
436 | { | ||
437 | struct perm_datum *pdatum = d; | ||
438 | char **permission_names = args; | ||
439 | |||
440 | BUG_ON(pdatum->value < 1 || pdatum->value > 32); | ||
441 | |||
442 | permission_names[pdatum->value - 1] = (char *)k; | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static void security_dump_masked_av(struct context *scontext, | ||
448 | struct context *tcontext, | ||
449 | u16 tclass, | ||
450 | u32 permissions, | ||
451 | const char *reason) | ||
452 | { | ||
453 | struct common_datum *common_dat; | ||
454 | struct class_datum *tclass_dat; | ||
455 | struct audit_buffer *ab; | ||
456 | char *tclass_name; | ||
457 | char *scontext_name = NULL; | ||
458 | char *tcontext_name = NULL; | ||
459 | char *permission_names[32]; | ||
460 | int index; | ||
461 | u32 length; | ||
462 | bool need_comma = false; | ||
463 | |||
464 | if (!permissions) | ||
465 | return; | ||
466 | |||
467 | tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1); | ||
468 | tclass_dat = policydb.class_val_to_struct[tclass - 1]; | ||
469 | common_dat = tclass_dat->comdatum; | ||
470 | |||
471 | /* init permission_names */ | ||
472 | if (common_dat && | ||
473 | hashtab_map(common_dat->permissions.table, | ||
474 | dump_masked_av_helper, permission_names) < 0) | ||
475 | goto out; | ||
476 | |||
477 | if (hashtab_map(tclass_dat->permissions.table, | ||
478 | dump_masked_av_helper, permission_names) < 0) | ||
479 | goto out; | ||
480 | |||
481 | /* get scontext/tcontext in text form */ | ||
482 | if (context_struct_to_string(scontext, | ||
483 | &scontext_name, &length) < 0) | ||
484 | goto out; | ||
485 | |||
486 | if (context_struct_to_string(tcontext, | ||
487 | &tcontext_name, &length) < 0) | ||
488 | goto out; | ||
489 | |||
490 | /* audit a message */ | ||
491 | ab = audit_log_start(current->audit_context, | ||
492 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
493 | if (!ab) | ||
494 | goto out; | ||
495 | |||
496 | audit_log_format(ab, "op=security_compute_av reason=%s " | ||
497 | "scontext=%s tcontext=%s tclass=%s perms=", | ||
498 | reason, scontext_name, tcontext_name, tclass_name); | ||
499 | |||
500 | for (index = 0; index < 32; index++) { | ||
501 | u32 mask = (1 << index); | ||
502 | |||
503 | if ((mask & permissions) == 0) | ||
504 | continue; | ||
505 | |||
506 | audit_log_format(ab, "%s%s", | ||
507 | need_comma ? "," : "", | ||
508 | permission_names[index] | ||
509 | ? permission_names[index] : "????"); | ||
510 | need_comma = true; | ||
511 | } | ||
512 | audit_log_end(ab); | ||
513 | out: | ||
514 | /* release scontext/tcontext */ | ||
515 | kfree(tcontext_name); | ||
516 | kfree(scontext_name); | ||
517 | |||
518 | return; | ||
519 | } | ||
520 | |||
521 | /* | ||
282 | * security_boundary_permission - drops violated permissions | 522 | * security_boundary_permission - drops violated permissions |
283 | * on boundary constraint. | 523 | * on boundary constraint. |
284 | */ | 524 | */ |
285 | static void type_attribute_bounds_av(struct context *scontext, | 525 | static void type_attribute_bounds_av(struct context *scontext, |
286 | struct context *tcontext, | 526 | struct context *tcontext, |
287 | u16 tclass, | 527 | u16 tclass, |
288 | u32 requested, | ||
289 | struct av_decision *avd) | 528 | struct av_decision *avd) |
290 | { | 529 | { |
291 | struct context lo_scontext; | 530 | struct context lo_scontext; |
292 | struct context lo_tcontext; | 531 | struct context lo_tcontext; |
293 | struct av_decision lo_avd; | 532 | struct av_decision lo_avd; |
294 | struct type_datum *source | 533 | struct type_datum *source; |
295 | = policydb.type_val_to_struct[scontext->type - 1]; | 534 | struct type_datum *target; |
296 | struct type_datum *target | ||
297 | = policydb.type_val_to_struct[tcontext->type - 1]; | ||
298 | u32 masked = 0; | 535 | u32 masked = 0; |
299 | 536 | ||
537 | source = flex_array_get_ptr(policydb.type_val_to_struct_array, | ||
538 | scontext->type - 1); | ||
539 | BUG_ON(!source); | ||
540 | |||
541 | target = flex_array_get_ptr(policydb.type_val_to_struct_array, | ||
542 | tcontext->type - 1); | ||
543 | BUG_ON(!target); | ||
544 | |||
300 | if (source->bounds) { | 545 | if (source->bounds) { |
301 | memset(&lo_avd, 0, sizeof(lo_avd)); | 546 | memset(&lo_avd, 0, sizeof(lo_avd)); |
302 | 547 | ||
@@ -306,7 +551,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
306 | context_struct_compute_av(&lo_scontext, | 551 | context_struct_compute_av(&lo_scontext, |
307 | tcontext, | 552 | tcontext, |
308 | tclass, | 553 | tclass, |
309 | requested, | ||
310 | &lo_avd); | 554 | &lo_avd); |
311 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 555 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
312 | return; /* no masked permission */ | 556 | return; /* no masked permission */ |
@@ -322,7 +566,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
322 | context_struct_compute_av(scontext, | 566 | context_struct_compute_av(scontext, |
323 | &lo_tcontext, | 567 | &lo_tcontext, |
324 | tclass, | 568 | tclass, |
325 | requested, | ||
326 | &lo_avd); | 569 | &lo_avd); |
327 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 570 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
328 | return; /* no masked permission */ | 571 | return; /* no masked permission */ |
@@ -339,7 +582,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
339 | context_struct_compute_av(&lo_scontext, | 582 | context_struct_compute_av(&lo_scontext, |
340 | &lo_tcontext, | 583 | &lo_tcontext, |
341 | tclass, | 584 | tclass, |
342 | requested, | ||
343 | &lo_avd); | 585 | &lo_avd); |
344 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 586 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
345 | return; /* no masked permission */ | 587 | return; /* no masked permission */ |
@@ -347,28 +589,12 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
347 | } | 589 | } |
348 | 590 | ||
349 | if (masked) { | 591 | if (masked) { |
350 | struct audit_buffer *ab; | ||
351 | char *stype_name | ||
352 | = policydb.p_type_val_to_name[source->value - 1]; | ||
353 | char *ttype_name | ||
354 | = policydb.p_type_val_to_name[target->value - 1]; | ||
355 | char *tclass_name | ||
356 | = policydb.p_class_val_to_name[tclass - 1]; | ||
357 | |||
358 | /* mask violated permissions */ | 592 | /* mask violated permissions */ |
359 | avd->allowed &= ~masked; | 593 | avd->allowed &= ~masked; |
360 | 594 | ||
361 | /* notice to userspace via audit message */ | 595 | /* audit masked permissions */ |
362 | ab = audit_log_start(current->audit_context, | 596 | security_dump_masked_av(scontext, tcontext, |
363 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | 597 | tclass, masked, "bounds"); |
364 | if (!ab) | ||
365 | return; | ||
366 | |||
367 | audit_log_format(ab, "av boundary violation: " | ||
368 | "source=%s target=%s tclass=%s", | ||
369 | stype_name, ttype_name, tclass_name); | ||
370 | avc_dump_av(ab, tclass, masked); | ||
371 | audit_log_end(ab); | ||
372 | } | 598 | } |
373 | } | 599 | } |
374 | 600 | ||
@@ -376,11 +602,10 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
376 | * Compute access vectors based on a context structure pair for | 602 | * Compute access vectors based on a context structure pair for |
377 | * the permissions in a particular class. | 603 | * the permissions in a particular class. |
378 | */ | 604 | */ |
379 | static int context_struct_compute_av(struct context *scontext, | 605 | static void context_struct_compute_av(struct context *scontext, |
380 | struct context *tcontext, | 606 | struct context *tcontext, |
381 | u16 tclass, | 607 | u16 tclass, |
382 | u32 requested, | 608 | struct av_decision *avd) |
383 | struct av_decision *avd) | ||
384 | { | 609 | { |
385 | struct constraint_node *constraint; | 610 | struct constraint_node *constraint; |
386 | struct role_allow *ra; | 611 | struct role_allow *ra; |
@@ -389,56 +614,17 @@ static int context_struct_compute_av(struct context *scontext, | |||
389 | struct class_datum *tclass_datum; | 614 | struct class_datum *tclass_datum; |
390 | struct ebitmap *sattr, *tattr; | 615 | struct ebitmap *sattr, *tattr; |
391 | struct ebitmap_node *snode, *tnode; | 616 | struct ebitmap_node *snode, *tnode; |
392 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
393 | unsigned int i, j; | 617 | unsigned int i, j; |
394 | 618 | ||
395 | /* | ||
396 | * Remap extended Netlink classes for old policy versions. | ||
397 | * Do this here rather than socket_type_to_security_class() | ||
398 | * in case a newer policy version is loaded, allowing sockets | ||
399 | * to remain in the correct class. | ||
400 | */ | ||
401 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
402 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
403 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
404 | tclass = SECCLASS_NETLINK_SOCKET; | ||
405 | |||
406 | /* | ||
407 | * Initialize the access vectors to the default values. | ||
408 | */ | ||
409 | avd->allowed = 0; | 619 | avd->allowed = 0; |
410 | avd->auditallow = 0; | 620 | avd->auditallow = 0; |
411 | avd->auditdeny = 0xffffffff; | 621 | avd->auditdeny = 0xffffffff; |
412 | avd->seqno = latest_granting; | ||
413 | avd->flags = 0; | ||
414 | |||
415 | /* | ||
416 | * Check for all the invalid cases. | ||
417 | * - tclass 0 | ||
418 | * - tclass > policy and > kernel | ||
419 | * - tclass > policy but is a userspace class | ||
420 | * - tclass > policy but we do not allow unknowns | ||
421 | */ | ||
422 | if (unlikely(!tclass)) | ||
423 | goto inval_class; | ||
424 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
425 | if (tclass > kdefs->cts_len || | ||
426 | !kdefs->class_to_string[tclass] || | ||
427 | !policydb.allow_unknown) | ||
428 | goto inval_class; | ||
429 | 622 | ||
430 | /* | 623 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { |
431 | * Kernel class and we allow unknown so pad the allow decision | 624 | if (printk_ratelimit()) |
432 | * the pad will be all 1 for unknown classes. | 625 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); |
433 | */ | 626 | return; |
434 | if (tclass <= kdefs->cts_len && policydb.allow_unknown) | 627 | } |
435 | avd->allowed = policydb.undefined_perms[tclass - 1]; | ||
436 | |||
437 | /* | ||
438 | * Not in policy. Since decision is completed (all 1 or all 0) return. | ||
439 | */ | ||
440 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
441 | return 0; | ||
442 | 628 | ||
443 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 629 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; |
444 | 630 | ||
@@ -448,8 +634,10 @@ static int context_struct_compute_av(struct context *scontext, | |||
448 | */ | 634 | */ |
449 | avkey.target_class = tclass; | 635 | avkey.target_class = tclass; |
450 | avkey.specified = AVTAB_AV; | 636 | avkey.specified = AVTAB_AV; |
451 | sattr = &policydb.type_attr_map[scontext->type - 1]; | 637 | sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1); |
452 | tattr = &policydb.type_attr_map[tcontext->type - 1]; | 638 | BUG_ON(!sattr); |
639 | tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1); | ||
640 | BUG_ON(!tattr); | ||
453 | ebitmap_for_each_positive_bit(sattr, snode, i) { | 641 | ebitmap_for_each_positive_bit(sattr, snode, i) { |
454 | ebitmap_for_each_positive_bit(tattr, tnode, j) { | 642 | ebitmap_for_each_positive_bit(tattr, tnode, j) { |
455 | avkey.source_type = i + 1; | 643 | avkey.source_type = i + 1; |
@@ -480,7 +668,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
480 | if ((constraint->permissions & (avd->allowed)) && | 668 | if ((constraint->permissions & (avd->allowed)) && |
481 | !constraint_expr_eval(scontext, tcontext, NULL, | 669 | !constraint_expr_eval(scontext, tcontext, NULL, |
482 | constraint->expr)) { | 670 | constraint->expr)) { |
483 | avd->allowed = (avd->allowed) & ~(constraint->permissions); | 671 | avd->allowed &= ~(constraint->permissions); |
484 | } | 672 | } |
485 | constraint = constraint->next; | 673 | constraint = constraint->next; |
486 | } | 674 | } |
@@ -490,8 +678,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
490 | * role is changing, then check the (current_role, new_role) | 678 | * role is changing, then check the (current_role, new_role) |
491 | * pair. | 679 | * pair. |
492 | */ | 680 | */ |
493 | if (tclass == SECCLASS_PROCESS && | 681 | if (tclass == policydb.process_class && |
494 | (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && | 682 | (avd->allowed & policydb.process_trans_perms) && |
495 | scontext->role != tcontext->role) { | 683 | scontext->role != tcontext->role) { |
496 | for (ra = policydb.role_allow; ra; ra = ra->next) { | 684 | for (ra = policydb.role_allow; ra; ra = ra->next) { |
497 | if (scontext->role == ra->role && | 685 | if (scontext->role == ra->role && |
@@ -499,8 +687,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
499 | break; | 687 | break; |
500 | } | 688 | } |
501 | if (!ra) | 689 | if (!ra) |
502 | avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | | 690 | avd->allowed &= ~policydb.process_trans_perms; |
503 | PROCESS__DYNTRANSITION); | ||
504 | } | 691 | } |
505 | 692 | ||
506 | /* | 693 | /* |
@@ -509,24 +696,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
509 | * permission and notice it to userspace via audit. | 696 | * permission and notice it to userspace via audit. |
510 | */ | 697 | */ |
511 | type_attribute_bounds_av(scontext, tcontext, | 698 | type_attribute_bounds_av(scontext, tcontext, |
512 | tclass, requested, avd); | 699 | tclass, avd); |
513 | |||
514 | return 0; | ||
515 | |||
516 | inval_class: | ||
517 | if (!tclass || tclass > kdefs->cts_len || | ||
518 | !kdefs->class_to_string[tclass]) { | ||
519 | if (printk_ratelimit()) | ||
520 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | ||
521 | __func__, tclass); | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * Known to the kernel, but not to the policy. | ||
527 | * Handle as a denial (allowed is 0). | ||
528 | */ | ||
529 | return 0; | ||
530 | } | 700 | } |
531 | 701 | ||
532 | static int security_validtrans_handle_fail(struct context *ocontext, | 702 | static int security_validtrans_handle_fail(struct context *ocontext, |
@@ -537,16 +707,16 @@ static int security_validtrans_handle_fail(struct context *ocontext, | |||
537 | char *o = NULL, *n = NULL, *t = NULL; | 707 | char *o = NULL, *n = NULL, *t = NULL; |
538 | u32 olen, nlen, tlen; | 708 | u32 olen, nlen, tlen; |
539 | 709 | ||
540 | if (context_struct_to_string(ocontext, &o, &olen) < 0) | 710 | if (context_struct_to_string(ocontext, &o, &olen)) |
541 | goto out; | 711 | goto out; |
542 | if (context_struct_to_string(ncontext, &n, &nlen) < 0) | 712 | if (context_struct_to_string(ncontext, &n, &nlen)) |
543 | goto out; | 713 | goto out; |
544 | if (context_struct_to_string(tcontext, &t, &tlen) < 0) | 714 | if (context_struct_to_string(tcontext, &t, &tlen)) |
545 | goto out; | 715 | goto out; |
546 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 716 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
547 | "security_validate_transition: denied for" | 717 | "security_validate_transition: denied for" |
548 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", | 718 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", |
549 | o, n, t, policydb.p_class_val_to_name[tclass-1]); | 719 | o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); |
550 | out: | 720 | out: |
551 | kfree(o); | 721 | kfree(o); |
552 | kfree(n); | 722 | kfree(n); |
@@ -558,13 +728,14 @@ out: | |||
558 | } | 728 | } |
559 | 729 | ||
560 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 730 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, |
561 | u16 tclass) | 731 | u16 orig_tclass) |
562 | { | 732 | { |
563 | struct context *ocontext; | 733 | struct context *ocontext; |
564 | struct context *ncontext; | 734 | struct context *ncontext; |
565 | struct context *tcontext; | 735 | struct context *tcontext; |
566 | struct class_datum *tclass_datum; | 736 | struct class_datum *tclass_datum; |
567 | struct constraint_node *constraint; | 737 | struct constraint_node *constraint; |
738 | u16 tclass; | ||
568 | int rc = 0; | 739 | int rc = 0; |
569 | 740 | ||
570 | if (!ss_initialized) | 741 | if (!ss_initialized) |
@@ -572,16 +743,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | |||
572 | 743 | ||
573 | read_lock(&policy_rwlock); | 744 | read_lock(&policy_rwlock); |
574 | 745 | ||
575 | /* | 746 | tclass = unmap_class(orig_tclass); |
576 | * Remap extended Netlink classes for old policy versions. | ||
577 | * Do this here rather than socket_type_to_security_class() | ||
578 | * in case a newer policy version is loaded, allowing sockets | ||
579 | * to remain in the correct class. | ||
580 | */ | ||
581 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
582 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
583 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
584 | tclass = SECCLASS_NETLINK_SOCKET; | ||
585 | 747 | ||
586 | if (!tclass || tclass > policydb.p_classes.nprim) { | 748 | if (!tclass || tclass > policydb.p_classes.nprim) { |
587 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | 749 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", |
@@ -645,10 +807,11 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
645 | struct context *old_context, *new_context; | 807 | struct context *old_context, *new_context; |
646 | struct type_datum *type; | 808 | struct type_datum *type; |
647 | int index; | 809 | int index; |
648 | int rc = -EINVAL; | 810 | int rc; |
649 | 811 | ||
650 | read_lock(&policy_rwlock); | 812 | read_lock(&policy_rwlock); |
651 | 813 | ||
814 | rc = -EINVAL; | ||
652 | old_context = sidtab_search(&sidtab, old_sid); | 815 | old_context = sidtab_search(&sidtab, old_sid); |
653 | if (!old_context) { | 816 | if (!old_context) { |
654 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", | 817 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", |
@@ -656,6 +819,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
656 | goto out; | 819 | goto out; |
657 | } | 820 | } |
658 | 821 | ||
822 | rc = -EINVAL; | ||
659 | new_context = sidtab_search(&sidtab, new_sid); | 823 | new_context = sidtab_search(&sidtab, new_sid); |
660 | if (!new_context) { | 824 | if (!new_context) { |
661 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", | 825 | printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", |
@@ -663,93 +827,165 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
663 | goto out; | 827 | goto out; |
664 | } | 828 | } |
665 | 829 | ||
666 | /* type/domain unchaned */ | 830 | rc = 0; |
667 | if (old_context->type == new_context->type) { | 831 | /* type/domain unchanged */ |
668 | rc = 0; | 832 | if (old_context->type == new_context->type) |
669 | goto out; | 833 | goto out; |
670 | } | ||
671 | 834 | ||
672 | index = new_context->type; | 835 | index = new_context->type; |
673 | while (true) { | 836 | while (true) { |
674 | type = policydb.type_val_to_struct[index - 1]; | 837 | type = flex_array_get_ptr(policydb.type_val_to_struct_array, |
838 | index - 1); | ||
675 | BUG_ON(!type); | 839 | BUG_ON(!type); |
676 | 840 | ||
677 | /* not bounded anymore */ | 841 | /* not bounded anymore */ |
678 | if (!type->bounds) { | 842 | rc = -EPERM; |
679 | rc = -EPERM; | 843 | if (!type->bounds) |
680 | break; | 844 | break; |
681 | } | ||
682 | 845 | ||
683 | /* @newsid is bounded by @oldsid */ | 846 | /* @newsid is bounded by @oldsid */ |
684 | if (type->bounds == old_context->type) { | 847 | rc = 0; |
685 | rc = 0; | 848 | if (type->bounds == old_context->type) |
686 | break; | 849 | break; |
687 | } | 850 | |
688 | index = type->bounds; | 851 | index = type->bounds; |
689 | } | 852 | } |
853 | |||
854 | if (rc) { | ||
855 | char *old_name = NULL; | ||
856 | char *new_name = NULL; | ||
857 | u32 length; | ||
858 | |||
859 | if (!context_struct_to_string(old_context, | ||
860 | &old_name, &length) && | ||
861 | !context_struct_to_string(new_context, | ||
862 | &new_name, &length)) { | ||
863 | audit_log(current->audit_context, | ||
864 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
865 | "op=security_bounded_transition " | ||
866 | "result=denied " | ||
867 | "oldcontext=%s newcontext=%s", | ||
868 | old_name, new_name); | ||
869 | } | ||
870 | kfree(new_name); | ||
871 | kfree(old_name); | ||
872 | } | ||
690 | out: | 873 | out: |
691 | read_unlock(&policy_rwlock); | 874 | read_unlock(&policy_rwlock); |
692 | 875 | ||
693 | return rc; | 876 | return rc; |
694 | } | 877 | } |
695 | 878 | ||
879 | static void avd_init(struct av_decision *avd) | ||
880 | { | ||
881 | avd->allowed = 0; | ||
882 | avd->auditallow = 0; | ||
883 | avd->auditdeny = 0xffffffff; | ||
884 | avd->seqno = latest_granting; | ||
885 | avd->flags = 0; | ||
886 | } | ||
887 | |||
696 | 888 | ||
697 | /** | 889 | /** |
698 | * security_compute_av - Compute access vector decisions. | 890 | * security_compute_av - Compute access vector decisions. |
699 | * @ssid: source security identifier | 891 | * @ssid: source security identifier |
700 | * @tsid: target security identifier | 892 | * @tsid: target security identifier |
701 | * @tclass: target security class | 893 | * @tclass: target security class |
702 | * @requested: requested permissions | ||
703 | * @avd: access vector decisions | 894 | * @avd: access vector decisions |
704 | * | 895 | * |
705 | * Compute a set of access vector decisions based on the | 896 | * Compute a set of access vector decisions based on the |
706 | * SID pair (@ssid, @tsid) for the permissions in @tclass. | 897 | * SID pair (@ssid, @tsid) for the permissions in @tclass. |
707 | * Return -%EINVAL if any of the parameters are invalid or %0 | ||
708 | * if the access vector decisions were computed successfully. | ||
709 | */ | 898 | */ |
710 | int security_compute_av(u32 ssid, | 899 | void security_compute_av(u32 ssid, |
711 | u32 tsid, | 900 | u32 tsid, |
712 | u16 tclass, | 901 | u16 orig_tclass, |
713 | u32 requested, | 902 | struct av_decision *avd) |
714 | struct av_decision *avd) | ||
715 | { | 903 | { |
904 | u16 tclass; | ||
716 | struct context *scontext = NULL, *tcontext = NULL; | 905 | struct context *scontext = NULL, *tcontext = NULL; |
717 | int rc = 0; | ||
718 | |||
719 | if (!ss_initialized) { | ||
720 | avd->allowed = 0xffffffff; | ||
721 | avd->auditallow = 0; | ||
722 | avd->auditdeny = 0xffffffff; | ||
723 | avd->seqno = latest_granting; | ||
724 | return 0; | ||
725 | } | ||
726 | 906 | ||
727 | read_lock(&policy_rwlock); | 907 | read_lock(&policy_rwlock); |
908 | avd_init(avd); | ||
909 | if (!ss_initialized) | ||
910 | goto allow; | ||
728 | 911 | ||
729 | scontext = sidtab_search(&sidtab, ssid); | 912 | scontext = sidtab_search(&sidtab, ssid); |
730 | if (!scontext) { | 913 | if (!scontext) { |
731 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 914 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
732 | __func__, ssid); | 915 | __func__, ssid); |
733 | rc = -EINVAL; | ||
734 | goto out; | 916 | goto out; |
735 | } | 917 | } |
918 | |||
919 | /* permissive domain? */ | ||
920 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
921 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
922 | |||
736 | tcontext = sidtab_search(&sidtab, tsid); | 923 | tcontext = sidtab_search(&sidtab, tsid); |
737 | if (!tcontext) { | 924 | if (!tcontext) { |
738 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 925 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
739 | __func__, tsid); | 926 | __func__, tsid); |
740 | rc = -EINVAL; | ||
741 | goto out; | 927 | goto out; |
742 | } | 928 | } |
743 | 929 | ||
744 | rc = context_struct_compute_av(scontext, tcontext, tclass, | 930 | tclass = unmap_class(orig_tclass); |
745 | requested, avd); | 931 | if (unlikely(orig_tclass && !tclass)) { |
932 | if (policydb.allow_unknown) | ||
933 | goto allow; | ||
934 | goto out; | ||
935 | } | ||
936 | context_struct_compute_av(scontext, tcontext, tclass, avd); | ||
937 | map_decision(orig_tclass, avd, policydb.allow_unknown); | ||
938 | out: | ||
939 | read_unlock(&policy_rwlock); | ||
940 | return; | ||
941 | allow: | ||
942 | avd->allowed = 0xffffffff; | ||
943 | goto out; | ||
944 | } | ||
945 | |||
946 | void security_compute_av_user(u32 ssid, | ||
947 | u32 tsid, | ||
948 | u16 tclass, | ||
949 | struct av_decision *avd) | ||
950 | { | ||
951 | struct context *scontext = NULL, *tcontext = NULL; | ||
952 | |||
953 | read_lock(&policy_rwlock); | ||
954 | avd_init(avd); | ||
955 | if (!ss_initialized) | ||
956 | goto allow; | ||
957 | |||
958 | scontext = sidtab_search(&sidtab, ssid); | ||
959 | if (!scontext) { | ||
960 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
961 | __func__, ssid); | ||
962 | goto out; | ||
963 | } | ||
746 | 964 | ||
747 | /* permissive domain? */ | 965 | /* permissive domain? */ |
748 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | 966 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) |
749 | avd->flags |= AVD_FLAGS_PERMISSIVE; | 967 | avd->flags |= AVD_FLAGS_PERMISSIVE; |
750 | out: | 968 | |
969 | tcontext = sidtab_search(&sidtab, tsid); | ||
970 | if (!tcontext) { | ||
971 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
972 | __func__, tsid); | ||
973 | goto out; | ||
974 | } | ||
975 | |||
976 | if (unlikely(!tclass)) { | ||
977 | if (policydb.allow_unknown) | ||
978 | goto allow; | ||
979 | goto out; | ||
980 | } | ||
981 | |||
982 | context_struct_compute_av(scontext, tcontext, tclass, avd); | ||
983 | out: | ||
751 | read_unlock(&policy_rwlock); | 984 | read_unlock(&policy_rwlock); |
752 | return rc; | 985 | return; |
986 | allow: | ||
987 | avd->allowed = 0xffffffff; | ||
988 | goto out; | ||
753 | } | 989 | } |
754 | 990 | ||
755 | /* | 991 | /* |
@@ -763,7 +999,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
763 | { | 999 | { |
764 | char *scontextp; | 1000 | char *scontextp; |
765 | 1001 | ||
766 | *scontext = NULL; | 1002 | if (scontext) |
1003 | *scontext = NULL; | ||
767 | *scontext_len = 0; | 1004 | *scontext_len = 0; |
768 | 1005 | ||
769 | if (context->len) { | 1006 | if (context->len) { |
@@ -775,11 +1012,14 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
775 | } | 1012 | } |
776 | 1013 | ||
777 | /* Compute the size of the context. */ | 1014 | /* Compute the size of the context. */ |
778 | *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1; | 1015 | *scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1; |
779 | *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1; | 1016 | *scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1; |
780 | *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1; | 1017 | *scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1; |
781 | *scontext_len += mls_compute_context_len(context); | 1018 | *scontext_len += mls_compute_context_len(context); |
782 | 1019 | ||
1020 | if (!scontext) | ||
1021 | return 0; | ||
1022 | |||
783 | /* Allocate space for the context; caller must free this space. */ | 1023 | /* Allocate space for the context; caller must free this space. */ |
784 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); | 1024 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); |
785 | if (!scontextp) | 1025 | if (!scontextp) |
@@ -790,12 +1030,12 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
790 | * Copy the user name, role name and type name into the context. | 1030 | * Copy the user name, role name and type name into the context. |
791 | */ | 1031 | */ |
792 | sprintf(scontextp, "%s:%s:%s", | 1032 | sprintf(scontextp, "%s:%s:%s", |
793 | policydb.p_user_val_to_name[context->user - 1], | 1033 | sym_name(&policydb, SYM_USERS, context->user - 1), |
794 | policydb.p_role_val_to_name[context->role - 1], | 1034 | sym_name(&policydb, SYM_ROLES, context->role - 1), |
795 | policydb.p_type_val_to_name[context->type - 1]); | 1035 | sym_name(&policydb, SYM_TYPES, context->type - 1)); |
796 | scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) + | 1036 | scontextp += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + |
797 | 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) + | 1037 | 1 + strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + |
798 | 1 + strlen(policydb.p_type_val_to_name[context->type - 1]); | 1038 | 1 + strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)); |
799 | 1039 | ||
800 | mls_sid_to_context(context, &scontextp); | 1040 | mls_sid_to_context(context, &scontextp); |
801 | 1041 | ||
@@ -819,7 +1059,8 @@ static int security_sid_to_context_core(u32 sid, char **scontext, | |||
819 | struct context *context; | 1059 | struct context *context; |
820 | int rc = 0; | 1060 | int rc = 0; |
821 | 1061 | ||
822 | *scontext = NULL; | 1062 | if (scontext) |
1063 | *scontext = NULL; | ||
823 | *scontext_len = 0; | 1064 | *scontext_len = 0; |
824 | 1065 | ||
825 | if (!ss_initialized) { | 1066 | if (!ss_initialized) { |
@@ -827,6 +1068,8 @@ static int security_sid_to_context_core(u32 sid, char **scontext, | |||
827 | char *scontextp; | 1068 | char *scontextp; |
828 | 1069 | ||
829 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; | 1070 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; |
1071 | if (!scontext) | ||
1072 | goto out; | ||
830 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); | 1073 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); |
831 | if (!scontextp) { | 1074 | if (!scontextp) { |
832 | rc = -ENOMEM; | 1075 | rc = -ENOMEM; |
@@ -951,16 +1194,13 @@ static int string_to_context_struct(struct policydb *pol, | |||
951 | if (rc) | 1194 | if (rc) |
952 | goto out; | 1195 | goto out; |
953 | 1196 | ||
954 | if ((p - scontext) < scontext_len) { | 1197 | rc = -EINVAL; |
955 | rc = -EINVAL; | 1198 | if ((p - scontext) < scontext_len) |
956 | goto out; | 1199 | goto out; |
957 | } | ||
958 | 1200 | ||
959 | /* Check the validity of the new context. */ | 1201 | /* Check the validity of the new context. */ |
960 | if (!policydb_context_isvalid(pol, ctx)) { | 1202 | if (!policydb_context_isvalid(pol, ctx)) |
961 | rc = -EINVAL; | ||
962 | goto out; | 1203 | goto out; |
963 | } | ||
964 | rc = 0; | 1204 | rc = 0; |
965 | out: | 1205 | out: |
966 | if (rc) | 1206 | if (rc) |
@@ -991,7 +1231,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
991 | *sid = SECSID_NULL; | 1231 | *sid = SECSID_NULL; |
992 | 1232 | ||
993 | /* Copy the string so that we can modify the copy as we parse it. */ | 1233 | /* Copy the string so that we can modify the copy as we parse it. */ |
994 | scontext2 = kmalloc(scontext_len+1, gfp_flags); | 1234 | scontext2 = kmalloc(scontext_len + 1, gfp_flags); |
995 | if (!scontext2) | 1235 | if (!scontext2) |
996 | return -ENOMEM; | 1236 | return -ENOMEM; |
997 | memcpy(scontext2, scontext, scontext_len); | 1237 | memcpy(scontext2, scontext, scontext_len); |
@@ -999,27 +1239,26 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, | |||
999 | 1239 | ||
1000 | if (force) { | 1240 | if (force) { |
1001 | /* Save another copy for storing in uninterpreted form */ | 1241 | /* Save another copy for storing in uninterpreted form */ |
1242 | rc = -ENOMEM; | ||
1002 | str = kstrdup(scontext2, gfp_flags); | 1243 | str = kstrdup(scontext2, gfp_flags); |
1003 | if (!str) { | 1244 | if (!str) |
1004 | kfree(scontext2); | 1245 | goto out; |
1005 | return -ENOMEM; | ||
1006 | } | ||
1007 | } | 1246 | } |
1008 | 1247 | ||
1009 | read_lock(&policy_rwlock); | 1248 | read_lock(&policy_rwlock); |
1010 | rc = string_to_context_struct(&policydb, &sidtab, | 1249 | rc = string_to_context_struct(&policydb, &sidtab, scontext2, |
1011 | scontext2, scontext_len, | 1250 | scontext_len, &context, def_sid); |
1012 | &context, def_sid); | ||
1013 | if (rc == -EINVAL && force) { | 1251 | if (rc == -EINVAL && force) { |
1014 | context.str = str; | 1252 | context.str = str; |
1015 | context.len = scontext_len; | 1253 | context.len = scontext_len; |
1016 | str = NULL; | 1254 | str = NULL; |
1017 | } else if (rc) | 1255 | } else if (rc) |
1018 | goto out; | 1256 | goto out_unlock; |
1019 | rc = sidtab_context_to_sid(&sidtab, &context, sid); | 1257 | rc = sidtab_context_to_sid(&sidtab, &context, sid); |
1020 | context_destroy(&context); | 1258 | context_destroy(&context); |
1021 | out: | 1259 | out_unlock: |
1022 | read_unlock(&policy_rwlock); | 1260 | read_unlock(&policy_rwlock); |
1261 | out: | ||
1023 | kfree(scontext2); | 1262 | kfree(scontext2); |
1024 | kfree(str); | 1263 | kfree(str); |
1025 | return rc; | 1264 | return rc; |
@@ -1083,18 +1322,18 @@ static int compute_sid_handle_invalid_context( | |||
1083 | char *s = NULL, *t = NULL, *n = NULL; | 1322 | char *s = NULL, *t = NULL, *n = NULL; |
1084 | u32 slen, tlen, nlen; | 1323 | u32 slen, tlen, nlen; |
1085 | 1324 | ||
1086 | if (context_struct_to_string(scontext, &s, &slen) < 0) | 1325 | if (context_struct_to_string(scontext, &s, &slen)) |
1087 | goto out; | 1326 | goto out; |
1088 | if (context_struct_to_string(tcontext, &t, &tlen) < 0) | 1327 | if (context_struct_to_string(tcontext, &t, &tlen)) |
1089 | goto out; | 1328 | goto out; |
1090 | if (context_struct_to_string(newcontext, &n, &nlen) < 0) | 1329 | if (context_struct_to_string(newcontext, &n, &nlen)) |
1091 | goto out; | 1330 | goto out; |
1092 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 1331 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
1093 | "security_compute_sid: invalid context %s" | 1332 | "security_compute_sid: invalid context %s" |
1094 | " for scontext=%s" | 1333 | " for scontext=%s" |
1095 | " tcontext=%s" | 1334 | " tcontext=%s" |
1096 | " tclass=%s", | 1335 | " tclass=%s", |
1097 | n, s, t, policydb.p_class_val_to_name[tclass-1]); | 1336 | n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); |
1098 | out: | 1337 | out: |
1099 | kfree(s); | 1338 | kfree(s); |
1100 | kfree(t); | 1339 | kfree(t); |
@@ -1106,20 +1345,22 @@ out: | |||
1106 | 1345 | ||
1107 | static int security_compute_sid(u32 ssid, | 1346 | static int security_compute_sid(u32 ssid, |
1108 | u32 tsid, | 1347 | u32 tsid, |
1109 | u16 tclass, | 1348 | u16 orig_tclass, |
1110 | u32 specified, | 1349 | u32 specified, |
1111 | u32 *out_sid) | 1350 | u32 *out_sid, |
1351 | bool kern) | ||
1112 | { | 1352 | { |
1113 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1353 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1114 | struct role_trans *roletr = NULL; | 1354 | struct role_trans *roletr = NULL; |
1115 | struct avtab_key avkey; | 1355 | struct avtab_key avkey; |
1116 | struct avtab_datum *avdatum; | 1356 | struct avtab_datum *avdatum; |
1117 | struct avtab_node *node; | 1357 | struct avtab_node *node; |
1358 | u16 tclass; | ||
1118 | int rc = 0; | 1359 | int rc = 0; |
1119 | 1360 | ||
1120 | if (!ss_initialized) { | 1361 | if (!ss_initialized) { |
1121 | switch (tclass) { | 1362 | switch (orig_tclass) { |
1122 | case SECCLASS_PROCESS: | 1363 | case SECCLASS_PROCESS: /* kernel value */ |
1123 | *out_sid = ssid; | 1364 | *out_sid = ssid; |
1124 | break; | 1365 | break; |
1125 | default: | 1366 | default: |
@@ -1133,6 +1374,11 @@ static int security_compute_sid(u32 ssid, | |||
1133 | 1374 | ||
1134 | read_lock(&policy_rwlock); | 1375 | read_lock(&policy_rwlock); |
1135 | 1376 | ||
1377 | if (kern) | ||
1378 | tclass = unmap_class(orig_tclass); | ||
1379 | else | ||
1380 | tclass = orig_tclass; | ||
1381 | |||
1136 | scontext = sidtab_search(&sidtab, ssid); | 1382 | scontext = sidtab_search(&sidtab, ssid); |
1137 | if (!scontext) { | 1383 | if (!scontext) { |
1138 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1384 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
@@ -1162,13 +1408,11 @@ static int security_compute_sid(u32 ssid, | |||
1162 | } | 1408 | } |
1163 | 1409 | ||
1164 | /* Set the role and type to default values. */ | 1410 | /* Set the role and type to default values. */ |
1165 | switch (tclass) { | 1411 | if (tclass == policydb.process_class) { |
1166 | case SECCLASS_PROCESS: | ||
1167 | /* Use the current role and type of process. */ | 1412 | /* Use the current role and type of process. */ |
1168 | newcontext.role = scontext->role; | 1413 | newcontext.role = scontext->role; |
1169 | newcontext.type = scontext->type; | 1414 | newcontext.type = scontext->type; |
1170 | break; | 1415 | } else { |
1171 | default: | ||
1172 | /* Use the well-defined object role. */ | 1416 | /* Use the well-defined object role. */ |
1173 | newcontext.role = OBJECT_R_VAL; | 1417 | newcontext.role = OBJECT_R_VAL; |
1174 | /* Use the type of the related object. */ | 1418 | /* Use the type of the related object. */ |
@@ -1199,8 +1443,7 @@ static int security_compute_sid(u32 ssid, | |||
1199 | } | 1443 | } |
1200 | 1444 | ||
1201 | /* Check for class-specific changes. */ | 1445 | /* Check for class-specific changes. */ |
1202 | switch (tclass) { | 1446 | if (tclass == policydb.process_class) { |
1203 | case SECCLASS_PROCESS: | ||
1204 | if (specified & AVTAB_TRANSITION) { | 1447 | if (specified & AVTAB_TRANSITION) { |
1205 | /* Look for a role transition rule. */ | 1448 | /* Look for a role transition rule. */ |
1206 | for (roletr = policydb.role_tr; roletr; | 1449 | for (roletr = policydb.role_tr; roletr; |
@@ -1213,9 +1456,6 @@ static int security_compute_sid(u32 ssid, | |||
1213 | } | 1456 | } |
1214 | } | 1457 | } |
1215 | } | 1458 | } |
1216 | break; | ||
1217 | default: | ||
1218 | break; | ||
1219 | } | 1459 | } |
1220 | 1460 | ||
1221 | /* Set the MLS attributes. | 1461 | /* Set the MLS attributes. |
@@ -1260,7 +1500,17 @@ int security_transition_sid(u32 ssid, | |||
1260 | u16 tclass, | 1500 | u16 tclass, |
1261 | u32 *out_sid) | 1501 | u32 *out_sid) |
1262 | { | 1502 | { |
1263 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); | 1503 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1504 | out_sid, true); | ||
1505 | } | ||
1506 | |||
1507 | int security_transition_sid_user(u32 ssid, | ||
1508 | u32 tsid, | ||
1509 | u16 tclass, | ||
1510 | u32 *out_sid) | ||
1511 | { | ||
1512 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | ||
1513 | out_sid, false); | ||
1264 | } | 1514 | } |
1265 | 1515 | ||
1266 | /** | 1516 | /** |
@@ -1281,7 +1531,8 @@ int security_member_sid(u32 ssid, | |||
1281 | u16 tclass, | 1531 | u16 tclass, |
1282 | u32 *out_sid) | 1532 | u32 *out_sid) |
1283 | { | 1533 | { |
1284 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); | 1534 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, |
1535 | false); | ||
1285 | } | 1536 | } |
1286 | 1537 | ||
1287 | /** | 1538 | /** |
@@ -1302,144 +1553,8 @@ int security_change_sid(u32 ssid, | |||
1302 | u16 tclass, | 1553 | u16 tclass, |
1303 | u32 *out_sid) | 1554 | u32 *out_sid) |
1304 | { | 1555 | { |
1305 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); | 1556 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, |
1306 | } | 1557 | false); |
1307 | |||
1308 | /* | ||
1309 | * Verify that each kernel class that is defined in the | ||
1310 | * policy is correct | ||
1311 | */ | ||
1312 | static int validate_classes(struct policydb *p) | ||
1313 | { | ||
1314 | int i, j; | ||
1315 | struct class_datum *cladatum; | ||
1316 | struct perm_datum *perdatum; | ||
1317 | u32 nprim, tmp, common_pts_len, perm_val, pol_val; | ||
1318 | u16 class_val; | ||
1319 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
1320 | const char *def_class, *def_perm, *pol_class; | ||
1321 | struct symtab *perms; | ||
1322 | bool print_unknown_handle = 0; | ||
1323 | |||
1324 | if (p->allow_unknown) { | ||
1325 | u32 num_classes = kdefs->cts_len; | ||
1326 | p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL); | ||
1327 | if (!p->undefined_perms) | ||
1328 | return -ENOMEM; | ||
1329 | } | ||
1330 | |||
1331 | for (i = 1; i < kdefs->cts_len; i++) { | ||
1332 | def_class = kdefs->class_to_string[i]; | ||
1333 | if (!def_class) | ||
1334 | continue; | ||
1335 | if (i > p->p_classes.nprim) { | ||
1336 | printk(KERN_INFO | ||
1337 | "SELinux: class %s not defined in policy\n", | ||
1338 | def_class); | ||
1339 | if (p->reject_unknown) | ||
1340 | return -EINVAL; | ||
1341 | if (p->allow_unknown) | ||
1342 | p->undefined_perms[i-1] = ~0U; | ||
1343 | print_unknown_handle = 1; | ||
1344 | continue; | ||
1345 | } | ||
1346 | pol_class = p->p_class_val_to_name[i-1]; | ||
1347 | if (strcmp(pol_class, def_class)) { | ||
1348 | printk(KERN_ERR | ||
1349 | "SELinux: class %d is incorrect, found %s but should be %s\n", | ||
1350 | i, pol_class, def_class); | ||
1351 | return -EINVAL; | ||
1352 | } | ||
1353 | } | ||
1354 | for (i = 0; i < kdefs->av_pts_len; i++) { | ||
1355 | class_val = kdefs->av_perm_to_string[i].tclass; | ||
1356 | perm_val = kdefs->av_perm_to_string[i].value; | ||
1357 | def_perm = kdefs->av_perm_to_string[i].name; | ||
1358 | if (class_val > p->p_classes.nprim) | ||
1359 | continue; | ||
1360 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1361 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1362 | BUG_ON(!cladatum); | ||
1363 | perms = &cladatum->permissions; | ||
1364 | nprim = 1 << (perms->nprim - 1); | ||
1365 | if (perm_val > nprim) { | ||
1366 | printk(KERN_INFO | ||
1367 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1368 | def_perm, pol_class); | ||
1369 | if (p->reject_unknown) | ||
1370 | return -EINVAL; | ||
1371 | if (p->allow_unknown) | ||
1372 | p->undefined_perms[class_val-1] |= perm_val; | ||
1373 | print_unknown_handle = 1; | ||
1374 | continue; | ||
1375 | } | ||
1376 | perdatum = hashtab_search(perms->table, def_perm); | ||
1377 | if (perdatum == NULL) { | ||
1378 | printk(KERN_ERR | ||
1379 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1380 | def_perm, pol_class); | ||
1381 | return -EINVAL; | ||
1382 | } | ||
1383 | pol_val = 1 << (perdatum->value - 1); | ||
1384 | if (pol_val != perm_val) { | ||
1385 | printk(KERN_ERR | ||
1386 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1387 | def_perm, pol_class); | ||
1388 | return -EINVAL; | ||
1389 | } | ||
1390 | } | ||
1391 | for (i = 0; i < kdefs->av_inherit_len; i++) { | ||
1392 | class_val = kdefs->av_inherit[i].tclass; | ||
1393 | if (class_val > p->p_classes.nprim) | ||
1394 | continue; | ||
1395 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1396 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1397 | BUG_ON(!cladatum); | ||
1398 | if (!cladatum->comdatum) { | ||
1399 | printk(KERN_ERR | ||
1400 | "SELinux: class %s should have an inherits clause but does not\n", | ||
1401 | pol_class); | ||
1402 | return -EINVAL; | ||
1403 | } | ||
1404 | tmp = kdefs->av_inherit[i].common_base; | ||
1405 | common_pts_len = 0; | ||
1406 | while (!(tmp & 0x01)) { | ||
1407 | common_pts_len++; | ||
1408 | tmp >>= 1; | ||
1409 | } | ||
1410 | perms = &cladatum->comdatum->permissions; | ||
1411 | for (j = 0; j < common_pts_len; j++) { | ||
1412 | def_perm = kdefs->av_inherit[i].common_pts[j]; | ||
1413 | if (j >= perms->nprim) { | ||
1414 | printk(KERN_INFO | ||
1415 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1416 | def_perm, pol_class); | ||
1417 | if (p->reject_unknown) | ||
1418 | return -EINVAL; | ||
1419 | if (p->allow_unknown) | ||
1420 | p->undefined_perms[class_val-1] |= (1 << j); | ||
1421 | print_unknown_handle = 1; | ||
1422 | continue; | ||
1423 | } | ||
1424 | perdatum = hashtab_search(perms->table, def_perm); | ||
1425 | if (perdatum == NULL) { | ||
1426 | printk(KERN_ERR | ||
1427 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1428 | def_perm, pol_class); | ||
1429 | return -EINVAL; | ||
1430 | } | ||
1431 | if (perdatum->value != j + 1) { | ||
1432 | printk(KERN_ERR | ||
1433 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1434 | def_perm, pol_class); | ||
1435 | return -EINVAL; | ||
1436 | } | ||
1437 | } | ||
1438 | } | ||
1439 | if (print_unknown_handle) | ||
1440 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
1441 | (security_get_allow_unknown() ? "allowed" : "denied")); | ||
1442 | return 0; | ||
1443 | } | 1558 | } |
1444 | 1559 | ||
1445 | /* Clone the SID into the new SID table. */ | 1560 | /* Clone the SID into the new SID table. */ |
@@ -1449,27 +1564,25 @@ static int clone_sid(u32 sid, | |||
1449 | { | 1564 | { |
1450 | struct sidtab *s = arg; | 1565 | struct sidtab *s = arg; |
1451 | 1566 | ||
1452 | return sidtab_insert(s, sid, context); | 1567 | if (sid > SECINITSID_NUM) |
1568 | return sidtab_insert(s, sid, context); | ||
1569 | else | ||
1570 | return 0; | ||
1453 | } | 1571 | } |
1454 | 1572 | ||
1455 | static inline int convert_context_handle_invalid_context(struct context *context) | 1573 | static inline int convert_context_handle_invalid_context(struct context *context) |
1456 | { | 1574 | { |
1457 | int rc = 0; | 1575 | char *s; |
1576 | u32 len; | ||
1458 | 1577 | ||
1459 | if (selinux_enforcing) { | 1578 | if (selinux_enforcing) |
1460 | rc = -EINVAL; | 1579 | return -EINVAL; |
1461 | } else { | 1580 | |
1462 | char *s; | 1581 | if (!context_struct_to_string(context, &s, &len)) { |
1463 | u32 len; | 1582 | printk(KERN_WARNING "SELinux: Context %s would be invalid if enforcing\n", s); |
1464 | 1583 | kfree(s); | |
1465 | if (!context_struct_to_string(context, &s, &len)) { | ||
1466 | printk(KERN_WARNING | ||
1467 | "SELinux: Context %s would be invalid if enforcing\n", | ||
1468 | s); | ||
1469 | kfree(s); | ||
1470 | } | ||
1471 | } | 1584 | } |
1472 | return rc; | 1585 | return 0; |
1473 | } | 1586 | } |
1474 | 1587 | ||
1475 | struct convert_context_args { | 1588 | struct convert_context_args { |
@@ -1490,28 +1603,33 @@ static int convert_context(u32 key, | |||
1490 | { | 1603 | { |
1491 | struct convert_context_args *args; | 1604 | struct convert_context_args *args; |
1492 | struct context oldc; | 1605 | struct context oldc; |
1606 | struct ocontext *oc; | ||
1607 | struct mls_range *range; | ||
1493 | struct role_datum *role; | 1608 | struct role_datum *role; |
1494 | struct type_datum *typdatum; | 1609 | struct type_datum *typdatum; |
1495 | struct user_datum *usrdatum; | 1610 | struct user_datum *usrdatum; |
1496 | char *s; | 1611 | char *s; |
1497 | u32 len; | 1612 | u32 len; |
1498 | int rc; | 1613 | int rc = 0; |
1614 | |||
1615 | if (key <= SECINITSID_NUM) | ||
1616 | goto out; | ||
1499 | 1617 | ||
1500 | args = p; | 1618 | args = p; |
1501 | 1619 | ||
1502 | if (c->str) { | 1620 | if (c->str) { |
1503 | struct context ctx; | 1621 | struct context ctx; |
1622 | |||
1623 | rc = -ENOMEM; | ||
1504 | s = kstrdup(c->str, GFP_KERNEL); | 1624 | s = kstrdup(c->str, GFP_KERNEL); |
1505 | if (!s) { | 1625 | if (!s) |
1506 | rc = -ENOMEM; | ||
1507 | goto out; | 1626 | goto out; |
1508 | } | 1627 | |
1509 | rc = string_to_context_struct(args->newp, NULL, s, | 1628 | rc = string_to_context_struct(args->newp, NULL, s, |
1510 | c->len, &ctx, SECSID_NULL); | 1629 | c->len, &ctx, SECSID_NULL); |
1511 | kfree(s); | 1630 | kfree(s); |
1512 | if (!rc) { | 1631 | if (!rc) { |
1513 | printk(KERN_INFO | 1632 | printk(KERN_INFO "SELinux: Context %s became valid (mapped).\n", |
1514 | "SELinux: Context %s became valid (mapped).\n", | ||
1515 | c->str); | 1633 | c->str); |
1516 | /* Replace string with mapped representation. */ | 1634 | /* Replace string with mapped representation. */ |
1517 | kfree(c->str); | 1635 | kfree(c->str); |
@@ -1523,8 +1641,7 @@ static int convert_context(u32 key, | |||
1523 | goto out; | 1641 | goto out; |
1524 | } else { | 1642 | } else { |
1525 | /* Other error condition, e.g. ENOMEM. */ | 1643 | /* Other error condition, e.g. ENOMEM. */ |
1526 | printk(KERN_ERR | 1644 | printk(KERN_ERR "SELinux: Unable to map context %s, rc = %d.\n", |
1527 | "SELinux: Unable to map context %s, rc = %d.\n", | ||
1528 | c->str, -rc); | 1645 | c->str, -rc); |
1529 | goto out; | 1646 | goto out; |
1530 | } | 1647 | } |
@@ -1534,32 +1651,64 @@ static int convert_context(u32 key, | |||
1534 | if (rc) | 1651 | if (rc) |
1535 | goto out; | 1652 | goto out; |
1536 | 1653 | ||
1537 | rc = -EINVAL; | ||
1538 | |||
1539 | /* Convert the user. */ | 1654 | /* Convert the user. */ |
1655 | rc = -EINVAL; | ||
1540 | usrdatum = hashtab_search(args->newp->p_users.table, | 1656 | usrdatum = hashtab_search(args->newp->p_users.table, |
1541 | args->oldp->p_user_val_to_name[c->user - 1]); | 1657 | sym_name(args->oldp, SYM_USERS, c->user - 1)); |
1542 | if (!usrdatum) | 1658 | if (!usrdatum) |
1543 | goto bad; | 1659 | goto bad; |
1544 | c->user = usrdatum->value; | 1660 | c->user = usrdatum->value; |
1545 | 1661 | ||
1546 | /* Convert the role. */ | 1662 | /* Convert the role. */ |
1663 | rc = -EINVAL; | ||
1547 | role = hashtab_search(args->newp->p_roles.table, | 1664 | role = hashtab_search(args->newp->p_roles.table, |
1548 | args->oldp->p_role_val_to_name[c->role - 1]); | 1665 | sym_name(args->oldp, SYM_ROLES, c->role - 1)); |
1549 | if (!role) | 1666 | if (!role) |
1550 | goto bad; | 1667 | goto bad; |
1551 | c->role = role->value; | 1668 | c->role = role->value; |
1552 | 1669 | ||
1553 | /* Convert the type. */ | 1670 | /* Convert the type. */ |
1671 | rc = -EINVAL; | ||
1554 | typdatum = hashtab_search(args->newp->p_types.table, | 1672 | typdatum = hashtab_search(args->newp->p_types.table, |
1555 | args->oldp->p_type_val_to_name[c->type - 1]); | 1673 | sym_name(args->oldp, SYM_TYPES, c->type - 1)); |
1556 | if (!typdatum) | 1674 | if (!typdatum) |
1557 | goto bad; | 1675 | goto bad; |
1558 | c->type = typdatum->value; | 1676 | c->type = typdatum->value; |
1559 | 1677 | ||
1560 | rc = mls_convert_context(args->oldp, args->newp, c); | 1678 | /* Convert the MLS fields if dealing with MLS policies */ |
1561 | if (rc) | 1679 | if (args->oldp->mls_enabled && args->newp->mls_enabled) { |
1562 | goto bad; | 1680 | rc = mls_convert_context(args->oldp, args->newp, c); |
1681 | if (rc) | ||
1682 | goto bad; | ||
1683 | } else if (args->oldp->mls_enabled && !args->newp->mls_enabled) { | ||
1684 | /* | ||
1685 | * Switching between MLS and non-MLS policy: | ||
1686 | * free any storage used by the MLS fields in the | ||
1687 | * context for all existing entries in the sidtab. | ||
1688 | */ | ||
1689 | mls_context_destroy(c); | ||
1690 | } else if (!args->oldp->mls_enabled && args->newp->mls_enabled) { | ||
1691 | /* | ||
1692 | * Switching between non-MLS and MLS policy: | ||
1693 | * ensure that the MLS fields of the context for all | ||
1694 | * existing entries in the sidtab are filled in with a | ||
1695 | * suitable default value, likely taken from one of the | ||
1696 | * initial SIDs. | ||
1697 | */ | ||
1698 | oc = args->newp->ocontexts[OCON_ISID]; | ||
1699 | while (oc && oc->sid[0] != SECINITSID_UNLABELED) | ||
1700 | oc = oc->next; | ||
1701 | rc = -EINVAL; | ||
1702 | if (!oc) { | ||
1703 | printk(KERN_ERR "SELinux: unable to look up" | ||
1704 | " the initial SIDs list\n"); | ||
1705 | goto bad; | ||
1706 | } | ||
1707 | range = &oc->context[0].range; | ||
1708 | rc = mls_range_set(c, range); | ||
1709 | if (rc) | ||
1710 | goto bad; | ||
1711 | } | ||
1563 | 1712 | ||
1564 | /* Check the validity of the new context. */ | 1713 | /* Check the validity of the new context. */ |
1565 | if (!policydb_context_isvalid(args->newp, c)) { | 1714 | if (!policydb_context_isvalid(args->newp, c)) { |
@@ -1569,19 +1718,20 @@ static int convert_context(u32 key, | |||
1569 | } | 1718 | } |
1570 | 1719 | ||
1571 | context_destroy(&oldc); | 1720 | context_destroy(&oldc); |
1721 | |||
1572 | rc = 0; | 1722 | rc = 0; |
1573 | out: | 1723 | out: |
1574 | return rc; | 1724 | return rc; |
1575 | bad: | 1725 | bad: |
1576 | /* Map old representation to string and save it. */ | 1726 | /* Map old representation to string and save it. */ |
1577 | if (context_struct_to_string(&oldc, &s, &len)) | 1727 | rc = context_struct_to_string(&oldc, &s, &len); |
1578 | return -ENOMEM; | 1728 | if (rc) |
1729 | return rc; | ||
1579 | context_destroy(&oldc); | 1730 | context_destroy(&oldc); |
1580 | context_destroy(c); | 1731 | context_destroy(c); |
1581 | c->str = s; | 1732 | c->str = s; |
1582 | c->len = len; | 1733 | c->len = len; |
1583 | printk(KERN_INFO | 1734 | printk(KERN_INFO "SELinux: Context %s became invalid (unmapped).\n", |
1584 | "SELinux: Context %s became invalid (unmapped).\n", | ||
1585 | c->str); | 1735 | c->str); |
1586 | rc = 0; | 1736 | rc = 0; |
1587 | goto out; | 1737 | goto out; |
@@ -1612,38 +1762,45 @@ int security_load_policy(void *data, size_t len) | |||
1612 | { | 1762 | { |
1613 | struct policydb oldpolicydb, newpolicydb; | 1763 | struct policydb oldpolicydb, newpolicydb; |
1614 | struct sidtab oldsidtab, newsidtab; | 1764 | struct sidtab oldsidtab, newsidtab; |
1765 | struct selinux_mapping *oldmap, *map = NULL; | ||
1615 | struct convert_context_args args; | 1766 | struct convert_context_args args; |
1616 | u32 seqno; | 1767 | u32 seqno; |
1768 | u16 map_size; | ||
1617 | int rc = 0; | 1769 | int rc = 0; |
1618 | struct policy_file file = { data, len }, *fp = &file; | 1770 | struct policy_file file = { data, len }, *fp = &file; |
1619 | 1771 | ||
1620 | if (!ss_initialized) { | 1772 | if (!ss_initialized) { |
1621 | avtab_cache_init(); | 1773 | avtab_cache_init(); |
1622 | if (policydb_read(&policydb, fp)) { | 1774 | rc = policydb_read(&policydb, fp); |
1775 | if (rc) { | ||
1623 | avtab_cache_destroy(); | 1776 | avtab_cache_destroy(); |
1624 | return -EINVAL; | 1777 | return rc; |
1625 | } | 1778 | } |
1626 | if (policydb_load_isids(&policydb, &sidtab)) { | 1779 | |
1780 | policydb.len = len; | ||
1781 | rc = selinux_set_mapping(&policydb, secclass_map, | ||
1782 | ¤t_mapping, | ||
1783 | ¤t_mapping_size); | ||
1784 | if (rc) { | ||
1627 | policydb_destroy(&policydb); | 1785 | policydb_destroy(&policydb); |
1628 | avtab_cache_destroy(); | 1786 | avtab_cache_destroy(); |
1629 | return -EINVAL; | 1787 | return rc; |
1630 | } | 1788 | } |
1631 | /* Verify that the kernel defined classes are correct. */ | 1789 | |
1632 | if (validate_classes(&policydb)) { | 1790 | rc = policydb_load_isids(&policydb, &sidtab); |
1633 | printk(KERN_ERR | 1791 | if (rc) { |
1634 | "SELinux: the definition of a class is incorrect\n"); | ||
1635 | sidtab_destroy(&sidtab); | ||
1636 | policydb_destroy(&policydb); | 1792 | policydb_destroy(&policydb); |
1637 | avtab_cache_destroy(); | 1793 | avtab_cache_destroy(); |
1638 | return -EINVAL; | 1794 | return rc; |
1639 | } | 1795 | } |
1796 | |||
1640 | security_load_policycaps(); | 1797 | security_load_policycaps(); |
1641 | policydb_loaded_version = policydb.policyvers; | ||
1642 | ss_initialized = 1; | 1798 | ss_initialized = 1; |
1643 | seqno = ++latest_granting; | 1799 | seqno = ++latest_granting; |
1644 | selinux_complete_init(); | 1800 | selinux_complete_init(); |
1645 | avc_ss_reset(seqno); | 1801 | avc_ss_reset(seqno); |
1646 | selnl_notify_policyload(seqno); | 1802 | selnl_notify_policyload(seqno); |
1803 | selinux_status_update_policyload(seqno); | ||
1647 | selinux_netlbl_cache_invalidate(); | 1804 | selinux_netlbl_cache_invalidate(); |
1648 | selinux_xfrm_notify_policyload(); | 1805 | selinux_xfrm_notify_policyload(); |
1649 | return 0; | 1806 | return 0; |
@@ -1653,21 +1810,27 @@ int security_load_policy(void *data, size_t len) | |||
1653 | sidtab_hash_eval(&sidtab, "sids"); | 1810 | sidtab_hash_eval(&sidtab, "sids"); |
1654 | #endif | 1811 | #endif |
1655 | 1812 | ||
1656 | if (policydb_read(&newpolicydb, fp)) | 1813 | rc = policydb_read(&newpolicydb, fp); |
1657 | return -EINVAL; | 1814 | if (rc) |
1815 | return rc; | ||
1658 | 1816 | ||
1659 | if (sidtab_init(&newsidtab)) { | 1817 | newpolicydb.len = len; |
1818 | /* If switching between different policy types, log MLS status */ | ||
1819 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | ||
1820 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); | ||
1821 | else if (!policydb.mls_enabled && newpolicydb.mls_enabled) | ||
1822 | printk(KERN_INFO "SELinux: Enabling MLS support...\n"); | ||
1823 | |||
1824 | rc = policydb_load_isids(&newpolicydb, &newsidtab); | ||
1825 | if (rc) { | ||
1826 | printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); | ||
1660 | policydb_destroy(&newpolicydb); | 1827 | policydb_destroy(&newpolicydb); |
1661 | return -ENOMEM; | 1828 | return rc; |
1662 | } | 1829 | } |
1663 | 1830 | ||
1664 | /* Verify that the kernel defined classes are correct. */ | 1831 | rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size); |
1665 | if (validate_classes(&newpolicydb)) { | 1832 | if (rc) |
1666 | printk(KERN_ERR | ||
1667 | "SELinux: the definition of a class is incorrect\n"); | ||
1668 | rc = -EINVAL; | ||
1669 | goto err; | 1833 | goto err; |
1670 | } | ||
1671 | 1834 | ||
1672 | rc = security_preserve_bools(&newpolicydb); | 1835 | rc = security_preserve_bools(&newpolicydb); |
1673 | if (rc) { | 1836 | if (rc) { |
@@ -1677,10 +1840,10 @@ int security_load_policy(void *data, size_t len) | |||
1677 | 1840 | ||
1678 | /* Clone the SID table. */ | 1841 | /* Clone the SID table. */ |
1679 | sidtab_shutdown(&sidtab); | 1842 | sidtab_shutdown(&sidtab); |
1680 | if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { | 1843 | |
1681 | rc = -ENOMEM; | 1844 | rc = sidtab_map(&sidtab, clone_sid, &newsidtab); |
1845 | if (rc) | ||
1682 | goto err; | 1846 | goto err; |
1683 | } | ||
1684 | 1847 | ||
1685 | /* | 1848 | /* |
1686 | * Convert the internal representations of contexts | 1849 | * Convert the internal representations of contexts |
@@ -1689,8 +1852,12 @@ int security_load_policy(void *data, size_t len) | |||
1689 | args.oldp = &policydb; | 1852 | args.oldp = &policydb; |
1690 | args.newp = &newpolicydb; | 1853 | args.newp = &newpolicydb; |
1691 | rc = sidtab_map(&newsidtab, convert_context, &args); | 1854 | rc = sidtab_map(&newsidtab, convert_context, &args); |
1692 | if (rc) | 1855 | if (rc) { |
1856 | printk(KERN_ERR "SELinux: unable to convert the internal" | ||
1857 | " representation of contexts in the new SID" | ||
1858 | " table\n"); | ||
1693 | goto err; | 1859 | goto err; |
1860 | } | ||
1694 | 1861 | ||
1695 | /* Save the old policydb and SID table to free later. */ | 1862 | /* Save the old policydb and SID table to free later. */ |
1696 | memcpy(&oldpolicydb, &policydb, sizeof policydb); | 1863 | memcpy(&oldpolicydb, &policydb, sizeof policydb); |
@@ -1701,28 +1868,44 @@ int security_load_policy(void *data, size_t len) | |||
1701 | memcpy(&policydb, &newpolicydb, sizeof policydb); | 1868 | memcpy(&policydb, &newpolicydb, sizeof policydb); |
1702 | sidtab_set(&sidtab, &newsidtab); | 1869 | sidtab_set(&sidtab, &newsidtab); |
1703 | security_load_policycaps(); | 1870 | security_load_policycaps(); |
1871 | oldmap = current_mapping; | ||
1872 | current_mapping = map; | ||
1873 | current_mapping_size = map_size; | ||
1704 | seqno = ++latest_granting; | 1874 | seqno = ++latest_granting; |
1705 | policydb_loaded_version = policydb.policyvers; | ||
1706 | write_unlock_irq(&policy_rwlock); | 1875 | write_unlock_irq(&policy_rwlock); |
1707 | 1876 | ||
1708 | /* Free the old policydb and SID table. */ | 1877 | /* Free the old policydb and SID table. */ |
1709 | policydb_destroy(&oldpolicydb); | 1878 | policydb_destroy(&oldpolicydb); |
1710 | sidtab_destroy(&oldsidtab); | 1879 | sidtab_destroy(&oldsidtab); |
1880 | kfree(oldmap); | ||
1711 | 1881 | ||
1712 | avc_ss_reset(seqno); | 1882 | avc_ss_reset(seqno); |
1713 | selnl_notify_policyload(seqno); | 1883 | selnl_notify_policyload(seqno); |
1884 | selinux_status_update_policyload(seqno); | ||
1714 | selinux_netlbl_cache_invalidate(); | 1885 | selinux_netlbl_cache_invalidate(); |
1715 | selinux_xfrm_notify_policyload(); | 1886 | selinux_xfrm_notify_policyload(); |
1716 | 1887 | ||
1717 | return 0; | 1888 | return 0; |
1718 | 1889 | ||
1719 | err: | 1890 | err: |
1891 | kfree(map); | ||
1720 | sidtab_destroy(&newsidtab); | 1892 | sidtab_destroy(&newsidtab); |
1721 | policydb_destroy(&newpolicydb); | 1893 | policydb_destroy(&newpolicydb); |
1722 | return rc; | 1894 | return rc; |
1723 | 1895 | ||
1724 | } | 1896 | } |
1725 | 1897 | ||
1898 | size_t security_policydb_len(void) | ||
1899 | { | ||
1900 | size_t len; | ||
1901 | |||
1902 | read_lock(&policy_rwlock); | ||
1903 | len = policydb.len; | ||
1904 | read_unlock(&policy_rwlock); | ||
1905 | |||
1906 | return len; | ||
1907 | } | ||
1908 | |||
1726 | /** | 1909 | /** |
1727 | * security_port_sid - Obtain the SID for a port. | 1910 | * security_port_sid - Obtain the SID for a port. |
1728 | * @protocol: protocol number | 1911 | * @protocol: protocol number |
@@ -1829,7 +2012,7 @@ int security_node_sid(u16 domain, | |||
1829 | u32 addrlen, | 2012 | u32 addrlen, |
1830 | u32 *out_sid) | 2013 | u32 *out_sid) |
1831 | { | 2014 | { |
1832 | int rc = 0; | 2015 | int rc; |
1833 | struct ocontext *c; | 2016 | struct ocontext *c; |
1834 | 2017 | ||
1835 | read_lock(&policy_rwlock); | 2018 | read_lock(&policy_rwlock); |
@@ -1838,10 +2021,9 @@ int security_node_sid(u16 domain, | |||
1838 | case AF_INET: { | 2021 | case AF_INET: { |
1839 | u32 addr; | 2022 | u32 addr; |
1840 | 2023 | ||
1841 | if (addrlen != sizeof(u32)) { | 2024 | rc = -EINVAL; |
1842 | rc = -EINVAL; | 2025 | if (addrlen != sizeof(u32)) |
1843 | goto out; | 2026 | goto out; |
1844 | } | ||
1845 | 2027 | ||
1846 | addr = *((u32 *)addrp); | 2028 | addr = *((u32 *)addrp); |
1847 | 2029 | ||
@@ -1855,10 +2037,9 @@ int security_node_sid(u16 domain, | |||
1855 | } | 2037 | } |
1856 | 2038 | ||
1857 | case AF_INET6: | 2039 | case AF_INET6: |
1858 | if (addrlen != sizeof(u64) * 2) { | 2040 | rc = -EINVAL; |
1859 | rc = -EINVAL; | 2041 | if (addrlen != sizeof(u64) * 2) |
1860 | goto out; | 2042 | goto out; |
1861 | } | ||
1862 | c = policydb.ocontexts[OCON_NODE6]; | 2043 | c = policydb.ocontexts[OCON_NODE6]; |
1863 | while (c) { | 2044 | while (c) { |
1864 | if (match_ipv6_addrmask(addrp, c->u.node6.addr, | 2045 | if (match_ipv6_addrmask(addrp, c->u.node6.addr, |
@@ -1869,6 +2050,7 @@ int security_node_sid(u16 domain, | |||
1869 | break; | 2050 | break; |
1870 | 2051 | ||
1871 | default: | 2052 | default: |
2053 | rc = 0; | ||
1872 | *out_sid = SECINITSID_NODE; | 2054 | *out_sid = SECINITSID_NODE; |
1873 | goto out; | 2055 | goto out; |
1874 | } | 2056 | } |
@@ -1886,6 +2068,7 @@ int security_node_sid(u16 domain, | |||
1886 | *out_sid = SECINITSID_NODE; | 2068 | *out_sid = SECINITSID_NODE; |
1887 | } | 2069 | } |
1888 | 2070 | ||
2071 | rc = 0; | ||
1889 | out: | 2072 | out: |
1890 | read_unlock(&policy_rwlock); | 2073 | read_unlock(&policy_rwlock); |
1891 | return rc; | 2074 | return rc; |
@@ -1930,30 +2113,28 @@ int security_get_user_sids(u32 fromsid, | |||
1930 | 2113 | ||
1931 | context_init(&usercon); | 2114 | context_init(&usercon); |
1932 | 2115 | ||
2116 | rc = -EINVAL; | ||
1933 | fromcon = sidtab_search(&sidtab, fromsid); | 2117 | fromcon = sidtab_search(&sidtab, fromsid); |
1934 | if (!fromcon) { | 2118 | if (!fromcon) |
1935 | rc = -EINVAL; | ||
1936 | goto out_unlock; | 2119 | goto out_unlock; |
1937 | } | ||
1938 | 2120 | ||
2121 | rc = -EINVAL; | ||
1939 | user = hashtab_search(policydb.p_users.table, username); | 2122 | user = hashtab_search(policydb.p_users.table, username); |
1940 | if (!user) { | 2123 | if (!user) |
1941 | rc = -EINVAL; | ||
1942 | goto out_unlock; | 2124 | goto out_unlock; |
1943 | } | 2125 | |
1944 | usercon.user = user->value; | 2126 | usercon.user = user->value; |
1945 | 2127 | ||
2128 | rc = -ENOMEM; | ||
1946 | mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC); | 2129 | mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC); |
1947 | if (!mysids) { | 2130 | if (!mysids) |
1948 | rc = -ENOMEM; | ||
1949 | goto out_unlock; | 2131 | goto out_unlock; |
1950 | } | ||
1951 | 2132 | ||
1952 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { | 2133 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { |
1953 | role = policydb.role_val_to_struct[i]; | 2134 | role = policydb.role_val_to_struct[i]; |
1954 | usercon.role = i+1; | 2135 | usercon.role = i + 1; |
1955 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { | 2136 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { |
1956 | usercon.type = j+1; | 2137 | usercon.type = j + 1; |
1957 | 2138 | ||
1958 | if (mls_setup_user_range(fromcon, user, &usercon)) | 2139 | if (mls_setup_user_range(fromcon, user, &usercon)) |
1959 | continue; | 2140 | continue; |
@@ -1964,12 +2145,11 @@ int security_get_user_sids(u32 fromsid, | |||
1964 | if (mynel < maxnel) { | 2145 | if (mynel < maxnel) { |
1965 | mysids[mynel++] = sid; | 2146 | mysids[mynel++] = sid; |
1966 | } else { | 2147 | } else { |
2148 | rc = -ENOMEM; | ||
1967 | maxnel += SIDS_NEL; | 2149 | maxnel += SIDS_NEL; |
1968 | mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); | 2150 | mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); |
1969 | if (!mysids2) { | 2151 | if (!mysids2) |
1970 | rc = -ENOMEM; | ||
1971 | goto out_unlock; | 2152 | goto out_unlock; |
1972 | } | ||
1973 | memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); | 2153 | memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); |
1974 | kfree(mysids); | 2154 | kfree(mysids); |
1975 | mysids = mysids2; | 2155 | mysids = mysids2; |
@@ -1977,7 +2157,7 @@ int security_get_user_sids(u32 fromsid, | |||
1977 | } | 2157 | } |
1978 | } | 2158 | } |
1979 | } | 2159 | } |
1980 | 2160 | rc = 0; | |
1981 | out_unlock: | 2161 | out_unlock: |
1982 | read_unlock(&policy_rwlock); | 2162 | read_unlock(&policy_rwlock); |
1983 | if (rc || !mynel) { | 2163 | if (rc || !mynel) { |
@@ -1985,15 +2165,15 @@ out_unlock: | |||
1985 | goto out; | 2165 | goto out; |
1986 | } | 2166 | } |
1987 | 2167 | ||
2168 | rc = -ENOMEM; | ||
1988 | mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL); | 2169 | mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL); |
1989 | if (!mysids2) { | 2170 | if (!mysids2) { |
1990 | rc = -ENOMEM; | ||
1991 | kfree(mysids); | 2171 | kfree(mysids); |
1992 | goto out; | 2172 | goto out; |
1993 | } | 2173 | } |
1994 | for (i = 0, j = 0; i < mynel; i++) { | 2174 | for (i = 0, j = 0; i < mynel; i++) { |
1995 | rc = avc_has_perm_noaudit(fromsid, mysids[i], | 2175 | rc = avc_has_perm_noaudit(fromsid, mysids[i], |
1996 | SECCLASS_PROCESS, | 2176 | SECCLASS_PROCESS, /* kernel value */ |
1997 | PROCESS__TRANSITION, AVC_STRICT, | 2177 | PROCESS__TRANSITION, AVC_STRICT, |
1998 | NULL); | 2178 | NULL); |
1999 | if (!rc) | 2179 | if (!rc) |
@@ -2021,30 +2201,32 @@ out: | |||
2021 | */ | 2201 | */ |
2022 | int security_genfs_sid(const char *fstype, | 2202 | int security_genfs_sid(const char *fstype, |
2023 | char *path, | 2203 | char *path, |
2024 | u16 sclass, | 2204 | u16 orig_sclass, |
2025 | u32 *sid) | 2205 | u32 *sid) |
2026 | { | 2206 | { |
2027 | int len; | 2207 | int len; |
2208 | u16 sclass; | ||
2028 | struct genfs *genfs; | 2209 | struct genfs *genfs; |
2029 | struct ocontext *c; | 2210 | struct ocontext *c; |
2030 | int rc = 0, cmp = 0; | 2211 | int rc, cmp = 0; |
2031 | 2212 | ||
2032 | while (path[0] == '/' && path[1] == '/') | 2213 | while (path[0] == '/' && path[1] == '/') |
2033 | path++; | 2214 | path++; |
2034 | 2215 | ||
2035 | read_lock(&policy_rwlock); | 2216 | read_lock(&policy_rwlock); |
2036 | 2217 | ||
2218 | sclass = unmap_class(orig_sclass); | ||
2219 | *sid = SECINITSID_UNLABELED; | ||
2220 | |||
2037 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { | 2221 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { |
2038 | cmp = strcmp(fstype, genfs->fstype); | 2222 | cmp = strcmp(fstype, genfs->fstype); |
2039 | if (cmp <= 0) | 2223 | if (cmp <= 0) |
2040 | break; | 2224 | break; |
2041 | } | 2225 | } |
2042 | 2226 | ||
2043 | if (!genfs || cmp) { | 2227 | rc = -ENOENT; |
2044 | *sid = SECINITSID_UNLABELED; | 2228 | if (!genfs || cmp) |
2045 | rc = -ENOENT; | ||
2046 | goto out; | 2229 | goto out; |
2047 | } | ||
2048 | 2230 | ||
2049 | for (c = genfs->head; c; c = c->next) { | 2231 | for (c = genfs->head; c; c = c->next) { |
2050 | len = strlen(c->u.name); | 2232 | len = strlen(c->u.name); |
@@ -2053,21 +2235,18 @@ int security_genfs_sid(const char *fstype, | |||
2053 | break; | 2235 | break; |
2054 | } | 2236 | } |
2055 | 2237 | ||
2056 | if (!c) { | 2238 | rc = -ENOENT; |
2057 | *sid = SECINITSID_UNLABELED; | 2239 | if (!c) |
2058 | rc = -ENOENT; | ||
2059 | goto out; | 2240 | goto out; |
2060 | } | ||
2061 | 2241 | ||
2062 | if (!c->sid[0]) { | 2242 | if (!c->sid[0]) { |
2063 | rc = sidtab_context_to_sid(&sidtab, | 2243 | rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]); |
2064 | &c->context[0], | ||
2065 | &c->sid[0]); | ||
2066 | if (rc) | 2244 | if (rc) |
2067 | goto out; | 2245 | goto out; |
2068 | } | 2246 | } |
2069 | 2247 | ||
2070 | *sid = c->sid[0]; | 2248 | *sid = c->sid[0]; |
2249 | rc = 0; | ||
2071 | out: | 2250 | out: |
2072 | read_unlock(&policy_rwlock); | 2251 | read_unlock(&policy_rwlock); |
2073 | return rc; | 2252 | return rc; |
@@ -2099,8 +2278,7 @@ int security_fs_use( | |||
2099 | if (c) { | 2278 | if (c) { |
2100 | *behavior = c->v.behavior; | 2279 | *behavior = c->v.behavior; |
2101 | if (!c->sid[0]) { | 2280 | if (!c->sid[0]) { |
2102 | rc = sidtab_context_to_sid(&sidtab, | 2281 | rc = sidtab_context_to_sid(&sidtab, &c->context[0], |
2103 | &c->context[0], | ||
2104 | &c->sid[0]); | 2282 | &c->sid[0]); |
2105 | if (rc) | 2283 | if (rc) |
2106 | goto out; | 2284 | goto out; |
@@ -2123,34 +2301,39 @@ out: | |||
2123 | 2301 | ||
2124 | int security_get_bools(int *len, char ***names, int **values) | 2302 | int security_get_bools(int *len, char ***names, int **values) |
2125 | { | 2303 | { |
2126 | int i, rc = -ENOMEM; | 2304 | int i, rc; |
2127 | 2305 | ||
2128 | read_lock(&policy_rwlock); | 2306 | read_lock(&policy_rwlock); |
2129 | *names = NULL; | 2307 | *names = NULL; |
2130 | *values = NULL; | 2308 | *values = NULL; |
2131 | 2309 | ||
2310 | rc = 0; | ||
2132 | *len = policydb.p_bools.nprim; | 2311 | *len = policydb.p_bools.nprim; |
2133 | if (!*len) { | 2312 | if (!*len) |
2134 | rc = 0; | ||
2135 | goto out; | 2313 | goto out; |
2136 | } | ||
2137 | 2314 | ||
2138 | *names = kcalloc(*len, sizeof(char *), GFP_ATOMIC); | 2315 | rc = -ENOMEM; |
2316 | *names = kcalloc(*len, sizeof(char *), GFP_ATOMIC); | ||
2139 | if (!*names) | 2317 | if (!*names) |
2140 | goto err; | 2318 | goto err; |
2141 | 2319 | ||
2142 | *values = kcalloc(*len, sizeof(int), GFP_ATOMIC); | 2320 | rc = -ENOMEM; |
2321 | *values = kcalloc(*len, sizeof(int), GFP_ATOMIC); | ||
2143 | if (!*values) | 2322 | if (!*values) |
2144 | goto err; | 2323 | goto err; |
2145 | 2324 | ||
2146 | for (i = 0; i < *len; i++) { | 2325 | for (i = 0; i < *len; i++) { |
2147 | size_t name_len; | 2326 | size_t name_len; |
2327 | |||
2148 | (*values)[i] = policydb.bool_val_to_struct[i]->state; | 2328 | (*values)[i] = policydb.bool_val_to_struct[i]->state; |
2149 | name_len = strlen(policydb.p_bool_val_to_name[i]) + 1; | 2329 | name_len = strlen(sym_name(&policydb, SYM_BOOLS, i)) + 1; |
2150 | (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC); | 2330 | |
2331 | rc = -ENOMEM; | ||
2332 | (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC); | ||
2151 | if (!(*names)[i]) | 2333 | if (!(*names)[i]) |
2152 | goto err; | 2334 | goto err; |
2153 | strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len); | 2335 | |
2336 | strncpy((*names)[i], sym_name(&policydb, SYM_BOOLS, i), name_len); | ||
2154 | (*names)[i][name_len - 1] = 0; | 2337 | (*names)[i][name_len - 1] = 0; |
2155 | } | 2338 | } |
2156 | rc = 0; | 2339 | rc = 0; |
@@ -2169,24 +2352,23 @@ err: | |||
2169 | 2352 | ||
2170 | int security_set_bools(int len, int *values) | 2353 | int security_set_bools(int len, int *values) |
2171 | { | 2354 | { |
2172 | int i, rc = 0; | 2355 | int i, rc; |
2173 | int lenp, seqno = 0; | 2356 | int lenp, seqno = 0; |
2174 | struct cond_node *cur; | 2357 | struct cond_node *cur; |
2175 | 2358 | ||
2176 | write_lock_irq(&policy_rwlock); | 2359 | write_lock_irq(&policy_rwlock); |
2177 | 2360 | ||
2361 | rc = -EFAULT; | ||
2178 | lenp = policydb.p_bools.nprim; | 2362 | lenp = policydb.p_bools.nprim; |
2179 | if (len != lenp) { | 2363 | if (len != lenp) |
2180 | rc = -EFAULT; | ||
2181 | goto out; | 2364 | goto out; |
2182 | } | ||
2183 | 2365 | ||
2184 | for (i = 0; i < len; i++) { | 2366 | for (i = 0; i < len; i++) { |
2185 | if (!!values[i] != policydb.bool_val_to_struct[i]->state) { | 2367 | if (!!values[i] != policydb.bool_val_to_struct[i]->state) { |
2186 | audit_log(current->audit_context, GFP_ATOMIC, | 2368 | audit_log(current->audit_context, GFP_ATOMIC, |
2187 | AUDIT_MAC_CONFIG_CHANGE, | 2369 | AUDIT_MAC_CONFIG_CHANGE, |
2188 | "bool=%s val=%d old_val=%d auid=%u ses=%u", | 2370 | "bool=%s val=%d old_val=%d auid=%u ses=%u", |
2189 | policydb.p_bool_val_to_name[i], | 2371 | sym_name(&policydb, SYM_BOOLS, i), |
2190 | !!values[i], | 2372 | !!values[i], |
2191 | policydb.bool_val_to_struct[i]->state, | 2373 | policydb.bool_val_to_struct[i]->state, |
2192 | audit_get_loginuid(current), | 2374 | audit_get_loginuid(current), |
@@ -2205,12 +2387,13 @@ int security_set_bools(int len, int *values) | |||
2205 | } | 2387 | } |
2206 | 2388 | ||
2207 | seqno = ++latest_granting; | 2389 | seqno = ++latest_granting; |
2208 | 2390 | rc = 0; | |
2209 | out: | 2391 | out: |
2210 | write_unlock_irq(&policy_rwlock); | 2392 | write_unlock_irq(&policy_rwlock); |
2211 | if (!rc) { | 2393 | if (!rc) { |
2212 | avc_ss_reset(seqno); | 2394 | avc_ss_reset(seqno); |
2213 | selnl_notify_policyload(seqno); | 2395 | selnl_notify_policyload(seqno); |
2396 | selinux_status_update_policyload(seqno); | ||
2214 | selinux_xfrm_notify_policyload(); | 2397 | selinux_xfrm_notify_policyload(); |
2215 | } | 2398 | } |
2216 | return rc; | 2399 | return rc; |
@@ -2218,16 +2401,15 @@ out: | |||
2218 | 2401 | ||
2219 | int security_get_bool_value(int bool) | 2402 | int security_get_bool_value(int bool) |
2220 | { | 2403 | { |
2221 | int rc = 0; | 2404 | int rc; |
2222 | int len; | 2405 | int len; |
2223 | 2406 | ||
2224 | read_lock(&policy_rwlock); | 2407 | read_lock(&policy_rwlock); |
2225 | 2408 | ||
2409 | rc = -EFAULT; | ||
2226 | len = policydb.p_bools.nprim; | 2410 | len = policydb.p_bools.nprim; |
2227 | if (bool >= len) { | 2411 | if (bool >= len) |
2228 | rc = -EFAULT; | ||
2229 | goto out; | 2412 | goto out; |
2230 | } | ||
2231 | 2413 | ||
2232 | rc = policydb.bool_val_to_struct[bool]->state; | 2414 | rc = policydb.bool_val_to_struct[bool]->state; |
2233 | out: | 2415 | out: |
@@ -2277,9 +2459,10 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2277 | struct context newcon; | 2459 | struct context newcon; |
2278 | char *s; | 2460 | char *s; |
2279 | u32 len; | 2461 | u32 len; |
2280 | int rc = 0; | 2462 | int rc; |
2281 | 2463 | ||
2282 | if (!ss_initialized || !selinux_mls_enabled) { | 2464 | rc = 0; |
2465 | if (!ss_initialized || !policydb.mls_enabled) { | ||
2283 | *new_sid = sid; | 2466 | *new_sid = sid; |
2284 | goto out; | 2467 | goto out; |
2285 | } | 2468 | } |
@@ -2287,19 +2470,20 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2287 | context_init(&newcon); | 2470 | context_init(&newcon); |
2288 | 2471 | ||
2289 | read_lock(&policy_rwlock); | 2472 | read_lock(&policy_rwlock); |
2473 | |||
2474 | rc = -EINVAL; | ||
2290 | context1 = sidtab_search(&sidtab, sid); | 2475 | context1 = sidtab_search(&sidtab, sid); |
2291 | if (!context1) { | 2476 | if (!context1) { |
2292 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 2477 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2293 | __func__, sid); | 2478 | __func__, sid); |
2294 | rc = -EINVAL; | ||
2295 | goto out_unlock; | 2479 | goto out_unlock; |
2296 | } | 2480 | } |
2297 | 2481 | ||
2482 | rc = -EINVAL; | ||
2298 | context2 = sidtab_search(&sidtab, mls_sid); | 2483 | context2 = sidtab_search(&sidtab, mls_sid); |
2299 | if (!context2) { | 2484 | if (!context2) { |
2300 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 2485 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2301 | __func__, mls_sid); | 2486 | __func__, mls_sid); |
2302 | rc = -EINVAL; | ||
2303 | goto out_unlock; | 2487 | goto out_unlock; |
2304 | } | 2488 | } |
2305 | 2489 | ||
@@ -2313,20 +2497,17 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2313 | /* Check the validity of the new context. */ | 2497 | /* Check the validity of the new context. */ |
2314 | if (!policydb_context_isvalid(&policydb, &newcon)) { | 2498 | if (!policydb_context_isvalid(&policydb, &newcon)) { |
2315 | rc = convert_context_handle_invalid_context(&newcon); | 2499 | rc = convert_context_handle_invalid_context(&newcon); |
2316 | if (rc) | 2500 | if (rc) { |
2317 | goto bad; | 2501 | if (!context_struct_to_string(&newcon, &s, &len)) { |
2502 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
2503 | "security_sid_mls_copy: invalid context %s", s); | ||
2504 | kfree(s); | ||
2505 | } | ||
2506 | goto out_unlock; | ||
2507 | } | ||
2318 | } | 2508 | } |
2319 | 2509 | ||
2320 | rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid); | 2510 | rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid); |
2321 | goto out_unlock; | ||
2322 | |||
2323 | bad: | ||
2324 | if (!context_struct_to_string(&newcon, &s, &len)) { | ||
2325 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
2326 | "security_sid_mls_copy: invalid context %s", s); | ||
2327 | kfree(s); | ||
2328 | } | ||
2329 | |||
2330 | out_unlock: | 2511 | out_unlock: |
2331 | read_unlock(&policy_rwlock); | 2512 | read_unlock(&policy_rwlock); |
2332 | context_destroy(&newcon); | 2513 | context_destroy(&newcon); |
@@ -2362,6 +2543,8 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2362 | struct context *nlbl_ctx; | 2543 | struct context *nlbl_ctx; |
2363 | struct context *xfrm_ctx; | 2544 | struct context *xfrm_ctx; |
2364 | 2545 | ||
2546 | *peer_sid = SECSID_NULL; | ||
2547 | |||
2365 | /* handle the common (which also happens to be the set of easy) cases | 2548 | /* handle the common (which also happens to be the set of easy) cases |
2366 | * right away, these two if statements catch everything involving a | 2549 | * right away, these two if statements catch everything involving a |
2367 | * single or absent peer SID/label */ | 2550 | * single or absent peer SID/label */ |
@@ -2380,40 +2563,37 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2380 | /* we don't need to check ss_initialized here since the only way both | 2563 | /* we don't need to check ss_initialized here since the only way both |
2381 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the | 2564 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the |
2382 | * security server was initialized and ss_initialized was true */ | 2565 | * security server was initialized and ss_initialized was true */ |
2383 | if (!selinux_mls_enabled) { | 2566 | if (!policydb.mls_enabled) |
2384 | *peer_sid = SECSID_NULL; | ||
2385 | return 0; | 2567 | return 0; |
2386 | } | ||
2387 | 2568 | ||
2388 | read_lock(&policy_rwlock); | 2569 | read_lock(&policy_rwlock); |
2389 | 2570 | ||
2571 | rc = -EINVAL; | ||
2390 | nlbl_ctx = sidtab_search(&sidtab, nlbl_sid); | 2572 | nlbl_ctx = sidtab_search(&sidtab, nlbl_sid); |
2391 | if (!nlbl_ctx) { | 2573 | if (!nlbl_ctx) { |
2392 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 2574 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2393 | __func__, nlbl_sid); | 2575 | __func__, nlbl_sid); |
2394 | rc = -EINVAL; | 2576 | goto out; |
2395 | goto out_slowpath; | ||
2396 | } | 2577 | } |
2578 | rc = -EINVAL; | ||
2397 | xfrm_ctx = sidtab_search(&sidtab, xfrm_sid); | 2579 | xfrm_ctx = sidtab_search(&sidtab, xfrm_sid); |
2398 | if (!xfrm_ctx) { | 2580 | if (!xfrm_ctx) { |
2399 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 2581 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
2400 | __func__, xfrm_sid); | 2582 | __func__, xfrm_sid); |
2401 | rc = -EINVAL; | 2583 | goto out; |
2402 | goto out_slowpath; | ||
2403 | } | 2584 | } |
2404 | rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES); | 2585 | rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES); |
2586 | if (rc) | ||
2587 | goto out; | ||
2405 | 2588 | ||
2406 | out_slowpath: | 2589 | /* at present NetLabel SIDs/labels really only carry MLS |
2590 | * information so if the MLS portion of the NetLabel SID | ||
2591 | * matches the MLS portion of the labeled XFRM SID/label | ||
2592 | * then pass along the XFRM SID as it is the most | ||
2593 | * expressive */ | ||
2594 | *peer_sid = xfrm_sid; | ||
2595 | out: | ||
2407 | read_unlock(&policy_rwlock); | 2596 | read_unlock(&policy_rwlock); |
2408 | if (rc == 0) | ||
2409 | /* at present NetLabel SIDs/labels really only carry MLS | ||
2410 | * information so if the MLS portion of the NetLabel SID | ||
2411 | * matches the MLS portion of the labeled XFRM SID/label | ||
2412 | * then pass along the XFRM SID as it is the most | ||
2413 | * expressive */ | ||
2414 | *peer_sid = xfrm_sid; | ||
2415 | else | ||
2416 | *peer_sid = SECSID_NULL; | ||
2417 | return rc; | 2597 | return rc; |
2418 | } | 2598 | } |
2419 | 2599 | ||
@@ -2432,18 +2612,19 @@ static int get_classes_callback(void *k, void *d, void *args) | |||
2432 | 2612 | ||
2433 | int security_get_classes(char ***classes, int *nclasses) | 2613 | int security_get_classes(char ***classes, int *nclasses) |
2434 | { | 2614 | { |
2435 | int rc = -ENOMEM; | 2615 | int rc; |
2436 | 2616 | ||
2437 | read_lock(&policy_rwlock); | 2617 | read_lock(&policy_rwlock); |
2438 | 2618 | ||
2619 | rc = -ENOMEM; | ||
2439 | *nclasses = policydb.p_classes.nprim; | 2620 | *nclasses = policydb.p_classes.nprim; |
2440 | *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); | 2621 | *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); |
2441 | if (!*classes) | 2622 | if (!*classes) |
2442 | goto out; | 2623 | goto out; |
2443 | 2624 | ||
2444 | rc = hashtab_map(policydb.p_classes.table, get_classes_callback, | 2625 | rc = hashtab_map(policydb.p_classes.table, get_classes_callback, |
2445 | *classes); | 2626 | *classes); |
2446 | if (rc < 0) { | 2627 | if (rc) { |
2447 | int i; | 2628 | int i; |
2448 | for (i = 0; i < *nclasses; i++) | 2629 | for (i = 0; i < *nclasses; i++) |
2449 | kfree((*classes)[i]); | 2630 | kfree((*classes)[i]); |
@@ -2470,34 +2651,35 @@ static int get_permissions_callback(void *k, void *d, void *args) | |||
2470 | 2651 | ||
2471 | int security_get_permissions(char *class, char ***perms, int *nperms) | 2652 | int security_get_permissions(char *class, char ***perms, int *nperms) |
2472 | { | 2653 | { |
2473 | int rc = -ENOMEM, i; | 2654 | int rc, i; |
2474 | struct class_datum *match; | 2655 | struct class_datum *match; |
2475 | 2656 | ||
2476 | read_lock(&policy_rwlock); | 2657 | read_lock(&policy_rwlock); |
2477 | 2658 | ||
2659 | rc = -EINVAL; | ||
2478 | match = hashtab_search(policydb.p_classes.table, class); | 2660 | match = hashtab_search(policydb.p_classes.table, class); |
2479 | if (!match) { | 2661 | if (!match) { |
2480 | printk(KERN_ERR "SELinux: %s: unrecognized class %s\n", | 2662 | printk(KERN_ERR "SELinux: %s: unrecognized class %s\n", |
2481 | __func__, class); | 2663 | __func__, class); |
2482 | rc = -EINVAL; | ||
2483 | goto out; | 2664 | goto out; |
2484 | } | 2665 | } |
2485 | 2666 | ||
2667 | rc = -ENOMEM; | ||
2486 | *nperms = match->permissions.nprim; | 2668 | *nperms = match->permissions.nprim; |
2487 | *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC); | 2669 | *perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC); |
2488 | if (!*perms) | 2670 | if (!*perms) |
2489 | goto out; | 2671 | goto out; |
2490 | 2672 | ||
2491 | if (match->comdatum) { | 2673 | if (match->comdatum) { |
2492 | rc = hashtab_map(match->comdatum->permissions.table, | 2674 | rc = hashtab_map(match->comdatum->permissions.table, |
2493 | get_permissions_callback, *perms); | 2675 | get_permissions_callback, *perms); |
2494 | if (rc < 0) | 2676 | if (rc) |
2495 | goto err; | 2677 | goto err; |
2496 | } | 2678 | } |
2497 | 2679 | ||
2498 | rc = hashtab_map(match->permissions.table, get_permissions_callback, | 2680 | rc = hashtab_map(match->permissions.table, get_permissions_callback, |
2499 | *perms); | 2681 | *perms); |
2500 | if (rc < 0) | 2682 | if (rc) |
2501 | goto err; | 2683 | goto err; |
2502 | 2684 | ||
2503 | out: | 2685 | out: |
@@ -2609,36 +2791,39 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
2609 | switch (field) { | 2791 | switch (field) { |
2610 | case AUDIT_SUBJ_USER: | 2792 | case AUDIT_SUBJ_USER: |
2611 | case AUDIT_OBJ_USER: | 2793 | case AUDIT_OBJ_USER: |
2794 | rc = -EINVAL; | ||
2612 | userdatum = hashtab_search(policydb.p_users.table, rulestr); | 2795 | userdatum = hashtab_search(policydb.p_users.table, rulestr); |
2613 | if (!userdatum) | 2796 | if (!userdatum) |
2614 | rc = -EINVAL; | 2797 | goto out; |
2615 | else | 2798 | tmprule->au_ctxt.user = userdatum->value; |
2616 | tmprule->au_ctxt.user = userdatum->value; | ||
2617 | break; | 2799 | break; |
2618 | case AUDIT_SUBJ_ROLE: | 2800 | case AUDIT_SUBJ_ROLE: |
2619 | case AUDIT_OBJ_ROLE: | 2801 | case AUDIT_OBJ_ROLE: |
2802 | rc = -EINVAL; | ||
2620 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); | 2803 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); |
2621 | if (!roledatum) | 2804 | if (!roledatum) |
2622 | rc = -EINVAL; | 2805 | goto out; |
2623 | else | 2806 | tmprule->au_ctxt.role = roledatum->value; |
2624 | tmprule->au_ctxt.role = roledatum->value; | ||
2625 | break; | 2807 | break; |
2626 | case AUDIT_SUBJ_TYPE: | 2808 | case AUDIT_SUBJ_TYPE: |
2627 | case AUDIT_OBJ_TYPE: | 2809 | case AUDIT_OBJ_TYPE: |
2810 | rc = -EINVAL; | ||
2628 | typedatum = hashtab_search(policydb.p_types.table, rulestr); | 2811 | typedatum = hashtab_search(policydb.p_types.table, rulestr); |
2629 | if (!typedatum) | 2812 | if (!typedatum) |
2630 | rc = -EINVAL; | 2813 | goto out; |
2631 | else | 2814 | tmprule->au_ctxt.type = typedatum->value; |
2632 | tmprule->au_ctxt.type = typedatum->value; | ||
2633 | break; | 2815 | break; |
2634 | case AUDIT_SUBJ_SEN: | 2816 | case AUDIT_SUBJ_SEN: |
2635 | case AUDIT_SUBJ_CLR: | 2817 | case AUDIT_SUBJ_CLR: |
2636 | case AUDIT_OBJ_LEV_LOW: | 2818 | case AUDIT_OBJ_LEV_LOW: |
2637 | case AUDIT_OBJ_LEV_HIGH: | 2819 | case AUDIT_OBJ_LEV_HIGH: |
2638 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); | 2820 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); |
2821 | if (rc) | ||
2822 | goto out; | ||
2639 | break; | 2823 | break; |
2640 | } | 2824 | } |
2641 | 2825 | rc = 0; | |
2826 | out: | ||
2642 | read_unlock(&policy_rwlock); | 2827 | read_unlock(&policy_rwlock); |
2643 | 2828 | ||
2644 | if (rc) { | 2829 | if (rc) { |
@@ -2863,7 +3048,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, | |||
2863 | int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | 3048 | int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, |
2864 | u32 *sid) | 3049 | u32 *sid) |
2865 | { | 3050 | { |
2866 | int rc = -EIDRM; | 3051 | int rc; |
2867 | struct context *ctx; | 3052 | struct context *ctx; |
2868 | struct context ctx_new; | 3053 | struct context ctx_new; |
2869 | 3054 | ||
@@ -2874,16 +3059,15 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | |||
2874 | 3059 | ||
2875 | read_lock(&policy_rwlock); | 3060 | read_lock(&policy_rwlock); |
2876 | 3061 | ||
2877 | if (secattr->flags & NETLBL_SECATTR_CACHE) { | 3062 | if (secattr->flags & NETLBL_SECATTR_CACHE) |
2878 | *sid = *(u32 *)secattr->cache->data; | 3063 | *sid = *(u32 *)secattr->cache->data; |
2879 | rc = 0; | 3064 | else if (secattr->flags & NETLBL_SECATTR_SECID) |
2880 | } else if (secattr->flags & NETLBL_SECATTR_SECID) { | ||
2881 | *sid = secattr->attr.secid; | 3065 | *sid = secattr->attr.secid; |
2882 | rc = 0; | 3066 | else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { |
2883 | } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { | 3067 | rc = -EIDRM; |
2884 | ctx = sidtab_search(&sidtab, SECINITSID_NETMSG); | 3068 | ctx = sidtab_search(&sidtab, SECINITSID_NETMSG); |
2885 | if (ctx == NULL) | 3069 | if (ctx == NULL) |
2886 | goto netlbl_secattr_to_sid_return; | 3070 | goto out; |
2887 | 3071 | ||
2888 | context_init(&ctx_new); | 3072 | context_init(&ctx_new); |
2889 | ctx_new.user = ctx->user; | 3073 | ctx_new.user = ctx->user; |
@@ -2891,34 +3075,35 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | |||
2891 | ctx_new.type = ctx->type; | 3075 | ctx_new.type = ctx->type; |
2892 | mls_import_netlbl_lvl(&ctx_new, secattr); | 3076 | mls_import_netlbl_lvl(&ctx_new, secattr); |
2893 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { | 3077 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { |
2894 | if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, | 3078 | rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat, |
2895 | secattr->attr.mls.cat) != 0) | 3079 | secattr->attr.mls.cat); |
2896 | goto netlbl_secattr_to_sid_return; | 3080 | if (rc) |
3081 | goto out; | ||
2897 | memcpy(&ctx_new.range.level[1].cat, | 3082 | memcpy(&ctx_new.range.level[1].cat, |
2898 | &ctx_new.range.level[0].cat, | 3083 | &ctx_new.range.level[0].cat, |
2899 | sizeof(ctx_new.range.level[0].cat)); | 3084 | sizeof(ctx_new.range.level[0].cat)); |
2900 | } | 3085 | } |
2901 | if (mls_context_isvalid(&policydb, &ctx_new) != 1) | 3086 | rc = -EIDRM; |
2902 | goto netlbl_secattr_to_sid_return_cleanup; | 3087 | if (!mls_context_isvalid(&policydb, &ctx_new)) |
3088 | goto out_free; | ||
2903 | 3089 | ||
2904 | rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid); | 3090 | rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid); |
2905 | if (rc != 0) | 3091 | if (rc) |
2906 | goto netlbl_secattr_to_sid_return_cleanup; | 3092 | goto out_free; |
2907 | 3093 | ||
2908 | security_netlbl_cache_add(secattr, *sid); | 3094 | security_netlbl_cache_add(secattr, *sid); |
2909 | 3095 | ||
2910 | ebitmap_destroy(&ctx_new.range.level[0].cat); | 3096 | ebitmap_destroy(&ctx_new.range.level[0].cat); |
2911 | } else { | 3097 | } else |
2912 | *sid = SECSID_NULL; | 3098 | *sid = SECSID_NULL; |
2913 | rc = 0; | ||
2914 | } | ||
2915 | 3099 | ||
2916 | netlbl_secattr_to_sid_return: | ||
2917 | read_unlock(&policy_rwlock); | 3100 | read_unlock(&policy_rwlock); |
2918 | return rc; | 3101 | return 0; |
2919 | netlbl_secattr_to_sid_return_cleanup: | 3102 | out_free: |
2920 | ebitmap_destroy(&ctx_new.range.level[0].cat); | 3103 | ebitmap_destroy(&ctx_new.range.level[0].cat); |
2921 | goto netlbl_secattr_to_sid_return; | 3104 | out: |
3105 | read_unlock(&policy_rwlock); | ||
3106 | return rc; | ||
2922 | } | 3107 | } |
2923 | 3108 | ||
2924 | /** | 3109 | /** |
@@ -2940,29 +3125,59 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) | |||
2940 | return 0; | 3125 | return 0; |
2941 | 3126 | ||
2942 | read_lock(&policy_rwlock); | 3127 | read_lock(&policy_rwlock); |
3128 | |||
3129 | rc = -ENOENT; | ||
2943 | ctx = sidtab_search(&sidtab, sid); | 3130 | ctx = sidtab_search(&sidtab, sid); |
2944 | if (ctx == NULL) { | 3131 | if (ctx == NULL) |
2945 | rc = -ENOENT; | 3132 | goto out; |
2946 | goto netlbl_sid_to_secattr_failure; | 3133 | |
2947 | } | 3134 | rc = -ENOMEM; |
2948 | secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], | 3135 | secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1), |
2949 | GFP_ATOMIC); | 3136 | GFP_ATOMIC); |
2950 | if (secattr->domain == NULL) { | 3137 | if (secattr->domain == NULL) |
2951 | rc = -ENOMEM; | 3138 | goto out; |
2952 | goto netlbl_sid_to_secattr_failure; | 3139 | |
2953 | } | ||
2954 | secattr->attr.secid = sid; | 3140 | secattr->attr.secid = sid; |
2955 | secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID; | 3141 | secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID; |
2956 | mls_export_netlbl_lvl(ctx, secattr); | 3142 | mls_export_netlbl_lvl(ctx, secattr); |
2957 | rc = mls_export_netlbl_cat(ctx, secattr); | 3143 | rc = mls_export_netlbl_cat(ctx, secattr); |
2958 | if (rc != 0) | 3144 | out: |
2959 | goto netlbl_sid_to_secattr_failure; | ||
2960 | read_unlock(&policy_rwlock); | 3145 | read_unlock(&policy_rwlock); |
3146 | return rc; | ||
3147 | } | ||
3148 | #endif /* CONFIG_NETLABEL */ | ||
2961 | 3149 | ||
2962 | return 0; | 3150 | /** |
3151 | * security_read_policy - read the policy. | ||
3152 | * @data: binary policy data | ||
3153 | * @len: length of data in bytes | ||
3154 | * | ||
3155 | */ | ||
3156 | int security_read_policy(void **data, ssize_t *len) | ||
3157 | { | ||
3158 | int rc; | ||
3159 | struct policy_file fp; | ||
2963 | 3160 | ||
2964 | netlbl_sid_to_secattr_failure: | 3161 | if (!ss_initialized) |
3162 | return -EINVAL; | ||
3163 | |||
3164 | *len = security_policydb_len(); | ||
3165 | |||
3166 | *data = vmalloc_user(*len); | ||
3167 | if (!*data) | ||
3168 | return -ENOMEM; | ||
3169 | |||
3170 | fp.data = *data; | ||
3171 | fp.len = *len; | ||
3172 | |||
3173 | read_lock(&policy_rwlock); | ||
3174 | rc = policydb_write(&policydb, &fp); | ||
2965 | read_unlock(&policy_rwlock); | 3175 | read_unlock(&policy_rwlock); |
2966 | return rc; | 3176 | |
3177 | if (rc) | ||
3178 | return rc; | ||
3179 | |||
3180 | *len = (unsigned long)fp.data - (unsigned long)*data; | ||
3181 | return 0; | ||
3182 | |||
2967 | } | 3183 | } |
2968 | #endif /* CONFIG_NETLABEL */ | ||
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index e817989764c..5840a35155f 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c | |||
@@ -147,6 +147,17 @@ out: | |||
147 | return rc; | 147 | return rc; |
148 | } | 148 | } |
149 | 149 | ||
150 | static void sidtab_update_cache(struct sidtab *s, struct sidtab_node *n, int loc) | ||
151 | { | ||
152 | BUG_ON(loc >= SIDTAB_CACHE_LEN); | ||
153 | |||
154 | while (loc > 0) { | ||
155 | s->cache[loc] = s->cache[loc - 1]; | ||
156 | loc--; | ||
157 | } | ||
158 | s->cache[0] = n; | ||
159 | } | ||
160 | |||
150 | static inline u32 sidtab_search_context(struct sidtab *s, | 161 | static inline u32 sidtab_search_context(struct sidtab *s, |
151 | struct context *context) | 162 | struct context *context) |
152 | { | 163 | { |
@@ -156,14 +167,33 @@ static inline u32 sidtab_search_context(struct sidtab *s, | |||
156 | for (i = 0; i < SIDTAB_SIZE; i++) { | 167 | for (i = 0; i < SIDTAB_SIZE; i++) { |
157 | cur = s->htable[i]; | 168 | cur = s->htable[i]; |
158 | while (cur) { | 169 | while (cur) { |
159 | if (context_cmp(&cur->context, context)) | 170 | if (context_cmp(&cur->context, context)) { |
171 | sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1); | ||
160 | return cur->sid; | 172 | return cur->sid; |
173 | } | ||
161 | cur = cur->next; | 174 | cur = cur->next; |
162 | } | 175 | } |
163 | } | 176 | } |
164 | return 0; | 177 | return 0; |
165 | } | 178 | } |
166 | 179 | ||
180 | static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context) | ||
181 | { | ||
182 | int i; | ||
183 | struct sidtab_node *node; | ||
184 | |||
185 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) { | ||
186 | node = s->cache[i]; | ||
187 | if (unlikely(!node)) | ||
188 | return 0; | ||
189 | if (context_cmp(&node->context, context)) { | ||
190 | sidtab_update_cache(s, node, i); | ||
191 | return node->sid; | ||
192 | } | ||
193 | } | ||
194 | return 0; | ||
195 | } | ||
196 | |||
167 | int sidtab_context_to_sid(struct sidtab *s, | 197 | int sidtab_context_to_sid(struct sidtab *s, |
168 | struct context *context, | 198 | struct context *context, |
169 | u32 *out_sid) | 199 | u32 *out_sid) |
@@ -174,7 +204,9 @@ int sidtab_context_to_sid(struct sidtab *s, | |||
174 | 204 | ||
175 | *out_sid = SECSID_NULL; | 205 | *out_sid = SECSID_NULL; |
176 | 206 | ||
177 | sid = sidtab_search_context(s, context); | 207 | sid = sidtab_search_cache(s, context); |
208 | if (!sid) | ||
209 | sid = sidtab_search_context(s, context); | ||
178 | if (!sid) { | 210 | if (!sid) { |
179 | spin_lock_irqsave(&s->lock, flags); | 211 | spin_lock_irqsave(&s->lock, flags); |
180 | /* Rescan now that we hold the lock. */ | 212 | /* Rescan now that we hold the lock. */ |
@@ -259,12 +291,15 @@ void sidtab_destroy(struct sidtab *s) | |||
259 | void sidtab_set(struct sidtab *dst, struct sidtab *src) | 291 | void sidtab_set(struct sidtab *dst, struct sidtab *src) |
260 | { | 292 | { |
261 | unsigned long flags; | 293 | unsigned long flags; |
294 | int i; | ||
262 | 295 | ||
263 | spin_lock_irqsave(&src->lock, flags); | 296 | spin_lock_irqsave(&src->lock, flags); |
264 | dst->htable = src->htable; | 297 | dst->htable = src->htable; |
265 | dst->nel = src->nel; | 298 | dst->nel = src->nel; |
266 | dst->next_sid = src->next_sid; | 299 | dst->next_sid = src->next_sid; |
267 | dst->shutdown = 0; | 300 | dst->shutdown = 0; |
301 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) | ||
302 | dst->cache[i] = NULL; | ||
268 | spin_unlock_irqrestore(&src->lock, flags); | 303 | spin_unlock_irqrestore(&src->lock, flags); |
269 | } | 304 | } |
270 | 305 | ||
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index 64ea5b1cdea..84dc154d938 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h | |||
@@ -26,6 +26,8 @@ struct sidtab { | |||
26 | unsigned int nel; /* number of elements */ | 26 | unsigned int nel; /* number of elements */ |
27 | unsigned int next_sid; /* next SID to allocate */ | 27 | unsigned int next_sid; /* next SID to allocate */ |
28 | unsigned char shutdown; | 28 | unsigned char shutdown; |
29 | #define SIDTAB_CACHE_LEN 3 | ||
30 | struct sidtab_node *cache[SIDTAB_CACHE_LEN]; | ||
29 | spinlock_t lock; | 31 | spinlock_t lock; |
30 | }; | 32 | }; |
31 | 33 | ||
diff --git a/security/selinux/ss/status.c b/security/selinux/ss/status.c new file mode 100644 index 00000000000..d982365f9d1 --- /dev/null +++ b/security/selinux/ss/status.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * mmap based event notifications for SELinux | ||
3 | * | ||
4 | * Author: KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
5 | * | ||
6 | * Copyright (C) 2010 NEC corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2, | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/gfp.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include "avc.h" | ||
17 | #include "services.h" | ||
18 | |||
19 | /* | ||
20 | * The selinux_status_page shall be exposed to userspace applications | ||
21 | * using mmap interface on /selinux/status. | ||
22 | * It enables to notify applications a few events that will cause reset | ||
23 | * of userspace access vector without context switching. | ||
24 | * | ||
25 | * The selinux_kernel_status structure on the head of status page is | ||
26 | * protected from concurrent accesses using seqlock logic, so userspace | ||
27 | * application should reference the status page according to the seqlock | ||
28 | * logic. | ||
29 | * | ||
30 | * Typically, application checks status->sequence at the head of access | ||
31 | * control routine. If it is odd-number, kernel is updating the status, | ||
32 | * so please wait for a moment. If it is changed from the last sequence | ||
33 | * number, it means something happen, so application will reset userspace | ||
34 | * avc, if needed. | ||
35 | * In most cases, application shall confirm the kernel status is not | ||
36 | * changed without any system call invocations. | ||
37 | */ | ||
38 | static struct page *selinux_status_page; | ||
39 | static DEFINE_MUTEX(selinux_status_lock); | ||
40 | |||
41 | /* | ||
42 | * selinux_kernel_status_page | ||
43 | * | ||
44 | * It returns a reference to selinux_status_page. If the status page is | ||
45 | * not allocated yet, it also tries to allocate it at the first time. | ||
46 | */ | ||
47 | struct page *selinux_kernel_status_page(void) | ||
48 | { | ||
49 | struct selinux_kernel_status *status; | ||
50 | struct page *result = NULL; | ||
51 | |||
52 | mutex_lock(&selinux_status_lock); | ||
53 | if (!selinux_status_page) { | ||
54 | selinux_status_page = alloc_page(GFP_KERNEL|__GFP_ZERO); | ||
55 | |||
56 | if (selinux_status_page) { | ||
57 | status = page_address(selinux_status_page); | ||
58 | |||
59 | status->version = SELINUX_KERNEL_STATUS_VERSION; | ||
60 | status->sequence = 0; | ||
61 | status->enforcing = selinux_enforcing; | ||
62 | /* | ||
63 | * NOTE: the next policyload event shall set | ||
64 | * a positive value on the status->policyload, | ||
65 | * although it may not be 1, but never zero. | ||
66 | * So, application can know it was updated. | ||
67 | */ | ||
68 | status->policyload = 0; | ||
69 | status->deny_unknown = !security_get_allow_unknown(); | ||
70 | } | ||
71 | } | ||
72 | result = selinux_status_page; | ||
73 | mutex_unlock(&selinux_status_lock); | ||
74 | |||
75 | return result; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * selinux_status_update_setenforce | ||
80 | * | ||
81 | * It updates status of the current enforcing/permissive mode. | ||
82 | */ | ||
83 | void selinux_status_update_setenforce(int enforcing) | ||
84 | { | ||
85 | struct selinux_kernel_status *status; | ||
86 | |||
87 | mutex_lock(&selinux_status_lock); | ||
88 | if (selinux_status_page) { | ||
89 | status = page_address(selinux_status_page); | ||
90 | |||
91 | status->sequence++; | ||
92 | smp_wmb(); | ||
93 | |||
94 | status->enforcing = enforcing; | ||
95 | |||
96 | smp_wmb(); | ||
97 | status->sequence++; | ||
98 | } | ||
99 | mutex_unlock(&selinux_status_lock); | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * selinux_status_update_policyload | ||
104 | * | ||
105 | * It updates status of the times of policy reloaded, and current | ||
106 | * setting of deny_unknown. | ||
107 | */ | ||
108 | void selinux_status_update_policyload(int seqno) | ||
109 | { | ||
110 | struct selinux_kernel_status *status; | ||
111 | |||
112 | mutex_lock(&selinux_status_lock); | ||
113 | if (selinux_status_page) { | ||
114 | status = page_address(selinux_status_page); | ||
115 | |||
116 | status->sequence++; | ||
117 | smp_wmb(); | ||
118 | |||
119 | status->policyload = seqno; | ||
120 | status->deny_unknown = !security_get_allow_unknown(); | ||
121 | |||
122 | smp_wmb(); | ||
123 | status->sequence++; | ||
124 | } | ||
125 | mutex_unlock(&selinux_status_lock); | ||
126 | } | ||
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 837658a98a5..160326ee99e 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c | |||
@@ -4,7 +4,6 @@ | |||
4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> | 4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> |
5 | */ | 5 | */ |
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/slab.h> | ||
8 | #include <linux/string.h> | 7 | #include <linux/string.h> |
9 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
10 | #include "symtab.h" | 9 | #include "symtab.h" |
@@ -37,7 +36,7 @@ int symtab_init(struct symtab *s, unsigned int size) | |||
37 | { | 36 | { |
38 | s->table = hashtab_create(symhash, symcmp, size); | 37 | s->table = hashtab_create(symhash, symcmp, size); |
39 | if (!s->table) | 38 | if (!s->table) |
40 | return -1; | 39 | return -ENOMEM; |
41 | s->nprim = 0; | 40 | s->nprim = 0; |
42 | return 0; | 41 | return 0; |
43 | } | 42 | } |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 72b18452e1a..fff78d3b51a 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/netfilter.h> | 38 | #include <linux/netfilter.h> |
39 | #include <linux/netfilter_ipv4.h> | 39 | #include <linux/netfilter_ipv4.h> |
40 | #include <linux/netfilter_ipv6.h> | 40 | #include <linux/netfilter_ipv6.h> |
41 | #include <linux/slab.h> | ||
41 | #include <linux/ip.h> | 42 | #include <linux/ip.h> |
42 | #include <linux/tcp.h> | 43 | #include <linux/tcp.h> |
43 | #include <linux/skbuff.h> | 44 | #include <linux/skbuff.h> |
@@ -401,7 +402,7 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) | |||
401 | * gone thru the IPSec process. | 402 | * gone thru the IPSec process. |
402 | */ | 403 | */ |
403 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 404 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
404 | struct avc_audit_data *ad) | 405 | struct common_audit_data *ad) |
405 | { | 406 | { |
406 | int i, rc = 0; | 407 | int i, rc = 0; |
407 | struct sec_path *sp; | 408 | struct sec_path *sp; |
@@ -442,7 +443,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | |||
442 | * checked in the selinux_xfrm_state_pol_flow_match hook above. | 443 | * checked in the selinux_xfrm_state_pol_flow_match hook above. |
443 | */ | 444 | */ |
444 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 445 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
445 | struct avc_audit_data *ad, u8 proto) | 446 | struct common_audit_data *ad, u8 proto) |
446 | { | 447 | { |
447 | struct dst_entry *dst; | 448 | struct dst_entry *dst; |
448 | int rc = 0; | 449 | int rc = 0; |