diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 562 |
1 files changed, 291 insertions, 271 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ff17820d35ec..d6bb20cbad62 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -65,16 +65,10 @@ | |||
65 | #include "audit.h" | 65 | #include "audit.h" |
66 | 66 | ||
67 | extern void selnl_notify_policyload(u32 seqno); | 67 | extern void selnl_notify_policyload(u32 seqno); |
68 | unsigned int policydb_loaded_version; | ||
69 | 68 | ||
70 | int selinux_policycap_netpeer; | 69 | int selinux_policycap_netpeer; |
71 | int selinux_policycap_openperm; | 70 | int selinux_policycap_openperm; |
72 | 71 | ||
73 | /* | ||
74 | * This is declared in avc.c | ||
75 | */ | ||
76 | extern const struct selinux_class_perm selinux_class_perm; | ||
77 | |||
78 | static DEFINE_RWLOCK(policy_rwlock); | 72 | static DEFINE_RWLOCK(policy_rwlock); |
79 | 73 | ||
80 | static struct sidtab sidtab; | 74 | static struct sidtab sidtab; |
@@ -98,6 +92,165 @@ static int context_struct_compute_av(struct context *scontext, | |||
98 | u16 tclass, | 92 | u16 tclass, |
99 | u32 requested, | 93 | u32 requested, |
100 | struct av_decision *avd); | 94 | struct av_decision *avd); |
95 | |||
96 | struct selinux_mapping { | ||
97 | u16 value; /* policy value */ | ||
98 | unsigned num_perms; | ||
99 | u32 perms[sizeof(u32) * 8]; | ||
100 | }; | ||
101 | |||
102 | static struct selinux_mapping *current_mapping; | ||
103 | static u16 current_mapping_size; | ||
104 | |||
105 | static int selinux_set_mapping(struct policydb *pol, | ||
106 | struct security_class_mapping *map, | ||
107 | struct selinux_mapping **out_map_p, | ||
108 | u16 *out_map_size) | ||
109 | { | ||
110 | struct selinux_mapping *out_map = NULL; | ||
111 | size_t size = sizeof(struct selinux_mapping); | ||
112 | u16 i, j; | ||
113 | unsigned k; | ||
114 | bool print_unknown_handle = false; | ||
115 | |||
116 | /* Find number of classes in the input mapping */ | ||
117 | if (!map) | ||
118 | return -EINVAL; | ||
119 | i = 0; | ||
120 | while (map[i].name) | ||
121 | i++; | ||
122 | |||
123 | /* Allocate space for the class records, plus one for class zero */ | ||
124 | out_map = kcalloc(++i, size, GFP_ATOMIC); | ||
125 | if (!out_map) | ||
126 | return -ENOMEM; | ||
127 | |||
128 | /* Store the raw class and permission values */ | ||
129 | j = 0; | ||
130 | while (map[j].name) { | ||
131 | struct security_class_mapping *p_in = map + (j++); | ||
132 | struct selinux_mapping *p_out = out_map + j; | ||
133 | |||
134 | /* An empty class string skips ahead */ | ||
135 | if (!strcmp(p_in->name, "")) { | ||
136 | p_out->num_perms = 0; | ||
137 | continue; | ||
138 | } | ||
139 | |||
140 | p_out->value = string_to_security_class(pol, p_in->name); | ||
141 | if (!p_out->value) { | ||
142 | printk(KERN_INFO | ||
143 | "SELinux: Class %s not defined in policy.\n", | ||
144 | p_in->name); | ||
145 | if (pol->reject_unknown) | ||
146 | goto err; | ||
147 | p_out->num_perms = 0; | ||
148 | print_unknown_handle = true; | ||
149 | continue; | ||
150 | } | ||
151 | |||
152 | k = 0; | ||
153 | while (p_in->perms && p_in->perms[k]) { | ||
154 | /* An empty permission string skips ahead */ | ||
155 | if (!*p_in->perms[k]) { | ||
156 | k++; | ||
157 | continue; | ||
158 | } | ||
159 | p_out->perms[k] = string_to_av_perm(pol, p_out->value, | ||
160 | p_in->perms[k]); | ||
161 | if (!p_out->perms[k]) { | ||
162 | printk(KERN_INFO | ||
163 | "SELinux: Permission %s in class %s not defined in policy.\n", | ||
164 | p_in->perms[k], p_in->name); | ||
165 | if (pol->reject_unknown) | ||
166 | goto err; | ||
167 | print_unknown_handle = true; | ||
168 | } | ||
169 | |||
170 | k++; | ||
171 | } | ||
172 | p_out->num_perms = k; | ||
173 | } | ||
174 | |||
175 | if (print_unknown_handle) | ||
176 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
177 | pol->allow_unknown ? "allowed" : "denied"); | ||
178 | |||
179 | *out_map_p = out_map; | ||
180 | *out_map_size = i; | ||
181 | return 0; | ||
182 | err: | ||
183 | kfree(out_map); | ||
184 | return -EINVAL; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * Get real, policy values from mapped values | ||
189 | */ | ||
190 | |||
191 | static u16 unmap_class(u16 tclass) | ||
192 | { | ||
193 | if (tclass < current_mapping_size) | ||
194 | return current_mapping[tclass].value; | ||
195 | |||
196 | return tclass; | ||
197 | } | ||
198 | |||
199 | static u32 unmap_perm(u16 tclass, u32 tperm) | ||
200 | { | ||
201 | if (tclass < current_mapping_size) { | ||
202 | unsigned i; | ||
203 | u32 kperm = 0; | ||
204 | |||
205 | for (i = 0; i < current_mapping[tclass].num_perms; i++) | ||
206 | if (tperm & (1<<i)) { | ||
207 | kperm |= current_mapping[tclass].perms[i]; | ||
208 | tperm &= ~(1<<i); | ||
209 | } | ||
210 | return kperm; | ||
211 | } | ||
212 | |||
213 | return tperm; | ||
214 | } | ||
215 | |||
216 | static void map_decision(u16 tclass, struct av_decision *avd, | ||
217 | int allow_unknown) | ||
218 | { | ||
219 | if (tclass < current_mapping_size) { | ||
220 | unsigned i, n = current_mapping[tclass].num_perms; | ||
221 | u32 result; | ||
222 | |||
223 | for (i = 0, result = 0; i < n; i++) { | ||
224 | if (avd->allowed & current_mapping[tclass].perms[i]) | ||
225 | result |= 1<<i; | ||
226 | if (allow_unknown && !current_mapping[tclass].perms[i]) | ||
227 | result |= 1<<i; | ||
228 | } | ||
229 | avd->allowed = result; | ||
230 | |||
231 | for (i = 0, result = 0; i < n; i++) | ||
232 | if (avd->auditallow & current_mapping[tclass].perms[i]) | ||
233 | result |= 1<<i; | ||
234 | avd->auditallow = result; | ||
235 | |||
236 | for (i = 0, result = 0; i < n; i++) { | ||
237 | if (avd->auditdeny & current_mapping[tclass].perms[i]) | ||
238 | result |= 1<<i; | ||
239 | if (!allow_unknown && !current_mapping[tclass].perms[i]) | ||
240 | result |= 1<<i; | ||
241 | } | ||
242 | /* | ||
243 | * In case the kernel has a bug and requests a permission | ||
244 | * between num_perms and the maximum permission number, we | ||
245 | * should audit that denial | ||
246 | */ | ||
247 | for (; i < (sizeof(u32)*8); i++) | ||
248 | result |= 1<<i; | ||
249 | avd->auditdeny = result; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | |||
101 | /* | 254 | /* |
102 | * Return the boolean value of a constraint expression | 255 | * Return the boolean value of a constraint expression |
103 | * when it is applied to the specified source and target | 256 | * when it is applied to the specified source and target |
@@ -467,21 +620,9 @@ static int context_struct_compute_av(struct context *scontext, | |||
467 | struct class_datum *tclass_datum; | 620 | struct class_datum *tclass_datum; |
468 | struct ebitmap *sattr, *tattr; | 621 | struct ebitmap *sattr, *tattr; |
469 | struct ebitmap_node *snode, *tnode; | 622 | struct ebitmap_node *snode, *tnode; |
470 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
471 | unsigned int i, j; | 623 | unsigned int i, j; |
472 | 624 | ||
473 | /* | 625 | /* |
474 | * Remap extended Netlink classes for old policy versions. | ||
475 | * Do this here rather than socket_type_to_security_class() | ||
476 | * in case a newer policy version is loaded, allowing sockets | ||
477 | * to remain in the correct class. | ||
478 | */ | ||
479 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
480 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
481 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
482 | tclass = SECCLASS_NETLINK_SOCKET; | ||
483 | |||
484 | /* | ||
485 | * Initialize the access vectors to the default values. | 626 | * Initialize the access vectors to the default values. |
486 | */ | 627 | */ |
487 | avd->allowed = 0; | 628 | avd->allowed = 0; |
@@ -490,33 +631,11 @@ static int context_struct_compute_av(struct context *scontext, | |||
490 | avd->seqno = latest_granting; | 631 | avd->seqno = latest_granting; |
491 | avd->flags = 0; | 632 | avd->flags = 0; |
492 | 633 | ||
493 | /* | 634 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { |
494 | * Check for all the invalid cases. | 635 | if (printk_ratelimit()) |
495 | * - tclass 0 | 636 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); |
496 | * - tclass > policy and > kernel | 637 | return -EINVAL; |
497 | * - tclass > policy but is a userspace class | 638 | } |
498 | * - tclass > policy but we do not allow unknowns | ||
499 | */ | ||
500 | if (unlikely(!tclass)) | ||
501 | goto inval_class; | ||
502 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
503 | if (tclass > kdefs->cts_len || | ||
504 | !kdefs->class_to_string[tclass] || | ||
505 | !policydb.allow_unknown) | ||
506 | goto inval_class; | ||
507 | |||
508 | /* | ||
509 | * Kernel class and we allow unknown so pad the allow decision | ||
510 | * the pad will be all 1 for unknown classes. | ||
511 | */ | ||
512 | if (tclass <= kdefs->cts_len && policydb.allow_unknown) | ||
513 | avd->allowed = policydb.undefined_perms[tclass - 1]; | ||
514 | |||
515 | /* | ||
516 | * Not in policy. Since decision is completed (all 1 or all 0) return. | ||
517 | */ | ||
518 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
519 | return 0; | ||
520 | 639 | ||
521 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 640 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; |
522 | 641 | ||
@@ -568,8 +687,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
568 | * role is changing, then check the (current_role, new_role) | 687 | * role is changing, then check the (current_role, new_role) |
569 | * pair. | 688 | * pair. |
570 | */ | 689 | */ |
571 | if (tclass == SECCLASS_PROCESS && | 690 | if (tclass == policydb.process_class && |
572 | (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && | 691 | (avd->allowed & policydb.process_trans_perms) && |
573 | scontext->role != tcontext->role) { | 692 | scontext->role != tcontext->role) { |
574 | for (ra = policydb.role_allow; ra; ra = ra->next) { | 693 | for (ra = policydb.role_allow; ra; ra = ra->next) { |
575 | if (scontext->role == ra->role && | 694 | if (scontext->role == ra->role && |
@@ -577,8 +696,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
577 | break; | 696 | break; |
578 | } | 697 | } |
579 | if (!ra) | 698 | if (!ra) |
580 | avd->allowed &= ~(PROCESS__TRANSITION | | 699 | avd->allowed &= ~policydb.process_trans_perms; |
581 | PROCESS__DYNTRANSITION); | ||
582 | } | 700 | } |
583 | 701 | ||
584 | /* | 702 | /* |
@@ -590,21 +708,6 @@ static int context_struct_compute_av(struct context *scontext, | |||
590 | tclass, requested, avd); | 708 | tclass, requested, avd); |
591 | 709 | ||
592 | return 0; | 710 | return 0; |
593 | |||
594 | inval_class: | ||
595 | if (!tclass || tclass > kdefs->cts_len || | ||
596 | !kdefs->class_to_string[tclass]) { | ||
597 | if (printk_ratelimit()) | ||
598 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | ||
599 | __func__, tclass); | ||
600 | return -EINVAL; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * Known to the kernel, but not to the policy. | ||
605 | * Handle as a denial (allowed is 0). | ||
606 | */ | ||
607 | return 0; | ||
608 | } | 711 | } |
609 | 712 | ||
610 | static int security_validtrans_handle_fail(struct context *ocontext, | 713 | static int security_validtrans_handle_fail(struct context *ocontext, |
@@ -636,13 +739,14 @@ out: | |||
636 | } | 739 | } |
637 | 740 | ||
638 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 741 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, |
639 | u16 tclass) | 742 | u16 orig_tclass) |
640 | { | 743 | { |
641 | struct context *ocontext; | 744 | struct context *ocontext; |
642 | struct context *ncontext; | 745 | struct context *ncontext; |
643 | struct context *tcontext; | 746 | struct context *tcontext; |
644 | struct class_datum *tclass_datum; | 747 | struct class_datum *tclass_datum; |
645 | struct constraint_node *constraint; | 748 | struct constraint_node *constraint; |
749 | u16 tclass; | ||
646 | int rc = 0; | 750 | int rc = 0; |
647 | 751 | ||
648 | if (!ss_initialized) | 752 | if (!ss_initialized) |
@@ -650,16 +754,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | |||
650 | 754 | ||
651 | read_lock(&policy_rwlock); | 755 | read_lock(&policy_rwlock); |
652 | 756 | ||
653 | /* | 757 | tclass = unmap_class(orig_tclass); |
654 | * Remap extended Netlink classes for old policy versions. | ||
655 | * Do this here rather than socket_type_to_security_class() | ||
656 | * in case a newer policy version is loaded, allowing sockets | ||
657 | * to remain in the correct class. | ||
658 | */ | ||
659 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
660 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
661 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
662 | tclass = SECCLASS_NETLINK_SOCKET; | ||
663 | 758 | ||
664 | if (!tclass || tclass > policydb.p_classes.nprim) { | 759 | if (!tclass || tclass > policydb.p_classes.nprim) { |
665 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | 760 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", |
@@ -792,6 +887,38 @@ out: | |||
792 | } | 887 | } |
793 | 888 | ||
794 | 889 | ||
890 | static int security_compute_av_core(u32 ssid, | ||
891 | u32 tsid, | ||
892 | u16 tclass, | ||
893 | u32 requested, | ||
894 | struct av_decision *avd) | ||
895 | { | ||
896 | struct context *scontext = NULL, *tcontext = NULL; | ||
897 | int rc = 0; | ||
898 | |||
899 | scontext = sidtab_search(&sidtab, ssid); | ||
900 | if (!scontext) { | ||
901 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
902 | __func__, ssid); | ||
903 | return -EINVAL; | ||
904 | } | ||
905 | tcontext = sidtab_search(&sidtab, tsid); | ||
906 | if (!tcontext) { | ||
907 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
908 | __func__, tsid); | ||
909 | return -EINVAL; | ||
910 | } | ||
911 | |||
912 | rc = context_struct_compute_av(scontext, tcontext, tclass, | ||
913 | requested, avd); | ||
914 | |||
915 | /* permissive domain? */ | ||
916 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
917 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
918 | |||
919 | return rc; | ||
920 | } | ||
921 | |||
795 | /** | 922 | /** |
796 | * security_compute_av - Compute access vector decisions. | 923 | * security_compute_av - Compute access vector decisions. |
797 | * @ssid: source security identifier | 924 | * @ssid: source security identifier |
@@ -807,12 +934,49 @@ out: | |||
807 | */ | 934 | */ |
808 | int security_compute_av(u32 ssid, | 935 | int security_compute_av(u32 ssid, |
809 | u32 tsid, | 936 | u32 tsid, |
810 | u16 tclass, | 937 | u16 orig_tclass, |
811 | u32 requested, | 938 | u32 orig_requested, |
812 | struct av_decision *avd) | 939 | struct av_decision *avd) |
813 | { | 940 | { |
814 | struct context *scontext = NULL, *tcontext = NULL; | 941 | u16 tclass; |
815 | int rc = 0; | 942 | u32 requested; |
943 | int rc; | ||
944 | |||
945 | read_lock(&policy_rwlock); | ||
946 | |||
947 | if (!ss_initialized) | ||
948 | goto allow; | ||
949 | |||
950 | requested = unmap_perm(orig_tclass, orig_requested); | ||
951 | tclass = unmap_class(orig_tclass); | ||
952 | if (unlikely(orig_tclass && !tclass)) { | ||
953 | if (policydb.allow_unknown) | ||
954 | goto allow; | ||
955 | rc = -EINVAL; | ||
956 | goto out; | ||
957 | } | ||
958 | rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); | ||
959 | map_decision(orig_tclass, avd, policydb.allow_unknown); | ||
960 | out: | ||
961 | read_unlock(&policy_rwlock); | ||
962 | return rc; | ||
963 | allow: | ||
964 | avd->allowed = 0xffffffff; | ||
965 | avd->auditallow = 0; | ||
966 | avd->auditdeny = 0xffffffff; | ||
967 | avd->seqno = latest_granting; | ||
968 | avd->flags = 0; | ||
969 | rc = 0; | ||
970 | goto out; | ||
971 | } | ||
972 | |||
973 | int security_compute_av_user(u32 ssid, | ||
974 | u32 tsid, | ||
975 | u16 tclass, | ||
976 | u32 requested, | ||
977 | struct av_decision *avd) | ||
978 | { | ||
979 | int rc; | ||
816 | 980 | ||
817 | if (!ss_initialized) { | 981 | if (!ss_initialized) { |
818 | avd->allowed = 0xffffffff; | 982 | avd->allowed = 0xffffffff; |
@@ -823,29 +987,7 @@ int security_compute_av(u32 ssid, | |||
823 | } | 987 | } |
824 | 988 | ||
825 | read_lock(&policy_rwlock); | 989 | read_lock(&policy_rwlock); |
826 | 990 | rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); | |
827 | scontext = sidtab_search(&sidtab, ssid); | ||
828 | if (!scontext) { | ||
829 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
830 | __func__, ssid); | ||
831 | rc = -EINVAL; | ||
832 | goto out; | ||
833 | } | ||
834 | tcontext = sidtab_search(&sidtab, tsid); | ||
835 | if (!tcontext) { | ||
836 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
837 | __func__, tsid); | ||
838 | rc = -EINVAL; | ||
839 | goto out; | ||
840 | } | ||
841 | |||
842 | rc = context_struct_compute_av(scontext, tcontext, tclass, | ||
843 | requested, avd); | ||
844 | |||
845 | /* permissive domain? */ | ||
846 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
847 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
848 | out: | ||
849 | read_unlock(&policy_rwlock); | 991 | read_unlock(&policy_rwlock); |
850 | return rc; | 992 | return rc; |
851 | } | 993 | } |
@@ -1204,20 +1346,22 @@ out: | |||
1204 | 1346 | ||
1205 | static int security_compute_sid(u32 ssid, | 1347 | static int security_compute_sid(u32 ssid, |
1206 | u32 tsid, | 1348 | u32 tsid, |
1207 | u16 tclass, | 1349 | u16 orig_tclass, |
1208 | u32 specified, | 1350 | u32 specified, |
1209 | u32 *out_sid) | 1351 | u32 *out_sid, |
1352 | bool kern) | ||
1210 | { | 1353 | { |
1211 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1354 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1212 | struct role_trans *roletr = NULL; | 1355 | struct role_trans *roletr = NULL; |
1213 | struct avtab_key avkey; | 1356 | struct avtab_key avkey; |
1214 | struct avtab_datum *avdatum; | 1357 | struct avtab_datum *avdatum; |
1215 | struct avtab_node *node; | 1358 | struct avtab_node *node; |
1359 | u16 tclass; | ||
1216 | int rc = 0; | 1360 | int rc = 0; |
1217 | 1361 | ||
1218 | if (!ss_initialized) { | 1362 | if (!ss_initialized) { |
1219 | switch (tclass) { | 1363 | switch (orig_tclass) { |
1220 | case SECCLASS_PROCESS: | 1364 | case SECCLASS_PROCESS: /* kernel value */ |
1221 | *out_sid = ssid; | 1365 | *out_sid = ssid; |
1222 | break; | 1366 | break; |
1223 | default: | 1367 | default: |
@@ -1231,6 +1375,11 @@ static int security_compute_sid(u32 ssid, | |||
1231 | 1375 | ||
1232 | read_lock(&policy_rwlock); | 1376 | read_lock(&policy_rwlock); |
1233 | 1377 | ||
1378 | if (kern) | ||
1379 | tclass = unmap_class(orig_tclass); | ||
1380 | else | ||
1381 | tclass = orig_tclass; | ||
1382 | |||
1234 | scontext = sidtab_search(&sidtab, ssid); | 1383 | scontext = sidtab_search(&sidtab, ssid); |
1235 | if (!scontext) { | 1384 | if (!scontext) { |
1236 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1385 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
@@ -1260,13 +1409,11 @@ static int security_compute_sid(u32 ssid, | |||
1260 | } | 1409 | } |
1261 | 1410 | ||
1262 | /* Set the role and type to default values. */ | 1411 | /* Set the role and type to default values. */ |
1263 | switch (tclass) { | 1412 | if (tclass == policydb.process_class) { |
1264 | case SECCLASS_PROCESS: | ||
1265 | /* Use the current role and type of process. */ | 1413 | /* Use the current role and type of process. */ |
1266 | newcontext.role = scontext->role; | 1414 | newcontext.role = scontext->role; |
1267 | newcontext.type = scontext->type; | 1415 | newcontext.type = scontext->type; |
1268 | break; | 1416 | } else { |
1269 | default: | ||
1270 | /* Use the well-defined object role. */ | 1417 | /* Use the well-defined object role. */ |
1271 | newcontext.role = OBJECT_R_VAL; | 1418 | newcontext.role = OBJECT_R_VAL; |
1272 | /* Use the type of the related object. */ | 1419 | /* Use the type of the related object. */ |
@@ -1297,8 +1444,7 @@ static int security_compute_sid(u32 ssid, | |||
1297 | } | 1444 | } |
1298 | 1445 | ||
1299 | /* Check for class-specific changes. */ | 1446 | /* Check for class-specific changes. */ |
1300 | switch (tclass) { | 1447 | if (tclass == policydb.process_class) { |
1301 | case SECCLASS_PROCESS: | ||
1302 | if (specified & AVTAB_TRANSITION) { | 1448 | if (specified & AVTAB_TRANSITION) { |
1303 | /* Look for a role transition rule. */ | 1449 | /* Look for a role transition rule. */ |
1304 | for (roletr = policydb.role_tr; roletr; | 1450 | for (roletr = policydb.role_tr; roletr; |
@@ -1311,9 +1457,6 @@ static int security_compute_sid(u32 ssid, | |||
1311 | } | 1457 | } |
1312 | } | 1458 | } |
1313 | } | 1459 | } |
1314 | break; | ||
1315 | default: | ||
1316 | break; | ||
1317 | } | 1460 | } |
1318 | 1461 | ||
1319 | /* Set the MLS attributes. | 1462 | /* Set the MLS attributes. |
@@ -1358,7 +1501,17 @@ int security_transition_sid(u32 ssid, | |||
1358 | u16 tclass, | 1501 | u16 tclass, |
1359 | u32 *out_sid) | 1502 | u32 *out_sid) |
1360 | { | 1503 | { |
1361 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); | 1504 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1505 | out_sid, true); | ||
1506 | } | ||
1507 | |||
1508 | int security_transition_sid_user(u32 ssid, | ||
1509 | u32 tsid, | ||
1510 | u16 tclass, | ||
1511 | u32 *out_sid) | ||
1512 | { | ||
1513 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | ||
1514 | out_sid, false); | ||
1362 | } | 1515 | } |
1363 | 1516 | ||
1364 | /** | 1517 | /** |
@@ -1379,7 +1532,8 @@ int security_member_sid(u32 ssid, | |||
1379 | u16 tclass, | 1532 | u16 tclass, |
1380 | u32 *out_sid) | 1533 | u32 *out_sid) |
1381 | { | 1534 | { |
1382 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); | 1535 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, |
1536 | false); | ||
1383 | } | 1537 | } |
1384 | 1538 | ||
1385 | /** | 1539 | /** |
@@ -1400,144 +1554,8 @@ int security_change_sid(u32 ssid, | |||
1400 | u16 tclass, | 1554 | u16 tclass, |
1401 | u32 *out_sid) | 1555 | u32 *out_sid) |
1402 | { | 1556 | { |
1403 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); | 1557 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, |
1404 | } | 1558 | false); |
1405 | |||
1406 | /* | ||
1407 | * Verify that each kernel class that is defined in the | ||
1408 | * policy is correct | ||
1409 | */ | ||
1410 | static int validate_classes(struct policydb *p) | ||
1411 | { | ||
1412 | int i, j; | ||
1413 | struct class_datum *cladatum; | ||
1414 | struct perm_datum *perdatum; | ||
1415 | u32 nprim, tmp, common_pts_len, perm_val, pol_val; | ||
1416 | u16 class_val; | ||
1417 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
1418 | const char *def_class, *def_perm, *pol_class; | ||
1419 | struct symtab *perms; | ||
1420 | bool print_unknown_handle = 0; | ||
1421 | |||
1422 | if (p->allow_unknown) { | ||
1423 | u32 num_classes = kdefs->cts_len; | ||
1424 | p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL); | ||
1425 | if (!p->undefined_perms) | ||
1426 | return -ENOMEM; | ||
1427 | } | ||
1428 | |||
1429 | for (i = 1; i < kdefs->cts_len; i++) { | ||
1430 | def_class = kdefs->class_to_string[i]; | ||
1431 | if (!def_class) | ||
1432 | continue; | ||
1433 | if (i > p->p_classes.nprim) { | ||
1434 | printk(KERN_INFO | ||
1435 | "SELinux: class %s not defined in policy\n", | ||
1436 | def_class); | ||
1437 | if (p->reject_unknown) | ||
1438 | return -EINVAL; | ||
1439 | if (p->allow_unknown) | ||
1440 | p->undefined_perms[i-1] = ~0U; | ||
1441 | print_unknown_handle = 1; | ||
1442 | continue; | ||
1443 | } | ||
1444 | pol_class = p->p_class_val_to_name[i-1]; | ||
1445 | if (strcmp(pol_class, def_class)) { | ||
1446 | printk(KERN_ERR | ||
1447 | "SELinux: class %d is incorrect, found %s but should be %s\n", | ||
1448 | i, pol_class, def_class); | ||
1449 | return -EINVAL; | ||
1450 | } | ||
1451 | } | ||
1452 | for (i = 0; i < kdefs->av_pts_len; i++) { | ||
1453 | class_val = kdefs->av_perm_to_string[i].tclass; | ||
1454 | perm_val = kdefs->av_perm_to_string[i].value; | ||
1455 | def_perm = kdefs->av_perm_to_string[i].name; | ||
1456 | if (class_val > p->p_classes.nprim) | ||
1457 | continue; | ||
1458 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1459 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1460 | BUG_ON(!cladatum); | ||
1461 | perms = &cladatum->permissions; | ||
1462 | nprim = 1 << (perms->nprim - 1); | ||
1463 | if (perm_val > nprim) { | ||
1464 | printk(KERN_INFO | ||
1465 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1466 | def_perm, pol_class); | ||
1467 | if (p->reject_unknown) | ||
1468 | return -EINVAL; | ||
1469 | if (p->allow_unknown) | ||
1470 | p->undefined_perms[class_val-1] |= perm_val; | ||
1471 | print_unknown_handle = 1; | ||
1472 | continue; | ||
1473 | } | ||
1474 | perdatum = hashtab_search(perms->table, def_perm); | ||
1475 | if (perdatum == NULL) { | ||
1476 | printk(KERN_ERR | ||
1477 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1478 | def_perm, pol_class); | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | pol_val = 1 << (perdatum->value - 1); | ||
1482 | if (pol_val != perm_val) { | ||
1483 | printk(KERN_ERR | ||
1484 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1485 | def_perm, pol_class); | ||
1486 | return -EINVAL; | ||
1487 | } | ||
1488 | } | ||
1489 | for (i = 0; i < kdefs->av_inherit_len; i++) { | ||
1490 | class_val = kdefs->av_inherit[i].tclass; | ||
1491 | if (class_val > p->p_classes.nprim) | ||
1492 | continue; | ||
1493 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1494 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1495 | BUG_ON(!cladatum); | ||
1496 | if (!cladatum->comdatum) { | ||
1497 | printk(KERN_ERR | ||
1498 | "SELinux: class %s should have an inherits clause but does not\n", | ||
1499 | pol_class); | ||
1500 | return -EINVAL; | ||
1501 | } | ||
1502 | tmp = kdefs->av_inherit[i].common_base; | ||
1503 | common_pts_len = 0; | ||
1504 | while (!(tmp & 0x01)) { | ||
1505 | common_pts_len++; | ||
1506 | tmp >>= 1; | ||
1507 | } | ||
1508 | perms = &cladatum->comdatum->permissions; | ||
1509 | for (j = 0; j < common_pts_len; j++) { | ||
1510 | def_perm = kdefs->av_inherit[i].common_pts[j]; | ||
1511 | if (j >= perms->nprim) { | ||
1512 | printk(KERN_INFO | ||
1513 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1514 | def_perm, pol_class); | ||
1515 | if (p->reject_unknown) | ||
1516 | return -EINVAL; | ||
1517 | if (p->allow_unknown) | ||
1518 | p->undefined_perms[class_val-1] |= (1 << j); | ||
1519 | print_unknown_handle = 1; | ||
1520 | continue; | ||
1521 | } | ||
1522 | perdatum = hashtab_search(perms->table, def_perm); | ||
1523 | if (perdatum == NULL) { | ||
1524 | printk(KERN_ERR | ||
1525 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1526 | def_perm, pol_class); | ||
1527 | return -EINVAL; | ||
1528 | } | ||
1529 | if (perdatum->value != j + 1) { | ||
1530 | printk(KERN_ERR | ||
1531 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1532 | def_perm, pol_class); | ||
1533 | return -EINVAL; | ||
1534 | } | ||
1535 | } | ||
1536 | } | ||
1537 | if (print_unknown_handle) | ||
1538 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
1539 | (security_get_allow_unknown() ? "allowed" : "denied")); | ||
1540 | return 0; | ||
1541 | } | 1559 | } |
1542 | 1560 | ||
1543 | /* Clone the SID into the new SID table. */ | 1561 | /* Clone the SID into the new SID table. */ |
@@ -1710,8 +1728,10 @@ int security_load_policy(void *data, size_t len) | |||
1710 | { | 1728 | { |
1711 | struct policydb oldpolicydb, newpolicydb; | 1729 | struct policydb oldpolicydb, newpolicydb; |
1712 | struct sidtab oldsidtab, newsidtab; | 1730 | struct sidtab oldsidtab, newsidtab; |
1731 | struct selinux_mapping *oldmap, *map = NULL; | ||
1713 | struct convert_context_args args; | 1732 | struct convert_context_args args; |
1714 | u32 seqno; | 1733 | u32 seqno; |
1734 | u16 map_size; | ||
1715 | int rc = 0; | 1735 | int rc = 0; |
1716 | struct policy_file file = { data, len }, *fp = &file; | 1736 | struct policy_file file = { data, len }, *fp = &file; |
1717 | 1737 | ||
@@ -1721,22 +1741,19 @@ int security_load_policy(void *data, size_t len) | |||
1721 | avtab_cache_destroy(); | 1741 | avtab_cache_destroy(); |
1722 | return -EINVAL; | 1742 | return -EINVAL; |
1723 | } | 1743 | } |
1724 | if (policydb_load_isids(&policydb, &sidtab)) { | 1744 | if (selinux_set_mapping(&policydb, secclass_map, |
1745 | ¤t_mapping, | ||
1746 | ¤t_mapping_size)) { | ||
1725 | policydb_destroy(&policydb); | 1747 | policydb_destroy(&policydb); |
1726 | avtab_cache_destroy(); | 1748 | avtab_cache_destroy(); |
1727 | return -EINVAL; | 1749 | return -EINVAL; |
1728 | } | 1750 | } |
1729 | /* Verify that the kernel defined classes are correct. */ | 1751 | if (policydb_load_isids(&policydb, &sidtab)) { |
1730 | if (validate_classes(&policydb)) { | ||
1731 | printk(KERN_ERR | ||
1732 | "SELinux: the definition of a class is incorrect\n"); | ||
1733 | sidtab_destroy(&sidtab); | ||
1734 | policydb_destroy(&policydb); | 1752 | policydb_destroy(&policydb); |
1735 | avtab_cache_destroy(); | 1753 | avtab_cache_destroy(); |
1736 | return -EINVAL; | 1754 | return -EINVAL; |
1737 | } | 1755 | } |
1738 | security_load_policycaps(); | 1756 | security_load_policycaps(); |
1739 | policydb_loaded_version = policydb.policyvers; | ||
1740 | ss_initialized = 1; | 1757 | ss_initialized = 1; |
1741 | seqno = ++latest_granting; | 1758 | seqno = ++latest_granting; |
1742 | selinux_complete_init(); | 1759 | selinux_complete_init(); |
@@ -1759,13 +1776,9 @@ int security_load_policy(void *data, size_t len) | |||
1759 | return -ENOMEM; | 1776 | return -ENOMEM; |
1760 | } | 1777 | } |
1761 | 1778 | ||
1762 | /* Verify that the kernel defined classes are correct. */ | 1779 | if (selinux_set_mapping(&newpolicydb, secclass_map, |
1763 | if (validate_classes(&newpolicydb)) { | 1780 | &map, &map_size)) |
1764 | printk(KERN_ERR | ||
1765 | "SELinux: the definition of a class is incorrect\n"); | ||
1766 | rc = -EINVAL; | ||
1767 | goto err; | 1781 | goto err; |
1768 | } | ||
1769 | 1782 | ||
1770 | rc = security_preserve_bools(&newpolicydb); | 1783 | rc = security_preserve_bools(&newpolicydb); |
1771 | if (rc) { | 1784 | if (rc) { |
@@ -1799,13 +1812,16 @@ int security_load_policy(void *data, size_t len) | |||
1799 | memcpy(&policydb, &newpolicydb, sizeof policydb); | 1812 | memcpy(&policydb, &newpolicydb, sizeof policydb); |
1800 | sidtab_set(&sidtab, &newsidtab); | 1813 | sidtab_set(&sidtab, &newsidtab); |
1801 | security_load_policycaps(); | 1814 | security_load_policycaps(); |
1815 | oldmap = current_mapping; | ||
1816 | current_mapping = map; | ||
1817 | current_mapping_size = map_size; | ||
1802 | seqno = ++latest_granting; | 1818 | seqno = ++latest_granting; |
1803 | policydb_loaded_version = policydb.policyvers; | ||
1804 | write_unlock_irq(&policy_rwlock); | 1819 | write_unlock_irq(&policy_rwlock); |
1805 | 1820 | ||
1806 | /* Free the old policydb and SID table. */ | 1821 | /* Free the old policydb and SID table. */ |
1807 | policydb_destroy(&oldpolicydb); | 1822 | policydb_destroy(&oldpolicydb); |
1808 | sidtab_destroy(&oldsidtab); | 1823 | sidtab_destroy(&oldsidtab); |
1824 | kfree(oldmap); | ||
1809 | 1825 | ||
1810 | avc_ss_reset(seqno); | 1826 | avc_ss_reset(seqno); |
1811 | selnl_notify_policyload(seqno); | 1827 | selnl_notify_policyload(seqno); |
@@ -1815,6 +1831,7 @@ int security_load_policy(void *data, size_t len) | |||
1815 | return 0; | 1831 | return 0; |
1816 | 1832 | ||
1817 | err: | 1833 | err: |
1834 | kfree(map); | ||
1818 | sidtab_destroy(&newsidtab); | 1835 | sidtab_destroy(&newsidtab); |
1819 | policydb_destroy(&newpolicydb); | 1836 | policydb_destroy(&newpolicydb); |
1820 | return rc; | 1837 | return rc; |
@@ -2091,7 +2108,7 @@ out_unlock: | |||
2091 | } | 2108 | } |
2092 | for (i = 0, j = 0; i < mynel; i++) { | 2109 | for (i = 0, j = 0; i < mynel; i++) { |
2093 | rc = avc_has_perm_noaudit(fromsid, mysids[i], | 2110 | rc = avc_has_perm_noaudit(fromsid, mysids[i], |
2094 | SECCLASS_PROCESS, | 2111 | SECCLASS_PROCESS, /* kernel value */ |
2095 | PROCESS__TRANSITION, AVC_STRICT, | 2112 | PROCESS__TRANSITION, AVC_STRICT, |
2096 | NULL); | 2113 | NULL); |
2097 | if (!rc) | 2114 | if (!rc) |
@@ -2119,10 +2136,11 @@ out: | |||
2119 | */ | 2136 | */ |
2120 | int security_genfs_sid(const char *fstype, | 2137 | int security_genfs_sid(const char *fstype, |
2121 | char *path, | 2138 | char *path, |
2122 | u16 sclass, | 2139 | u16 orig_sclass, |
2123 | u32 *sid) | 2140 | u32 *sid) |
2124 | { | 2141 | { |
2125 | int len; | 2142 | int len; |
2143 | u16 sclass; | ||
2126 | struct genfs *genfs; | 2144 | struct genfs *genfs; |
2127 | struct ocontext *c; | 2145 | struct ocontext *c; |
2128 | int rc = 0, cmp = 0; | 2146 | int rc = 0, cmp = 0; |
@@ -2132,6 +2150,8 @@ int security_genfs_sid(const char *fstype, | |||
2132 | 2150 | ||
2133 | read_lock(&policy_rwlock); | 2151 | read_lock(&policy_rwlock); |
2134 | 2152 | ||
2153 | sclass = unmap_class(orig_sclass); | ||
2154 | |||
2135 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { | 2155 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { |
2136 | cmp = strcmp(fstype, genfs->fstype); | 2156 | cmp = strcmp(fstype, genfs->fstype); |
2137 | if (cmp <= 0) | 2157 | if (cmp <= 0) |