hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/security/selinux/ss/services.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Implementation of the security services.
34 *
....@@ -35,9 +36,6 @@
3536 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
3637 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
3738 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
38
- * This program is free software; you can redistribute it and/or modify
39
- * it under the terms of the GNU General Public License as published by
40
- * the Free Software Foundation, version 2.
4139 */
4240 #include <linux/kernel.h>
4341 #include <linux/slab.h>
....@@ -48,9 +46,6 @@
4846 #include <linux/in.h>
4947 #include <linux/sched.h>
5048 #include <linux/audit.h>
51
-#include <linux/mutex.h>
52
-#include <linux/selinux.h>
53
-#include <linux/flex_array.h>
5449 #include <linux/vmalloc.h>
5550 #include <net/netlabel.h>
5651
....@@ -69,31 +64,32 @@
6964 #include "xfrm.h"
7065 #include "ebitmap.h"
7166 #include "audit.h"
67
+#include "policycap_names.h"
7268
73
-/* Policy capability names */
74
-const char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
75
- "network_peer_controls",
76
- "open_perms",
77
- "extended_socket_class",
78
- "always_check_network",
79
- "cgroup_seclabel",
80
- "nnp_nosuid_transition"
69
+#include <trace/hooks/selinux.h>
70
+
71
+struct convert_context_args {
72
+ struct selinux_state *state;
73
+ struct policydb *oldp;
74
+ struct policydb *newp;
8175 };
8276
83
-static struct selinux_ss selinux_ss;
84
-
85
-void selinux_ss_init(struct selinux_ss **ss)
86
-{
87
- rwlock_init(&selinux_ss.policy_rwlock);
88
- mutex_init(&selinux_ss.status_lock);
89
- *ss = &selinux_ss;
90
-}
77
+struct selinux_policy_convert_data {
78
+ struct convert_context_args args;
79
+ struct sidtab_convert_params sidtab_params;
80
+};
9181
9282 /* Forward declaration. */
9383 static int context_struct_to_string(struct policydb *policydb,
9484 struct context *context,
9585 char **scontext,
9686 u32 *scontext_len);
87
+
88
+static int sidtab_entry_to_string(struct policydb *policydb,
89
+ struct sidtab *sidtab,
90
+ struct sidtab_entry *entry,
91
+ char **scontext,
92
+ u32 *scontext_len);
9793
9894 static void context_struct_compute_av(struct policydb *policydb,
9995 struct context *scontext,
....@@ -247,9 +243,17 @@
247243
248244 int security_mls_enabled(struct selinux_state *state)
249245 {
250
- struct policydb *p = &state->ss->policydb;
246
+ int mls_enabled;
247
+ struct selinux_policy *policy;
251248
252
- return p->mls_enabled;
249
+ if (!selinux_initialized(state))
250
+ return 0;
251
+
252
+ rcu_read_lock();
253
+ policy = rcu_dereference(state->policy);
254
+ mls_enabled = policy->policydb.mls_enabled;
255
+ rcu_read_unlock();
256
+ return mls_enabled;
253257 }
254258
255259 /*
....@@ -481,11 +485,11 @@
481485
482486 /* init permission_names */
483487 if (common_dat &&
484
- hashtab_map(common_dat->permissions.table,
488
+ hashtab_map(&common_dat->permissions.table,
485489 dump_masked_av_helper, permission_names) < 0)
486490 goto out;
487491
488
- if (hashtab_map(tclass_dat->permissions.table,
492
+ if (hashtab_map(&tclass_dat->permissions.table,
489493 dump_masked_av_helper, permission_names) < 0)
490494 goto out;
491495
....@@ -546,15 +550,13 @@
546550 struct type_datum *target;
547551 u32 masked = 0;
548552
549
- source = flex_array_get_ptr(policydb->type_val_to_struct_array,
550
- scontext->type - 1);
553
+ source = policydb->type_val_to_struct[scontext->type - 1];
551554 BUG_ON(!source);
552555
553556 if (!source->bounds)
554557 return;
555558
556
- target = flex_array_get_ptr(policydb->type_val_to_struct_array,
557
- tcontext->type - 1);
559
+ target = policydb->type_val_to_struct[tcontext->type - 1];
558560 BUG_ON(!target);
559561
560562 memset(&lo_avd, 0, sizeof(lo_avd));
....@@ -654,12 +656,8 @@
654656 */
655657 avkey.target_class = tclass;
656658 avkey.specified = AVTAB_AV | AVTAB_XPERMS;
657
- sattr = flex_array_get(policydb->type_attr_map_array,
658
- scontext->type - 1);
659
- BUG_ON(!sattr);
660
- tattr = flex_array_get(policydb->type_attr_map_array,
661
- tcontext->type - 1);
662
- BUG_ON(!tattr);
659
+ sattr = &policydb->type_attr_map_array[scontext->type - 1];
660
+ tattr = &policydb->type_attr_map_array[tcontext->type - 1];
663661 ebitmap_for_each_positive_bit(sattr, snode, i) {
664662 ebitmap_for_each_positive_bit(tattr, tnode, j) {
665663 avkey.source_type = i + 1;
....@@ -726,20 +724,22 @@
726724 }
727725
728726 static int security_validtrans_handle_fail(struct selinux_state *state,
729
- struct context *ocontext,
730
- struct context *ncontext,
731
- struct context *tcontext,
732
- u16 tclass)
727
+ struct selinux_policy *policy,
728
+ struct sidtab_entry *oentry,
729
+ struct sidtab_entry *nentry,
730
+ struct sidtab_entry *tentry,
731
+ u16 tclass)
733732 {
734
- struct policydb *p = &state->ss->policydb;
733
+ struct policydb *p = &policy->policydb;
734
+ struct sidtab *sidtab = policy->sidtab;
735735 char *o = NULL, *n = NULL, *t = NULL;
736736 u32 olen, nlen, tlen;
737737
738
- if (context_struct_to_string(p, ocontext, &o, &olen))
738
+ if (sidtab_entry_to_string(p, sidtab, oentry, &o, &olen))
739739 goto out;
740
- if (context_struct_to_string(p, ncontext, &n, &nlen))
740
+ if (sidtab_entry_to_string(p, sidtab, nentry, &n, &nlen))
741741 goto out;
742
- if (context_struct_to_string(p, tcontext, &t, &tlen))
742
+ if (sidtab_entry_to_string(p, sidtab, tentry, &t, &tlen))
743743 goto out;
744744 audit_log(audit_context(), GFP_ATOMIC, AUDIT_SELINUX_ERR,
745745 "op=security_validate_transition seresult=denied"
....@@ -759,27 +759,29 @@
759759 u32 oldsid, u32 newsid, u32 tasksid,
760760 u16 orig_tclass, bool user)
761761 {
762
+ struct selinux_policy *policy;
762763 struct policydb *policydb;
763764 struct sidtab *sidtab;
764
- struct context *ocontext;
765
- struct context *ncontext;
766
- struct context *tcontext;
765
+ struct sidtab_entry *oentry;
766
+ struct sidtab_entry *nentry;
767
+ struct sidtab_entry *tentry;
767768 struct class_datum *tclass_datum;
768769 struct constraint_node *constraint;
769770 u16 tclass;
770771 int rc = 0;
771772
772773
773
- if (!state->initialized)
774
+ if (!selinux_initialized(state))
774775 return 0;
775776
776
- read_lock(&state->ss->policy_rwlock);
777
+ rcu_read_lock();
777778
778
- policydb = &state->ss->policydb;
779
- sidtab = state->ss->sidtab;
779
+ policy = rcu_dereference(state->policy);
780
+ policydb = &policy->policydb;
781
+ sidtab = policy->sidtab;
780782
781783 if (!user)
782
- tclass = unmap_class(&state->ss->map, orig_tclass);
784
+ tclass = unmap_class(&policy->map, orig_tclass);
783785 else
784786 tclass = orig_tclass;
785787
....@@ -789,24 +791,24 @@
789791 }
790792 tclass_datum = policydb->class_val_to_struct[tclass - 1];
791793
792
- ocontext = sidtab_search(sidtab, oldsid);
793
- if (!ocontext) {
794
+ oentry = sidtab_search_entry(sidtab, oldsid);
795
+ if (!oentry) {
794796 pr_err("SELinux: %s: unrecognized SID %d\n",
795797 __func__, oldsid);
796798 rc = -EINVAL;
797799 goto out;
798800 }
799801
800
- ncontext = sidtab_search(sidtab, newsid);
801
- if (!ncontext) {
802
+ nentry = sidtab_search_entry(sidtab, newsid);
803
+ if (!nentry) {
802804 pr_err("SELinux: %s: unrecognized SID %d\n",
803805 __func__, newsid);
804806 rc = -EINVAL;
805807 goto out;
806808 }
807809
808
- tcontext = sidtab_search(sidtab, tasksid);
809
- if (!tcontext) {
810
+ tentry = sidtab_search_entry(sidtab, tasksid);
811
+ if (!tentry) {
810812 pr_err("SELinux: %s: unrecognized SID %d\n",
811813 __func__, tasksid);
812814 rc = -EINVAL;
....@@ -815,23 +817,25 @@
815817
816818 constraint = tclass_datum->validatetrans;
817819 while (constraint) {
818
- if (!constraint_expr_eval(policydb, ocontext, ncontext,
819
- tcontext, constraint->expr)) {
820
+ if (!constraint_expr_eval(policydb, &oentry->context,
821
+ &nentry->context, &tentry->context,
822
+ constraint->expr)) {
820823 if (user)
821824 rc = -EPERM;
822825 else
823826 rc = security_validtrans_handle_fail(state,
824
- ocontext,
825
- ncontext,
826
- tcontext,
827
- tclass);
827
+ policy,
828
+ oentry,
829
+ nentry,
830
+ tentry,
831
+ tclass);
828832 goto out;
829833 }
830834 constraint = constraint->next;
831835 }
832836
833837 out:
834
- read_unlock(&state->ss->policy_rwlock);
838
+ rcu_read_unlock();
835839 return rc;
836840 }
837841
....@@ -863,32 +867,33 @@
863867 int security_bounded_transition(struct selinux_state *state,
864868 u32 old_sid, u32 new_sid)
865869 {
870
+ struct selinux_policy *policy;
866871 struct policydb *policydb;
867872 struct sidtab *sidtab;
868
- struct context *old_context, *new_context;
873
+ struct sidtab_entry *old_entry, *new_entry;
869874 struct type_datum *type;
870875 int index;
871876 int rc;
872877
873
- if (!state->initialized)
878
+ if (!selinux_initialized(state))
874879 return 0;
875880
876
- read_lock(&state->ss->policy_rwlock);
877
-
878
- policydb = &state->ss->policydb;
879
- sidtab = state->ss->sidtab;
881
+ rcu_read_lock();
882
+ policy = rcu_dereference(state->policy);
883
+ policydb = &policy->policydb;
884
+ sidtab = policy->sidtab;
880885
881886 rc = -EINVAL;
882
- old_context = sidtab_search(sidtab, old_sid);
883
- if (!old_context) {
887
+ old_entry = sidtab_search_entry(sidtab, old_sid);
888
+ if (!old_entry) {
884889 pr_err("SELinux: %s: unrecognized SID %u\n",
885890 __func__, old_sid);
886891 goto out;
887892 }
888893
889894 rc = -EINVAL;
890
- new_context = sidtab_search(sidtab, new_sid);
891
- if (!new_context) {
895
+ new_entry = sidtab_search_entry(sidtab, new_sid);
896
+ if (!new_entry) {
892897 pr_err("SELinux: %s: unrecognized SID %u\n",
893898 __func__, new_sid);
894899 goto out;
....@@ -896,13 +901,12 @@
896901
897902 rc = 0;
898903 /* type/domain unchanged */
899
- if (old_context->type == new_context->type)
904
+ if (old_entry->context.type == new_entry->context.type)
900905 goto out;
901906
902
- index = new_context->type;
907
+ index = new_entry->context.type;
903908 while (true) {
904
- type = flex_array_get_ptr(policydb->type_val_to_struct_array,
905
- index - 1);
909
+ type = policydb->type_val_to_struct[index - 1];
906910 BUG_ON(!type);
907911
908912 /* not bounded anymore */
....@@ -912,7 +916,7 @@
912916
913917 /* @newsid is bounded by @oldsid */
914918 rc = 0;
915
- if (type->bounds == old_context->type)
919
+ if (type->bounds == old_entry->context.type)
916920 break;
917921
918922 index = type->bounds;
....@@ -923,10 +927,10 @@
923927 char *new_name = NULL;
924928 u32 length;
925929
926
- if (!context_struct_to_string(policydb, old_context,
927
- &old_name, &length) &&
928
- !context_struct_to_string(policydb, new_context,
929
- &new_name, &length)) {
930
+ if (!sidtab_entry_to_string(policydb, sidtab, old_entry,
931
+ &old_name, &length) &&
932
+ !sidtab_entry_to_string(policydb, sidtab, new_entry,
933
+ &new_name, &length)) {
930934 audit_log(audit_context(),
931935 GFP_ATOMIC, AUDIT_SELINUX_ERR,
932936 "op=security_bounded_transition "
....@@ -938,17 +942,20 @@
938942 kfree(old_name);
939943 }
940944 out:
941
- read_unlock(&state->ss->policy_rwlock);
945
+ rcu_read_unlock();
942946
943947 return rc;
944948 }
945949
946
-static void avd_init(struct selinux_state *state, struct av_decision *avd)
950
+static void avd_init(struct selinux_policy *policy, struct av_decision *avd)
947951 {
948952 avd->allowed = 0;
949953 avd->auditallow = 0;
950954 avd->auditdeny = 0xffffffff;
951
- avd->seqno = state->ss->latest_granting;
955
+ if (policy)
956
+ avd->seqno = policy->latest_granting;
957
+ else
958
+ avd->seqno = 0;
952959 avd->flags = 0;
953960 }
954961
....@@ -1013,6 +1020,7 @@
10131020 u8 driver,
10141021 struct extended_perms_decision *xpermd)
10151022 {
1023
+ struct selinux_policy *policy;
10161024 struct policydb *policydb;
10171025 struct sidtab *sidtab;
10181026 u16 tclass;
....@@ -1029,12 +1037,13 @@
10291037 memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p));
10301038 memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
10311039
1032
- read_lock(&state->ss->policy_rwlock);
1033
- if (!state->initialized)
1040
+ rcu_read_lock();
1041
+ if (!selinux_initialized(state))
10341042 goto allow;
10351043
1036
- policydb = &state->ss->policydb;
1037
- sidtab = state->ss->sidtab;
1044
+ policy = rcu_dereference(state->policy);
1045
+ policydb = &policy->policydb;
1046
+ sidtab = policy->sidtab;
10381047
10391048 scontext = sidtab_search(sidtab, ssid);
10401049 if (!scontext) {
....@@ -1050,7 +1059,7 @@
10501059 goto out;
10511060 }
10521061
1053
- tclass = unmap_class(&state->ss->map, orig_tclass);
1062
+ tclass = unmap_class(&policy->map, orig_tclass);
10541063 if (unlikely(orig_tclass && !tclass)) {
10551064 if (policydb->allow_unknown)
10561065 goto allow;
....@@ -1065,12 +1074,8 @@
10651074
10661075 avkey.target_class = tclass;
10671076 avkey.specified = AVTAB_XPERMS;
1068
- sattr = flex_array_get(policydb->type_attr_map_array,
1069
- scontext->type - 1);
1070
- BUG_ON(!sattr);
1071
- tattr = flex_array_get(policydb->type_attr_map_array,
1072
- tcontext->type - 1);
1073
- BUG_ON(!tattr);
1077
+ sattr = &policydb->type_attr_map_array[scontext->type - 1];
1078
+ tattr = &policydb->type_attr_map_array[tcontext->type - 1];
10741079 ebitmap_for_each_positive_bit(sattr, snode, i) {
10751080 ebitmap_for_each_positive_bit(tattr, tnode, j) {
10761081 avkey.source_type = i + 1;
....@@ -1086,7 +1091,7 @@
10861091 }
10871092 }
10881093 out:
1089
- read_unlock(&state->ss->policy_rwlock);
1094
+ rcu_read_unlock();
10901095 return;
10911096 allow:
10921097 memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p));
....@@ -1111,19 +1116,21 @@
11111116 struct av_decision *avd,
11121117 struct extended_perms *xperms)
11131118 {
1119
+ struct selinux_policy *policy;
11141120 struct policydb *policydb;
11151121 struct sidtab *sidtab;
11161122 u16 tclass;
11171123 struct context *scontext = NULL, *tcontext = NULL;
11181124
1119
- read_lock(&state->ss->policy_rwlock);
1120
- avd_init(state, avd);
1125
+ rcu_read_lock();
1126
+ policy = rcu_dereference(state->policy);
1127
+ avd_init(policy, avd);
11211128 xperms->len = 0;
1122
- if (!state->initialized)
1129
+ if (!selinux_initialized(state))
11231130 goto allow;
11241131
1125
- policydb = &state->ss->policydb;
1126
- sidtab = state->ss->sidtab;
1132
+ policydb = &policy->policydb;
1133
+ sidtab = policy->sidtab;
11271134
11281135 scontext = sidtab_search(sidtab, ssid);
11291136 if (!scontext) {
....@@ -1143,7 +1150,7 @@
11431150 goto out;
11441151 }
11451152
1146
- tclass = unmap_class(&state->ss->map, orig_tclass);
1153
+ tclass = unmap_class(&policy->map, orig_tclass);
11471154 if (unlikely(orig_tclass && !tclass)) {
11481155 if (policydb->allow_unknown)
11491156 goto allow;
....@@ -1151,10 +1158,10 @@
11511158 }
11521159 context_struct_compute_av(policydb, scontext, tcontext, tclass, avd,
11531160 xperms);
1154
- map_decision(&state->ss->map, orig_tclass, avd,
1161
+ map_decision(&policy->map, orig_tclass, avd,
11551162 policydb->allow_unknown);
11561163 out:
1157
- read_unlock(&state->ss->policy_rwlock);
1164
+ rcu_read_unlock();
11581165 return;
11591166 allow:
11601167 avd->allowed = 0xffffffff;
....@@ -1167,17 +1174,19 @@
11671174 u16 tclass,
11681175 struct av_decision *avd)
11691176 {
1177
+ struct selinux_policy *policy;
11701178 struct policydb *policydb;
11711179 struct sidtab *sidtab;
11721180 struct context *scontext = NULL, *tcontext = NULL;
11731181
1174
- read_lock(&state->ss->policy_rwlock);
1175
- avd_init(state, avd);
1176
- if (!state->initialized)
1182
+ rcu_read_lock();
1183
+ policy = rcu_dereference(state->policy);
1184
+ avd_init(policy, avd);
1185
+ if (!selinux_initialized(state))
11771186 goto allow;
11781187
1179
- policydb = &state->ss->policydb;
1180
- sidtab = state->ss->sidtab;
1188
+ policydb = &policy->policydb;
1189
+ sidtab = policy->sidtab;
11811190
11821191 scontext = sidtab_search(sidtab, ssid);
11831192 if (!scontext) {
....@@ -1206,7 +1215,7 @@
12061215 context_struct_compute_av(policydb, scontext, tcontext, tclass, avd,
12071216 NULL);
12081217 out:
1209
- read_unlock(&state->ss->policy_rwlock);
1218
+ rcu_read_unlock();
12101219 return;
12111220 allow:
12121221 avd->allowed = 0xffffffff;
....@@ -1270,21 +1279,40 @@
12701279 return 0;
12711280 }
12721281
1282
+static int sidtab_entry_to_string(struct policydb *p,
1283
+ struct sidtab *sidtab,
1284
+ struct sidtab_entry *entry,
1285
+ char **scontext, u32 *scontext_len)
1286
+{
1287
+ int rc = sidtab_sid2str_get(sidtab, entry, scontext, scontext_len);
1288
+
1289
+ if (rc != -ENOENT)
1290
+ return rc;
1291
+
1292
+ rc = context_struct_to_string(p, &entry->context, scontext,
1293
+ scontext_len);
1294
+ if (!rc && scontext)
1295
+ sidtab_sid2str_put(sidtab, entry, *scontext, *scontext_len);
1296
+ return rc;
1297
+}
1298
+
12731299 #include "initial_sid_to_string.h"
12741300
12751301 int security_sidtab_hash_stats(struct selinux_state *state, char *page)
12761302 {
1303
+ struct selinux_policy *policy;
12771304 int rc;
12781305
1279
- if (!state->initialized) {
1306
+ if (!selinux_initialized(state)) {
12801307 pr_err("SELinux: %s: called before initial load_policy\n",
12811308 __func__);
12821309 return -EINVAL;
12831310 }
12841311
1285
- read_lock(&state->ss->policy_rwlock);
1286
- rc = sidtab_hash_stats(state->ss->sidtab, page);
1287
- read_unlock(&state->ss->policy_rwlock);
1312
+ rcu_read_lock();
1313
+ policy = rcu_dereference(state->policy);
1314
+ rc = sidtab_hash_stats(policy->sidtab, page);
1315
+ rcu_read_unlock();
12881316
12891317 return rc;
12901318 }
....@@ -1298,56 +1326,62 @@
12981326
12991327 static int security_sid_to_context_core(struct selinux_state *state,
13001328 u32 sid, char **scontext,
1301
- u32 *scontext_len, int force)
1329
+ u32 *scontext_len, int force,
1330
+ int only_invalid)
13021331 {
1332
+ struct selinux_policy *policy;
13031333 struct policydb *policydb;
13041334 struct sidtab *sidtab;
1305
- struct context *context;
1335
+ struct sidtab_entry *entry;
13061336 int rc = 0;
13071337
13081338 if (scontext)
13091339 *scontext = NULL;
13101340 *scontext_len = 0;
13111341
1312
- if (!state->initialized) {
1342
+ if (!selinux_initialized(state)) {
13131343 if (sid <= SECINITSID_NUM) {
13141344 char *scontextp;
1345
+ const char *s = initial_sid_to_string[sid];
13151346
1316
- *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
1347
+ if (!s)
1348
+ return -EINVAL;
1349
+ *scontext_len = strlen(s) + 1;
13171350 if (!scontext)
1318
- goto out;
1319
- scontextp = kmemdup(initial_sid_to_string[sid],
1320
- *scontext_len, GFP_ATOMIC);
1321
- if (!scontextp) {
1322
- rc = -ENOMEM;
1323
- goto out;
1324
- }
1351
+ return 0;
1352
+ scontextp = kmemdup(s, *scontext_len, GFP_ATOMIC);
1353
+ if (!scontextp)
1354
+ return -ENOMEM;
13251355 *scontext = scontextp;
1326
- goto out;
1356
+ return 0;
13271357 }
13281358 pr_err("SELinux: %s: called before initial "
13291359 "load_policy on unknown SID %d\n", __func__, sid);
1330
- rc = -EINVAL;
1331
- goto out;
1360
+ return -EINVAL;
13321361 }
1333
- read_lock(&state->ss->policy_rwlock);
1334
- policydb = &state->ss->policydb;
1335
- sidtab = state->ss->sidtab;
1362
+ rcu_read_lock();
1363
+ policy = rcu_dereference(state->policy);
1364
+ policydb = &policy->policydb;
1365
+ sidtab = policy->sidtab;
1366
+
13361367 if (force)
1337
- context = sidtab_search_force(sidtab, sid);
1368
+ entry = sidtab_search_entry_force(sidtab, sid);
13381369 else
1339
- context = sidtab_search(sidtab, sid);
1340
- if (!context) {
1370
+ entry = sidtab_search_entry(sidtab, sid);
1371
+ if (!entry) {
13411372 pr_err("SELinux: %s: unrecognized SID %d\n",
13421373 __func__, sid);
13431374 rc = -EINVAL;
13441375 goto out_unlock;
13451376 }
1346
- rc = context_struct_to_string(policydb, context, scontext,
1347
- scontext_len);
1377
+ if (only_invalid && !entry->context.len)
1378
+ goto out_unlock;
1379
+
1380
+ rc = sidtab_entry_to_string(policydb, sidtab, entry, scontext,
1381
+ scontext_len);
1382
+
13481383 out_unlock:
1349
- read_unlock(&state->ss->policy_rwlock);
1350
-out:
1384
+ rcu_read_unlock();
13511385 return rc;
13521386
13531387 }
....@@ -1366,14 +1400,34 @@
13661400 u32 sid, char **scontext, u32 *scontext_len)
13671401 {
13681402 return security_sid_to_context_core(state, sid, scontext,
1369
- scontext_len, 0);
1403
+ scontext_len, 0, 0);
13701404 }
13711405
13721406 int security_sid_to_context_force(struct selinux_state *state, u32 sid,
13731407 char **scontext, u32 *scontext_len)
13741408 {
13751409 return security_sid_to_context_core(state, sid, scontext,
1376
- scontext_len, 1);
1410
+ scontext_len, 1, 0);
1411
+}
1412
+
1413
+/**
1414
+ * security_sid_to_context_inval - Obtain a context for a given SID if it
1415
+ * is invalid.
1416
+ * @sid: security identifier, SID
1417
+ * @scontext: security context
1418
+ * @scontext_len: length in bytes
1419
+ *
1420
+ * Write the string representation of the context associated with @sid
1421
+ * into a dynamically allocated string of the correct size, but only if the
1422
+ * context is invalid in the current policy. Set @scontext to point to
1423
+ * this string (or NULL if the context is valid) and set @scontext_len to
1424
+ * the length of the string (or 0 if the context is valid).
1425
+ */
1426
+int security_sid_to_context_inval(struct selinux_state *state, u32 sid,
1427
+ char **scontext, u32 *scontext_len)
1428
+{
1429
+ return security_sid_to_context_core(state, sid, scontext,
1430
+ scontext_len, 1, 1);
13771431 }
13781432
13791433 /*
....@@ -1408,7 +1462,7 @@
14081462
14091463 *p++ = 0;
14101464
1411
- usrdatum = hashtab_search(pol->p_users.table, scontextp);
1465
+ usrdatum = symtab_search(&pol->p_users, scontextp);
14121466 if (!usrdatum)
14131467 goto out;
14141468
....@@ -1424,7 +1478,7 @@
14241478
14251479 *p++ = 0;
14261480
1427
- role = hashtab_search(pol->p_roles.table, scontextp);
1481
+ role = symtab_search(&pol->p_roles, scontextp);
14281482 if (!role)
14291483 goto out;
14301484 ctx->role = role->value;
....@@ -1436,7 +1490,7 @@
14361490 oldc = *p;
14371491 *p++ = 0;
14381492
1439
- typdatum = hashtab_search(pol->p_types.table, scontextp);
1493
+ typdatum = symtab_search(&pol->p_types, scontextp);
14401494 if (!typdatum || typdatum->attribute)
14411495 goto out;
14421496
....@@ -1457,47 +1511,12 @@
14571511 return rc;
14581512 }
14591513
1460
-int context_add_hash(struct policydb *policydb,
1461
- struct context *context)
1462
-{
1463
- int rc;
1464
- char *str;
1465
- int len;
1466
-
1467
- if (context->str) {
1468
- context->hash = context_compute_hash(context->str);
1469
- } else {
1470
- rc = context_struct_to_string(policydb, context,
1471
- &str, &len);
1472
- if (rc)
1473
- return rc;
1474
- context->hash = context_compute_hash(str);
1475
- kfree(str);
1476
- }
1477
- return 0;
1478
-}
1479
-
1480
-static int context_struct_to_sid(struct selinux_state *state,
1481
- struct context *context, u32 *sid)
1482
-{
1483
- int rc;
1484
- struct sidtab *sidtab = state->ss->sidtab;
1485
- struct policydb *policydb = &state->ss->policydb;
1486
-
1487
- if (!context->hash) {
1488
- rc = context_add_hash(policydb, context);
1489
- if (rc)
1490
- return rc;
1491
- }
1492
-
1493
- return sidtab_context_to_sid(sidtab, context, sid);
1494
-}
1495
-
14961514 static int security_context_to_sid_core(struct selinux_state *state,
14971515 const char *scontext, u32 scontext_len,
14981516 u32 *sid, u32 def_sid, gfp_t gfp_flags,
14991517 int force)
15001518 {
1519
+ struct selinux_policy *policy;
15011520 struct policydb *policydb;
15021521 struct sidtab *sidtab;
15031522 char *scontext2, *str = NULL;
....@@ -1513,11 +1532,13 @@
15131532 if (!scontext2)
15141533 return -ENOMEM;
15151534
1516
- if (!state->initialized) {
1535
+ if (!selinux_initialized(state)) {
15171536 int i;
15181537
15191538 for (i = 1; i < SECINITSID_NUM; i++) {
1520
- if (!strcmp(initial_sid_to_string[i], scontext2)) {
1539
+ const char *s = initial_sid_to_string[i];
1540
+
1541
+ if (s && !strcmp(s, scontext2)) {
15211542 *sid = i;
15221543 goto out;
15231544 }
....@@ -1534,9 +1555,11 @@
15341555 if (!str)
15351556 goto out;
15361557 }
1537
- read_lock(&state->ss->policy_rwlock);
1538
- policydb = &state->ss->policydb;
1539
- sidtab = state->ss->sidtab;
1558
+retry:
1559
+ rcu_read_lock();
1560
+ policy = rcu_dereference(state->policy);
1561
+ policydb = &policy->policydb;
1562
+ sidtab = policy->sidtab;
15401563 rc = string_to_context_struct(policydb, sidtab, scontext2,
15411564 &context, def_sid);
15421565 if (rc == -EINVAL && force) {
....@@ -1545,10 +1568,19 @@
15451568 str = NULL;
15461569 } else if (rc)
15471570 goto out_unlock;
1548
- rc = context_struct_to_sid(state, &context, sid);
1571
+ rc = sidtab_context_to_sid(sidtab, &context, sid);
1572
+ if (rc == -ESTALE) {
1573
+ rcu_read_unlock();
1574
+ if (context.str) {
1575
+ str = context.str;
1576
+ context.str = NULL;
1577
+ }
1578
+ context_destroy(&context);
1579
+ goto retry;
1580
+ }
15491581 context_destroy(&context);
15501582 out_unlock:
1551
- read_unlock(&state->ss->policy_rwlock);
1583
+ rcu_read_unlock();
15521584 out:
15531585 kfree(scontext2);
15541586 kfree(str);
....@@ -1618,27 +1650,32 @@
16181650
16191651 static int compute_sid_handle_invalid_context(
16201652 struct selinux_state *state,
1621
- struct context *scontext,
1622
- struct context *tcontext,
1653
+ struct selinux_policy *policy,
1654
+ struct sidtab_entry *sentry,
1655
+ struct sidtab_entry *tentry,
16231656 u16 tclass,
16241657 struct context *newcontext)
16251658 {
1626
- struct policydb *policydb = &state->ss->policydb;
1659
+ struct policydb *policydb = &policy->policydb;
1660
+ struct sidtab *sidtab = policy->sidtab;
16271661 char *s = NULL, *t = NULL, *n = NULL;
16281662 u32 slen, tlen, nlen;
1663
+ struct audit_buffer *ab;
16291664
1630
- if (context_struct_to_string(policydb, scontext, &s, &slen))
1665
+ if (sidtab_entry_to_string(policydb, sidtab, sentry, &s, &slen))
16311666 goto out;
1632
- if (context_struct_to_string(policydb, tcontext, &t, &tlen))
1667
+ if (sidtab_entry_to_string(policydb, sidtab, tentry, &t, &tlen))
16331668 goto out;
16341669 if (context_struct_to_string(policydb, newcontext, &n, &nlen))
16351670 goto out;
1636
- audit_log(audit_context(), GFP_ATOMIC, AUDIT_SELINUX_ERR,
1637
- "op=security_compute_sid invalid_context=%s"
1638
- " scontext=%s"
1639
- " tcontext=%s"
1640
- " tclass=%s",
1641
- n, s, t, sym_name(policydb, SYM_CLASSES, tclass-1));
1671
+ ab = audit_log_start(audit_context(), GFP_ATOMIC, AUDIT_SELINUX_ERR);
1672
+ audit_log_format(ab,
1673
+ "op=security_compute_sid invalid_context=");
1674
+ /* no need to record the NUL with untrusted strings */
1675
+ audit_log_n_untrustedstring(ab, n, nlen - 1);
1676
+ audit_log_format(ab, " scontext=%s tcontext=%s tclass=%s",
1677
+ s, t, sym_name(policydb, SYM_CLASSES, tclass-1));
1678
+ audit_log_end(ab);
16421679 out:
16431680 kfree(s);
16441681 kfree(t);
....@@ -1653,8 +1690,8 @@
16531690 u32 stype, u32 ttype, u16 tclass,
16541691 const char *objname)
16551692 {
1656
- struct filename_trans ft;
1657
- struct filename_trans_datum *otype;
1693
+ struct filename_trans_key ft;
1694
+ struct filename_trans_datum *datum;
16581695
16591696 /*
16601697 * Most filename trans rules are going to live in specific directories
....@@ -1664,14 +1701,18 @@
16641701 if (!ebitmap_get_bit(&policydb->filename_trans_ttypes, ttype))
16651702 return;
16661703
1667
- ft.stype = stype;
16681704 ft.ttype = ttype;
16691705 ft.tclass = tclass;
16701706 ft.name = objname;
16711707
1672
- otype = hashtab_search(policydb->filename_trans, &ft);
1673
- if (otype)
1674
- newcontext->type = otype->otype;
1708
+ datum = policydb_filenametr_search(policydb, &ft);
1709
+ while (datum) {
1710
+ if (ebitmap_get_bit(&datum->stypes, stype - 1)) {
1711
+ newcontext->type = datum->otype;
1712
+ return;
1713
+ }
1714
+ datum = datum->next;
1715
+ }
16751716 }
16761717
16771718 static int security_compute_sid(struct selinux_state *state,
....@@ -1683,11 +1724,12 @@
16831724 u32 *out_sid,
16841725 bool kern)
16851726 {
1727
+ struct selinux_policy *policy;
16861728 struct policydb *policydb;
16871729 struct sidtab *sidtab;
1688
- struct class_datum *cladatum = NULL;
1689
- struct context *scontext = NULL, *tcontext = NULL, newcontext;
1690
- struct role_trans *roletr = NULL;
1730
+ struct class_datum *cladatum;
1731
+ struct context *scontext, *tcontext, newcontext;
1732
+ struct sidtab_entry *sentry, *tentry;
16911733 struct avtab_key avkey;
16921734 struct avtab_datum *avdatum;
16931735 struct avtab_node *node;
....@@ -1695,7 +1737,7 @@
16951737 int rc = 0;
16961738 bool sock;
16971739
1698
- if (!state->initialized) {
1740
+ if (!selinux_initialized(state)) {
16991741 switch (orig_tclass) {
17001742 case SECCLASS_PROCESS: /* kernel value */
17011743 *out_sid = ssid;
....@@ -1707,36 +1749,43 @@
17071749 goto out;
17081750 }
17091751
1752
+retry:
1753
+ cladatum = NULL;
17101754 context_init(&newcontext);
17111755
1712
- read_lock(&state->ss->policy_rwlock);
1756
+ rcu_read_lock();
1757
+
1758
+ policy = rcu_dereference(state->policy);
17131759
17141760 if (kern) {
1715
- tclass = unmap_class(&state->ss->map, orig_tclass);
1761
+ tclass = unmap_class(&policy->map, orig_tclass);
17161762 sock = security_is_socket_class(orig_tclass);
17171763 } else {
17181764 tclass = orig_tclass;
1719
- sock = security_is_socket_class(map_class(&state->ss->map,
1765
+ sock = security_is_socket_class(map_class(&policy->map,
17201766 tclass));
17211767 }
17221768
1723
- policydb = &state->ss->policydb;
1724
- sidtab = state->ss->sidtab;
1769
+ policydb = &policy->policydb;
1770
+ sidtab = policy->sidtab;
17251771
1726
- scontext = sidtab_search(sidtab, ssid);
1727
- if (!scontext) {
1772
+ sentry = sidtab_search_entry(sidtab, ssid);
1773
+ if (!sentry) {
17281774 pr_err("SELinux: %s: unrecognized SID %d\n",
17291775 __func__, ssid);
17301776 rc = -EINVAL;
17311777 goto out_unlock;
17321778 }
1733
- tcontext = sidtab_search(sidtab, tsid);
1734
- if (!tcontext) {
1779
+ tentry = sidtab_search_entry(sidtab, tsid);
1780
+ if (!tentry) {
17351781 pr_err("SELinux: %s: unrecognized SID %d\n",
17361782 __func__, tsid);
17371783 rc = -EINVAL;
17381784 goto out_unlock;
17391785 }
1786
+
1787
+ scontext = &sentry->context;
1788
+ tcontext = &tentry->context;
17401789
17411790 if (tclass && tclass <= policydb->p_classes.nprim)
17421791 cladatum = policydb->class_val_to_struct[tclass - 1];
....@@ -1765,7 +1814,7 @@
17651814 } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
17661815 newcontext.role = tcontext->role;
17671816 } else {
1768
- if ((tclass == policydb->process_class) || (sock == true))
1817
+ if ((tclass == policydb->process_class) || sock)
17691818 newcontext.role = scontext->role;
17701819 else
17711820 newcontext.role = OBJECT_R_VAL;
....@@ -1777,7 +1826,7 @@
17771826 } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
17781827 newcontext.type = tcontext->type;
17791828 } else {
1780
- if ((tclass == policydb->process_class) || (sock == true)) {
1829
+ if ((tclass == policydb->process_class) || sock) {
17811830 /* Use the type of process. */
17821831 newcontext.type = scontext->type;
17831832 } else {
....@@ -1817,16 +1866,16 @@
18171866 /* Check for class-specific changes. */
18181867 if (specified & AVTAB_TRANSITION) {
18191868 /* Look for a role transition rule. */
1820
- for (roletr = policydb->role_tr; roletr;
1821
- roletr = roletr->next) {
1822
- if ((roletr->role == scontext->role) &&
1823
- (roletr->type == tcontext->type) &&
1824
- (roletr->tclass == tclass)) {
1825
- /* Use the role transition rule. */
1826
- newcontext.role = roletr->new_role;
1827
- break;
1828
- }
1829
- }
1869
+ struct role_trans_datum *rtd;
1870
+ struct role_trans_key rtk = {
1871
+ .role = scontext->role,
1872
+ .type = tcontext->type,
1873
+ .tclass = tclass,
1874
+ };
1875
+
1876
+ rtd = policydb_roletr_search(policydb, &rtk);
1877
+ if (rtd)
1878
+ newcontext.role = rtd->new_role;
18301879 }
18311880
18321881 /* Set the MLS attributes.
....@@ -1838,17 +1887,21 @@
18381887
18391888 /* Check the validity of the context. */
18401889 if (!policydb_context_isvalid(policydb, &newcontext)) {
1841
- rc = compute_sid_handle_invalid_context(state, scontext,
1842
- tcontext,
1843
- tclass,
1890
+ rc = compute_sid_handle_invalid_context(state, policy, sentry,
1891
+ tentry, tclass,
18441892 &newcontext);
18451893 if (rc)
18461894 goto out_unlock;
18471895 }
18481896 /* Obtain the sid for the context. */
1849
- rc = context_struct_to_sid(state, &newcontext, out_sid);
1897
+ rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
1898
+ if (rc == -ESTALE) {
1899
+ rcu_read_unlock();
1900
+ context_destroy(&newcontext);
1901
+ goto retry;
1902
+ }
18501903 out_unlock:
1851
- read_unlock(&state->ss->policy_rwlock);
1904
+ rcu_read_unlock();
18521905 context_destroy(&newcontext);
18531906 out:
18541907 return rc;
....@@ -1935,9 +1988,9 @@
19351988
19361989 static inline int convert_context_handle_invalid_context(
19371990 struct selinux_state *state,
1991
+ struct policydb *policydb,
19381992 struct context *context)
19391993 {
1940
- struct policydb *policydb = &state->ss->policydb;
19411994 char *s;
19421995 u32 len;
19431996
....@@ -1952,12 +2005,6 @@
19522005 return 0;
19532006 }
19542007
1955
-struct convert_context_args {
1956
- struct selinux_state *state;
1957
- struct policydb *oldp;
1958
- struct policydb *newp;
1959
-};
1960
-
19612008 /*
19622009 * Convert the values in the security context
19632010 * structure `oldc' from the values specified
....@@ -1966,7 +2013,8 @@
19662013 * in `newc'. Verify that the context is valid
19672014 * under the new policy.
19682015 */
1969
-static int convert_context(struct context *oldc, struct context *newc, void *p)
2016
+static int convert_context(struct context *oldc, struct context *newc, void *p,
2017
+ gfp_t gfp_flags)
19702018 {
19712019 struct convert_context_args *args;
19722020 struct ocontext *oc;
....@@ -1980,7 +2028,7 @@
19802028 args = p;
19812029
19822030 if (oldc->str) {
1983
- s = kstrdup(oldc->str, GFP_KERNEL);
2031
+ s = kstrdup(oldc->str, gfp_flags);
19842032 if (!s)
19852033 return -ENOMEM;
19862034
....@@ -1998,7 +2046,6 @@
19982046 context_init(newc);
19992047 newc->str = s;
20002048 newc->len = oldc->len;
2001
- newc->hash = oldc->hash;
20022049 return 0;
20032050 }
20042051 kfree(s);
....@@ -2017,26 +2064,26 @@
20172064
20182065 /* Convert the user. */
20192066 rc = -EINVAL;
2020
- usrdatum = hashtab_search(args->newp->p_users.table,
2021
- sym_name(args->oldp,
2022
- SYM_USERS, oldc->user - 1));
2067
+ usrdatum = symtab_search(&args->newp->p_users,
2068
+ sym_name(args->oldp,
2069
+ SYM_USERS, oldc->user - 1));
20232070 if (!usrdatum)
20242071 goto bad;
20252072 newc->user = usrdatum->value;
20262073
20272074 /* Convert the role. */
20282075 rc = -EINVAL;
2029
- role = hashtab_search(args->newp->p_roles.table,
2030
- sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
2076
+ role = symtab_search(&args->newp->p_roles,
2077
+ sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
20312078 if (!role)
20322079 goto bad;
20332080 newc->role = role->value;
20342081
20352082 /* Convert the type. */
20362083 rc = -EINVAL;
2037
- typdatum = hashtab_search(args->newp->p_types.table,
2038
- sym_name(args->oldp,
2039
- SYM_TYPES, oldc->type - 1));
2084
+ typdatum = symtab_search(&args->newp->p_types,
2085
+ sym_name(args->oldp,
2086
+ SYM_TYPES, oldc->type - 1));
20402087 if (!typdatum)
20412088 goto bad;
20422089 newc->type = typdatum->value;
....@@ -2070,14 +2117,12 @@
20702117
20712118 /* Check the validity of the new context. */
20722119 if (!policydb_context_isvalid(args->newp, newc)) {
2073
- rc = convert_context_handle_invalid_context(args->state, oldc);
2120
+ rc = convert_context_handle_invalid_context(args->state,
2121
+ args->oldp,
2122
+ oldc);
20742123 if (rc)
20752124 goto bad;
20762125 }
2077
-
2078
- rc = context_add_hash(args->newp, newc);
2079
- if (rc)
2080
- goto bad;
20812126
20822127 return 0;
20832128 bad:
....@@ -2088,20 +2133,23 @@
20882133 context_destroy(newc);
20892134 newc->str = s;
20902135 newc->len = len;
2091
- newc->hash = context_compute_hash(s);
20922136 pr_info("SELinux: Context %s became invalid (unmapped).\n",
20932137 newc->str);
20942138 return 0;
20952139 }
20962140
2097
-static void security_load_policycaps(struct selinux_state *state)
2141
+static void security_load_policycaps(struct selinux_state *state,
2142
+ struct selinux_policy *policy)
20982143 {
2099
- struct policydb *p = &state->ss->policydb;
2144
+ struct policydb *p;
21002145 unsigned int i;
21012146 struct ebitmap_node *node;
21022147
2148
+ p = &policy->policydb;
2149
+
21032150 for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
2104
- state->policycap[i] = ebitmap_get_bit(&p->policycaps, i);
2151
+ WRITE_ONCE(state->policycap[i],
2152
+ ebitmap_get_bit(&p->policycaps, i));
21052153
21062154 for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
21072155 pr_info("SELinux: policy capability %s=%d\n",
....@@ -2119,8 +2167,107 @@
21192167 selinux_nlmsg_init();
21202168 }
21212169
2122
-static int security_preserve_bools(struct selinux_state *state,
2123
- struct policydb *newpolicydb);
2170
+static int security_preserve_bools(struct selinux_policy *oldpolicy,
2171
+ struct selinux_policy *newpolicy);
2172
+
2173
+static void selinux_policy_free(struct selinux_policy *policy)
2174
+{
2175
+ if (!policy)
2176
+ return;
2177
+
2178
+ sidtab_destroy(policy->sidtab);
2179
+ kfree(policy->map.mapping);
2180
+ policydb_destroy(&policy->policydb);
2181
+ kfree(policy->sidtab);
2182
+ kfree(policy);
2183
+}
2184
+
2185
+static void selinux_policy_cond_free(struct selinux_policy *policy)
2186
+{
2187
+ cond_policydb_destroy_dup(&policy->policydb);
2188
+ kfree(policy);
2189
+}
2190
+
2191
+void selinux_policy_cancel(struct selinux_state *state,
2192
+ struct selinux_load_state *load_state)
2193
+{
2194
+ struct selinux_policy *oldpolicy;
2195
+
2196
+ oldpolicy = rcu_dereference_protected(state->policy,
2197
+ lockdep_is_held(&state->policy_mutex));
2198
+
2199
+ sidtab_cancel_convert(oldpolicy->sidtab);
2200
+ selinux_policy_free(load_state->policy);
2201
+ kfree(load_state->convert_data);
2202
+}
2203
+
2204
+static void selinux_notify_policy_change(struct selinux_state *state,
2205
+ u32 seqno)
2206
+{
2207
+ /* Flush external caches and notify userspace of policy load */
2208
+ avc_ss_reset(state->avc, seqno);
2209
+ selnl_notify_policyload(seqno);
2210
+ selinux_status_update_policyload(state, seqno);
2211
+ selinux_netlbl_cache_invalidate();
2212
+ selinux_xfrm_notify_policyload();
2213
+}
2214
+
2215
+void selinux_policy_commit(struct selinux_state *state,
2216
+ struct selinux_load_state *load_state)
2217
+{
2218
+ struct selinux_policy *oldpolicy, *newpolicy = load_state->policy;
2219
+ unsigned long flags;
2220
+ u32 seqno;
2221
+
2222
+ oldpolicy = rcu_dereference_protected(state->policy,
2223
+ lockdep_is_held(&state->policy_mutex));
2224
+
2225
+ /* If switching between different policy types, log MLS status */
2226
+ if (oldpolicy) {
2227
+ if (oldpolicy->policydb.mls_enabled && !newpolicy->policydb.mls_enabled)
2228
+ pr_info("SELinux: Disabling MLS support...\n");
2229
+ else if (!oldpolicy->policydb.mls_enabled && newpolicy->policydb.mls_enabled)
2230
+ pr_info("SELinux: Enabling MLS support...\n");
2231
+ }
2232
+
2233
+ /* Set latest granting seqno for new policy. */
2234
+ if (oldpolicy)
2235
+ newpolicy->latest_granting = oldpolicy->latest_granting + 1;
2236
+ else
2237
+ newpolicy->latest_granting = 1;
2238
+ seqno = newpolicy->latest_granting;
2239
+
2240
+ /* Install the new policy. */
2241
+ if (oldpolicy) {
2242
+ sidtab_freeze_begin(oldpolicy->sidtab, &flags);
2243
+ rcu_assign_pointer(state->policy, newpolicy);
2244
+ sidtab_freeze_end(oldpolicy->sidtab, &flags);
2245
+ } else {
2246
+ rcu_assign_pointer(state->policy, newpolicy);
2247
+ }
2248
+
2249
+ /* Load the policycaps from the new policy */
2250
+ security_load_policycaps(state, newpolicy);
2251
+
2252
+ if (!selinux_initialized(state)) {
2253
+ /*
2254
+ * After first policy load, the security server is
2255
+ * marked as initialized and ready to handle requests and
2256
+ * any objects created prior to policy load are then labeled.
2257
+ */
2258
+ selinux_mark_initialized(state);
2259
+ selinux_complete_init();
2260
+ trace_android_vh_selinux_is_initialized(state);
2261
+ }
2262
+
2263
+ /* Free the old policy */
2264
+ synchronize_rcu();
2265
+ selinux_policy_free(oldpolicy);
2266
+ kfree(load_state->convert_data);
2267
+
2268
+ /* Notify others of the policy change */
2269
+ selinux_notify_policy_change(state, seqno);
2270
+}
21242271
21252272 /**
21262273 * security_load_policy - Load a security policy configuration.
....@@ -2132,173 +2279,138 @@
21322279 * This function will flush the access vector cache after
21332280 * loading the new policy.
21342281 */
2135
-int security_load_policy(struct selinux_state *state, void *data, size_t len)
2282
+int security_load_policy(struct selinux_state *state, void *data, size_t len,
2283
+ struct selinux_load_state *load_state)
21362284 {
2137
- struct policydb *policydb;
2138
- struct sidtab *oldsidtab, *newsidtab;
2139
- struct policydb *oldpolicydb, *newpolicydb;
2140
- struct selinux_mapping *oldmapping;
2141
- struct selinux_map newmap;
2142
- struct sidtab_convert_params convert_params;
2143
- struct convert_context_args args;
2144
- u32 seqno;
2285
+ struct selinux_policy *newpolicy, *oldpolicy;
2286
+ struct selinux_policy_convert_data *convert_data;
21452287 int rc = 0;
21462288 struct policy_file file = { data, len }, *fp = &file;
21472289
2148
- oldpolicydb = kcalloc(2, sizeof(*oldpolicydb), GFP_KERNEL);
2149
- if (!oldpolicydb) {
2290
+ newpolicy = kzalloc(sizeof(*newpolicy), GFP_KERNEL);
2291
+ if (!newpolicy)
2292
+ return -ENOMEM;
2293
+
2294
+ newpolicy->sidtab = kzalloc(sizeof(*newpolicy->sidtab), GFP_KERNEL);
2295
+ if (!newpolicy->sidtab) {
21502296 rc = -ENOMEM;
2151
- goto out;
2152
- }
2153
- newpolicydb = oldpolicydb + 1;
2154
-
2155
- policydb = &state->ss->policydb;
2156
-
2157
- newsidtab = kmalloc(sizeof(*newsidtab), GFP_KERNEL);
2158
- if (!newsidtab) {
2159
- rc = -ENOMEM;
2160
- goto out;
2297
+ goto err_policy;
21612298 }
21622299
2163
- if (!state->initialized) {
2164
- rc = policydb_read(policydb, fp);
2165
- if (rc) {
2166
- kfree(newsidtab);
2167
- goto out;
2168
- }
2300
+ rc = policydb_read(&newpolicy->policydb, fp);
2301
+ if (rc)
2302
+ goto err_sidtab;
21692303
2170
- policydb->len = len;
2171
- rc = selinux_set_mapping(policydb, secclass_map,
2172
- &state->ss->map);
2173
- if (rc) {
2174
- kfree(newsidtab);
2175
- policydb_destroy(policydb);
2176
- goto out;
2177
- }
2304
+ newpolicy->policydb.len = len;
2305
+ rc = selinux_set_mapping(&newpolicy->policydb, secclass_map,
2306
+ &newpolicy->map);
2307
+ if (rc)
2308
+ goto err_policydb;
21782309
2179
- rc = policydb_load_isids(policydb, newsidtab);
2180
- if (rc) {
2181
- kfree(newsidtab);
2182
- policydb_destroy(policydb);
2183
- goto out;
2184
- }
2185
-
2186
- state->ss->sidtab = newsidtab;
2187
- security_load_policycaps(state);
2188
- state->initialized = 1;
2189
- seqno = ++state->ss->latest_granting;
2190
- selinux_complete_init();
2191
- avc_ss_reset(state->avc, seqno);
2192
- selnl_notify_policyload(seqno);
2193
- selinux_status_update_policyload(state, seqno);
2194
- selinux_netlbl_cache_invalidate();
2195
- selinux_xfrm_notify_policyload();
2196
- goto out;
2197
- }
2198
-
2199
- rc = policydb_read(newpolicydb, fp);
2200
- if (rc) {
2201
- kfree(newsidtab);
2202
- goto out;
2203
- }
2204
-
2205
- newpolicydb->len = len;
2206
- /* If switching between different policy types, log MLS status */
2207
- if (policydb->mls_enabled && !newpolicydb->mls_enabled)
2208
- pr_info("SELinux: Disabling MLS support...\n");
2209
- else if (!policydb->mls_enabled && newpolicydb->mls_enabled)
2210
- pr_info("SELinux: Enabling MLS support...\n");
2211
-
2212
- rc = policydb_load_isids(newpolicydb, newsidtab);
2310
+ rc = policydb_load_isids(&newpolicy->policydb, newpolicy->sidtab);
22132311 if (rc) {
22142312 pr_err("SELinux: unable to load the initial SIDs\n");
2215
- policydb_destroy(newpolicydb);
2216
- kfree(newsidtab);
2217
- goto out;
2313
+ goto err_mapping;
22182314 }
22192315
2220
- rc = selinux_set_mapping(newpolicydb, secclass_map, &newmap);
2221
- if (rc)
2222
- goto err;
2316
+ if (!selinux_initialized(state)) {
2317
+ /* First policy load, so no need to preserve state from old policy */
2318
+ load_state->policy = newpolicy;
2319
+ load_state->convert_data = NULL;
2320
+ return 0;
2321
+ }
22232322
2224
- rc = security_preserve_bools(state, newpolicydb);
2323
+ oldpolicy = rcu_dereference_protected(state->policy,
2324
+ lockdep_is_held(&state->policy_mutex));
2325
+
2326
+ /* Preserve active boolean values from the old policy */
2327
+ rc = security_preserve_bools(oldpolicy, newpolicy);
22252328 if (rc) {
22262329 pr_err("SELinux: unable to preserve booleans\n");
2227
- goto err;
2330
+ goto err_free_isids;
22282331 }
22292332
2230
- oldsidtab = state->ss->sidtab;
2333
+ convert_data = kmalloc(sizeof(*convert_data), GFP_KERNEL);
2334
+ if (!convert_data) {
2335
+ rc = -ENOMEM;
2336
+ goto err_free_isids;
2337
+ }
22312338
22322339 /*
22332340 * Convert the internal representations of contexts
22342341 * in the new SID table.
22352342 */
2236
- args.state = state;
2237
- args.oldp = policydb;
2238
- args.newp = newpolicydb;
2343
+ convert_data->args.state = state;
2344
+ convert_data->args.oldp = &oldpolicy->policydb;
2345
+ convert_data->args.newp = &newpolicy->policydb;
22392346
2240
- convert_params.func = convert_context;
2241
- convert_params.args = &args;
2242
- convert_params.target = newsidtab;
2347
+ convert_data->sidtab_params.func = convert_context;
2348
+ convert_data->sidtab_params.args = &convert_data->args;
2349
+ convert_data->sidtab_params.target = newpolicy->sidtab;
22432350
2244
- rc = sidtab_convert(oldsidtab, &convert_params);
2351
+ rc = sidtab_convert(oldpolicy->sidtab, &convert_data->sidtab_params);
22452352 if (rc) {
22462353 pr_err("SELinux: unable to convert the internal"
22472354 " representation of contexts in the new SID"
22482355 " table\n");
2249
- goto err;
2356
+ goto err_free_convert_data;
22502357 }
22512358
2252
- /* Save the old policydb and SID table to free later. */
2253
- memcpy(oldpolicydb, policydb, sizeof(*policydb));
2359
+ load_state->policy = newpolicy;
2360
+ load_state->convert_data = convert_data;
2361
+ return 0;
22542362
2255
- /* Install the new policydb and SID table. */
2256
- write_lock_irq(&state->ss->policy_rwlock);
2257
- memcpy(policydb, newpolicydb, sizeof(*policydb));
2258
- state->ss->sidtab = newsidtab;
2259
- security_load_policycaps(state);
2260
- oldmapping = state->ss->map.mapping;
2261
- state->ss->map.mapping = newmap.mapping;
2262
- state->ss->map.size = newmap.size;
2263
- seqno = ++state->ss->latest_granting;
2264
- write_unlock_irq(&state->ss->policy_rwlock);
2363
+err_free_convert_data:
2364
+ kfree(convert_data);
2365
+err_free_isids:
2366
+ sidtab_destroy(newpolicy->sidtab);
2367
+err_mapping:
2368
+ kfree(newpolicy->map.mapping);
2369
+err_policydb:
2370
+ policydb_destroy(&newpolicy->policydb);
2371
+err_sidtab:
2372
+ kfree(newpolicy->sidtab);
2373
+err_policy:
2374
+ kfree(newpolicy);
22652375
2266
- /* Free the old policydb and SID table. */
2267
- policydb_destroy(oldpolicydb);
2268
- sidtab_destroy(oldsidtab);
2269
- kfree(oldsidtab);
2270
- kfree(oldmapping);
2271
-
2272
- avc_ss_reset(state->avc, seqno);
2273
- selnl_notify_policyload(seqno);
2274
- selinux_status_update_policyload(state, seqno);
2275
- selinux_netlbl_cache_invalidate();
2276
- selinux_xfrm_notify_policyload();
2277
-
2278
- rc = 0;
2279
- goto out;
2280
-
2281
-err:
2282
- kfree(newmap.mapping);
2283
- sidtab_destroy(newsidtab);
2284
- kfree(newsidtab);
2285
- policydb_destroy(newpolicydb);
2286
-
2287
-out:
2288
- kfree(oldpolicydb);
22892376 return rc;
22902377 }
22912378
2292
-size_t security_policydb_len(struct selinux_state *state)
2379
+/**
2380
+ * ocontext_to_sid - Helper to safely get sid for an ocontext
2381
+ * @sidtab: SID table
2382
+ * @c: ocontext structure
2383
+ * @index: index of the context entry (0 or 1)
2384
+ * @out_sid: pointer to the resulting SID value
2385
+ *
2386
+ * For all ocontexts except OCON_ISID the SID fields are populated
2387
+ * on-demand when needed. Since updating the SID value is an SMP-sensitive
2388
+ * operation, this helper must be used to do that safely.
2389
+ *
2390
+ * WARNING: This function may return -ESTALE, indicating that the caller
2391
+ * must retry the operation after re-acquiring the policy pointer!
2392
+ */
2393
+static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c,
2394
+ size_t index, u32 *out_sid)
22932395 {
2294
- struct policydb *p = &state->ss->policydb;
2295
- size_t len;
2396
+ int rc;
2397
+ u32 sid;
22962398
2297
- read_lock(&state->ss->policy_rwlock);
2298
- len = p->len;
2299
- read_unlock(&state->ss->policy_rwlock);
2399
+ /* Ensure the associated sidtab entry is visible to this thread. */
2400
+ sid = smp_load_acquire(&c->sid[index]);
2401
+ if (!sid) {
2402
+ rc = sidtab_context_to_sid(sidtab, &c->context[index], &sid);
2403
+ if (rc)
2404
+ return rc;
23002405
2301
- return len;
2406
+ /*
2407
+ * Ensure the new sidtab entry is visible to other threads
2408
+ * when they see the SID.
2409
+ */
2410
+ smp_store_release(&c->sid[index], sid);
2411
+ }
2412
+ *out_sid = sid;
2413
+ return 0;
23022414 }
23032415
23042416 /**
....@@ -2310,15 +2422,23 @@
23102422 int security_port_sid(struct selinux_state *state,
23112423 u8 protocol, u16 port, u32 *out_sid)
23122424 {
2425
+ struct selinux_policy *policy;
23132426 struct policydb *policydb;
23142427 struct sidtab *sidtab;
23152428 struct ocontext *c;
2316
- int rc = 0;
2429
+ int rc;
23172430
2318
- read_lock(&state->ss->policy_rwlock);
2431
+ if (!selinux_initialized(state)) {
2432
+ *out_sid = SECINITSID_PORT;
2433
+ return 0;
2434
+ }
23192435
2320
- policydb = &state->ss->policydb;
2321
- sidtab = state->ss->sidtab;
2436
+retry:
2437
+ rc = 0;
2438
+ rcu_read_lock();
2439
+ policy = rcu_dereference(state->policy);
2440
+ policydb = &policy->policydb;
2441
+ sidtab = policy->sidtab;
23222442
23232443 c = policydb->ocontexts[OCON_PORT];
23242444 while (c) {
....@@ -2330,19 +2450,19 @@
23302450 }
23312451
23322452 if (c) {
2333
- if (!c->sid[0]) {
2334
- rc = context_struct_to_sid(state, &c->context[0],
2335
- &c->sid[0]);
2336
- if (rc)
2337
- goto out;
2453
+ rc = ocontext_to_sid(sidtab, c, 0, out_sid);
2454
+ if (rc == -ESTALE) {
2455
+ rcu_read_unlock();
2456
+ goto retry;
23382457 }
2339
- *out_sid = c->sid[0];
2458
+ if (rc)
2459
+ goto out;
23402460 } else {
23412461 *out_sid = SECINITSID_PORT;
23422462 }
23432463
23442464 out:
2345
- read_unlock(&state->ss->policy_rwlock);
2465
+ rcu_read_unlock();
23462466 return rc;
23472467 }
23482468
....@@ -2355,13 +2475,23 @@
23552475 int security_ib_pkey_sid(struct selinux_state *state,
23562476 u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
23572477 {
2478
+ struct selinux_policy *policy;
23582479 struct policydb *policydb;
2480
+ struct sidtab *sidtab;
23592481 struct ocontext *c;
2360
- int rc = 0;
2482
+ int rc;
23612483
2362
- read_lock(&state->ss->policy_rwlock);
2484
+ if (!selinux_initialized(state)) {
2485
+ *out_sid = SECINITSID_UNLABELED;
2486
+ return 0;
2487
+ }
23632488
2364
- policydb = &state->ss->policydb;
2489
+retry:
2490
+ rc = 0;
2491
+ rcu_read_lock();
2492
+ policy = rcu_dereference(state->policy);
2493
+ policydb = &policy->policydb;
2494
+ sidtab = policy->sidtab;
23652495
23662496 c = policydb->ocontexts[OCON_IBPKEY];
23672497 while (c) {
....@@ -2374,19 +2504,18 @@
23742504 }
23752505
23762506 if (c) {
2377
- if (!c->sid[0]) {
2378
- rc = context_struct_to_sid(state,
2379
- &c->context[0],
2380
- &c->sid[0]);
2381
- if (rc)
2382
- goto out;
2507
+ rc = ocontext_to_sid(sidtab, c, 0, out_sid);
2508
+ if (rc == -ESTALE) {
2509
+ rcu_read_unlock();
2510
+ goto retry;
23832511 }
2384
- *out_sid = c->sid[0];
2512
+ if (rc)
2513
+ goto out;
23852514 } else
23862515 *out_sid = SECINITSID_UNLABELED;
23872516
23882517 out:
2389
- read_unlock(&state->ss->policy_rwlock);
2518
+ rcu_read_unlock();
23902519 return rc;
23912520 }
23922521
....@@ -2399,15 +2528,23 @@
23992528 int security_ib_endport_sid(struct selinux_state *state,
24002529 const char *dev_name, u8 port_num, u32 *out_sid)
24012530 {
2531
+ struct selinux_policy *policy;
24022532 struct policydb *policydb;
24032533 struct sidtab *sidtab;
24042534 struct ocontext *c;
2405
- int rc = 0;
2535
+ int rc;
24062536
2407
- read_lock(&state->ss->policy_rwlock);
2537
+ if (!selinux_initialized(state)) {
2538
+ *out_sid = SECINITSID_UNLABELED;
2539
+ return 0;
2540
+ }
24082541
2409
- policydb = &state->ss->policydb;
2410
- sidtab = state->ss->sidtab;
2542
+retry:
2543
+ rc = 0;
2544
+ rcu_read_lock();
2545
+ policy = rcu_dereference(state->policy);
2546
+ policydb = &policy->policydb;
2547
+ sidtab = policy->sidtab;
24112548
24122549 c = policydb->ocontexts[OCON_IBENDPORT];
24132550 while (c) {
....@@ -2421,18 +2558,18 @@
24212558 }
24222559
24232560 if (c) {
2424
- if (!c->sid[0]) {
2425
- rc = context_struct_to_sid(state, &c->context[0],
2426
- &c->sid[0]);
2427
- if (rc)
2428
- goto out;
2561
+ rc = ocontext_to_sid(sidtab, c, 0, out_sid);
2562
+ if (rc == -ESTALE) {
2563
+ rcu_read_unlock();
2564
+ goto retry;
24292565 }
2430
- *out_sid = c->sid[0];
2566
+ if (rc)
2567
+ goto out;
24312568 } else
24322569 *out_sid = SECINITSID_UNLABELED;
24332570
24342571 out:
2435
- read_unlock(&state->ss->policy_rwlock);
2572
+ rcu_read_unlock();
24362573 return rc;
24372574 }
24382575
....@@ -2444,15 +2581,23 @@
24442581 int security_netif_sid(struct selinux_state *state,
24452582 char *name, u32 *if_sid)
24462583 {
2584
+ struct selinux_policy *policy;
24472585 struct policydb *policydb;
24482586 struct sidtab *sidtab;
2449
- int rc = 0;
2587
+ int rc;
24502588 struct ocontext *c;
24512589
2452
- read_lock(&state->ss->policy_rwlock);
2590
+ if (!selinux_initialized(state)) {
2591
+ *if_sid = SECINITSID_NETIF;
2592
+ return 0;
2593
+ }
24532594
2454
- policydb = &state->ss->policydb;
2455
- sidtab = state->ss->sidtab;
2595
+retry:
2596
+ rc = 0;
2597
+ rcu_read_lock();
2598
+ policy = rcu_dereference(state->policy);
2599
+ policydb = &policy->policydb;
2600
+ sidtab = policy->sidtab;
24562601
24572602 c = policydb->ocontexts[OCON_NETIF];
24582603 while (c) {
....@@ -2462,22 +2607,18 @@
24622607 }
24632608
24642609 if (c) {
2465
- if (!c->sid[0] || !c->sid[1]) {
2466
- rc = context_struct_to_sid(state, &c->context[0],
2467
- &c->sid[0]);
2468
- if (rc)
2469
- goto out;
2470
- rc = context_struct_to_sid(state, &c->context[1],
2471
- &c->sid[1]);
2472
- if (rc)
2473
- goto out;
2610
+ rc = ocontext_to_sid(sidtab, c, 0, if_sid);
2611
+ if (rc == -ESTALE) {
2612
+ rcu_read_unlock();
2613
+ goto retry;
24742614 }
2475
- *if_sid = c->sid[0];
2615
+ if (rc)
2616
+ goto out;
24762617 } else
24772618 *if_sid = SECINITSID_NETIF;
24782619
24792620 out:
2480
- read_unlock(&state->ss->policy_rwlock);
2621
+ rcu_read_unlock();
24812622 return rc;
24822623 }
24832624
....@@ -2507,13 +2648,22 @@
25072648 u32 addrlen,
25082649 u32 *out_sid)
25092650 {
2651
+ struct selinux_policy *policy;
25102652 struct policydb *policydb;
2653
+ struct sidtab *sidtab;
25112654 int rc;
25122655 struct ocontext *c;
25132656
2514
- read_lock(&state->ss->policy_rwlock);
2657
+ if (!selinux_initialized(state)) {
2658
+ *out_sid = SECINITSID_NODE;
2659
+ return 0;
2660
+ }
25152661
2516
- policydb = &state->ss->policydb;
2662
+retry:
2663
+ rcu_read_lock();
2664
+ policy = rcu_dereference(state->policy);
2665
+ policydb = &policy->policydb;
2666
+ sidtab = policy->sidtab;
25172667
25182668 switch (domain) {
25192669 case AF_INET: {
....@@ -2554,21 +2704,20 @@
25542704 }
25552705
25562706 if (c) {
2557
- if (!c->sid[0]) {
2558
- rc = context_struct_to_sid(state,
2559
- &c->context[0],
2560
- &c->sid[0]);
2561
- if (rc)
2562
- goto out;
2707
+ rc = ocontext_to_sid(sidtab, c, 0, out_sid);
2708
+ if (rc == -ESTALE) {
2709
+ rcu_read_unlock();
2710
+ goto retry;
25632711 }
2564
- *out_sid = c->sid[0];
2712
+ if (rc)
2713
+ goto out;
25652714 } else {
25662715 *out_sid = SECINITSID_NODE;
25672716 }
25682717
25692718 rc = 0;
25702719 out:
2571
- read_unlock(&state->ss->policy_rwlock);
2720
+ rcu_read_unlock();
25722721 return rc;
25732722 }
25742723
....@@ -2594,26 +2743,33 @@
25942743 u32 **sids,
25952744 u32 *nel)
25962745 {
2746
+ struct selinux_policy *policy;
25972747 struct policydb *policydb;
25982748 struct sidtab *sidtab;
25992749 struct context *fromcon, usercon;
26002750 u32 *mysids = NULL, *mysids2, sid;
2601
- u32 mynel = 0, maxnel = SIDS_NEL;
2751
+ u32 i, j, mynel, maxnel = SIDS_NEL;
26022752 struct user_datum *user;
26032753 struct role_datum *role;
26042754 struct ebitmap_node *rnode, *tnode;
2605
- int rc = 0, i, j;
2755
+ int rc;
26062756
26072757 *sids = NULL;
26082758 *nel = 0;
26092759
2610
- if (!state->initialized)
2611
- goto out;
2760
+ if (!selinux_initialized(state))
2761
+ return 0;
26122762
2613
- read_lock(&state->ss->policy_rwlock);
2763
+ mysids = kcalloc(maxnel, sizeof(*mysids), GFP_KERNEL);
2764
+ if (!mysids)
2765
+ return -ENOMEM;
26142766
2615
- policydb = &state->ss->policydb;
2616
- sidtab = state->ss->sidtab;
2767
+retry:
2768
+ mynel = 0;
2769
+ rcu_read_lock();
2770
+ policy = rcu_dereference(state->policy);
2771
+ policydb = &policy->policydb;
2772
+ sidtab = policy->sidtab;
26172773
26182774 context_init(&usercon);
26192775
....@@ -2623,33 +2779,27 @@
26232779 goto out_unlock;
26242780
26252781 rc = -EINVAL;
2626
- user = hashtab_search(policydb->p_users.table, username);
2782
+ user = symtab_search(&policydb->p_users, username);
26272783 if (!user)
26282784 goto out_unlock;
26292785
26302786 usercon.user = user->value;
2631
-
2632
- rc = -ENOMEM;
2633
- mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC);
2634
- if (!mysids)
2635
- goto out_unlock;
26362787
26372788 ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
26382789 role = policydb->role_val_to_struct[i];
26392790 usercon.role = i + 1;
26402791 ebitmap_for_each_positive_bit(&role->types, tnode, j) {
26412792 usercon.type = j + 1;
2642
- /*
2643
- * The same context struct is reused here so the hash
2644
- * must be reset.
2645
- */
2646
- usercon.hash = 0;
26472793
26482794 if (mls_setup_user_range(policydb, fromcon, user,
26492795 &usercon))
26502796 continue;
26512797
2652
- rc = context_struct_to_sid(state, &usercon, &sid);
2798
+ rc = sidtab_context_to_sid(sidtab, &usercon, &sid);
2799
+ if (rc == -ESTALE) {
2800
+ rcu_read_unlock();
2801
+ goto retry;
2802
+ }
26532803 if (rc)
26542804 goto out_unlock;
26552805 if (mynel < maxnel) {
....@@ -2669,17 +2819,17 @@
26692819 }
26702820 rc = 0;
26712821 out_unlock:
2672
- read_unlock(&state->ss->policy_rwlock);
2822
+ rcu_read_unlock();
26732823 if (rc || !mynel) {
26742824 kfree(mysids);
2675
- goto out;
2825
+ return rc;
26762826 }
26772827
26782828 rc = -ENOMEM;
26792829 mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
26802830 if (!mysids2) {
26812831 kfree(mysids);
2682
- goto out;
2832
+ return rc;
26832833 }
26842834 for (i = 0, j = 0; i < mynel; i++) {
26852835 struct av_decision dummy_avd;
....@@ -2692,12 +2842,10 @@
26922842 mysids2[j++] = mysids[i];
26932843 cond_resched();
26942844 }
2695
- rc = 0;
26962845 kfree(mysids);
26972846 *sids = mysids2;
26982847 *nel = j;
2699
-out:
2700
- return rc;
2848
+ return 0;
27012849 }
27022850
27032851 /**
....@@ -2711,25 +2859,27 @@
27112859 * cannot support xattr or use a fixed labeling behavior like
27122860 * transition SIDs or task SIDs.
27132861 *
2714
- * The caller must acquire the policy_rwlock before calling this function.
2862
+ * WARNING: This function may return -ESTALE, indicating that the caller
2863
+ * must retry the operation after re-acquiring the policy pointer!
27152864 */
2716
-static inline int __security_genfs_sid(struct selinux_state *state,
2865
+static inline int __security_genfs_sid(struct selinux_policy *policy,
27172866 const char *fstype,
27182867 char *path,
27192868 u16 orig_sclass,
27202869 u32 *sid)
27212870 {
2722
- struct policydb *policydb = &state->ss->policydb;
2871
+ struct policydb *policydb = &policy->policydb;
2872
+ struct sidtab *sidtab = policy->sidtab;
27232873 int len;
27242874 u16 sclass;
27252875 struct genfs *genfs;
27262876 struct ocontext *c;
2727
- int rc, cmp = 0;
2877
+ int cmp = 0;
27282878
27292879 while (path[0] == '/' && path[1] == '/')
27302880 path++;
27312881
2732
- sclass = unmap_class(&state->ss->map, orig_sclass);
2882
+ sclass = unmap_class(&policy->map, orig_sclass);
27332883 *sid = SECINITSID_UNLABELED;
27342884
27352885 for (genfs = policydb->genfs; genfs; genfs = genfs->next) {
....@@ -2738,9 +2888,8 @@
27382888 break;
27392889 }
27402890
2741
- rc = -ENOENT;
27422891 if (!genfs || cmp)
2743
- goto out;
2892
+ return -ENOENT;
27442893
27452894 for (c = genfs->head; c; c = c->next) {
27462895 len = strlen(c->u.name);
....@@ -2749,20 +2898,10 @@
27492898 break;
27502899 }
27512900
2752
- rc = -ENOENT;
27532901 if (!c)
2754
- goto out;
2902
+ return -ENOENT;
27552903
2756
- if (!c->sid[0]) {
2757
- rc = context_struct_to_sid(state, &c->context[0], &c->sid[0]);
2758
- if (rc)
2759
- goto out;
2760
- }
2761
-
2762
- *sid = c->sid[0];
2763
- rc = 0;
2764
-out:
2765
- return rc;
2904
+ return ocontext_to_sid(sidtab, c, 0, sid);
27662905 }
27672906
27682907 /**
....@@ -2781,12 +2920,32 @@
27812920 u16 orig_sclass,
27822921 u32 *sid)
27832922 {
2923
+ struct selinux_policy *policy;
27842924 int retval;
27852925
2786
- read_lock(&state->ss->policy_rwlock);
2787
- retval = __security_genfs_sid(state, fstype, path, orig_sclass, sid);
2788
- read_unlock(&state->ss->policy_rwlock);
2926
+ if (!selinux_initialized(state)) {
2927
+ *sid = SECINITSID_UNLABELED;
2928
+ return 0;
2929
+ }
2930
+
2931
+ do {
2932
+ rcu_read_lock();
2933
+ policy = rcu_dereference(state->policy);
2934
+ retval = __security_genfs_sid(policy, fstype, path,
2935
+ orig_sclass, sid);
2936
+ rcu_read_unlock();
2937
+ } while (retval == -ESTALE);
27892938 return retval;
2939
+}
2940
+
2941
+int selinux_policy_genfs_sid(struct selinux_policy *policy,
2942
+ const char *fstype,
2943
+ char *path,
2944
+ u16 orig_sclass,
2945
+ u32 *sid)
2946
+{
2947
+ /* no lock required, policy is not yet accessible by other threads */
2948
+ return __security_genfs_sid(policy, fstype, path, orig_sclass, sid);
27902949 }
27912950
27922951 /**
....@@ -2795,17 +2954,26 @@
27952954 */
27962955 int security_fs_use(struct selinux_state *state, struct super_block *sb)
27972956 {
2957
+ struct selinux_policy *policy;
27982958 struct policydb *policydb;
27992959 struct sidtab *sidtab;
2800
- int rc = 0;
2960
+ int rc;
28012961 struct ocontext *c;
28022962 struct superblock_security_struct *sbsec = sb->s_security;
28032963 const char *fstype = sb->s_type->name;
28042964
2805
- read_lock(&state->ss->policy_rwlock);
2965
+ if (!selinux_initialized(state)) {
2966
+ sbsec->behavior = SECURITY_FS_USE_NONE;
2967
+ sbsec->sid = SECINITSID_UNLABELED;
2968
+ return 0;
2969
+ }
28062970
2807
- policydb = &state->ss->policydb;
2808
- sidtab = state->ss->sidtab;
2971
+retry:
2972
+ rc = 0;
2973
+ rcu_read_lock();
2974
+ policy = rcu_dereference(state->policy);
2975
+ policydb = &policy->policydb;
2976
+ sidtab = policy->sidtab;
28092977
28102978 c = policydb->ocontexts[OCON_FSUSE];
28112979 while (c) {
....@@ -2816,16 +2984,20 @@
28162984
28172985 if (c) {
28182986 sbsec->behavior = c->v.behavior;
2819
- if (!c->sid[0]) {
2820
- rc = context_struct_to_sid(state, &c->context[0],
2821
- &c->sid[0]);
2822
- if (rc)
2823
- goto out;
2987
+ rc = ocontext_to_sid(sidtab, c, 0, &sbsec->sid);
2988
+ if (rc == -ESTALE) {
2989
+ rcu_read_unlock();
2990
+ goto retry;
28242991 }
2825
- sbsec->sid = c->sid[0];
2992
+ if (rc)
2993
+ goto out;
28262994 } else {
2827
- rc = __security_genfs_sid(state, fstype, "/", SECCLASS_DIR,
2828
- &sbsec->sid);
2995
+ rc = __security_genfs_sid(policy, fstype, "/",
2996
+ SECCLASS_DIR, &sbsec->sid);
2997
+ if (rc == -ESTALE) {
2998
+ rcu_read_unlock();
2999
+ goto retry;
3000
+ }
28293001 if (rc) {
28303002 sbsec->behavior = SECURITY_FS_USE_NONE;
28313003 rc = 0;
....@@ -2835,26 +3007,18 @@
28353007 }
28363008
28373009 out:
2838
- read_unlock(&state->ss->policy_rwlock);
3010
+ rcu_read_unlock();
28393011 return rc;
28403012 }
28413013
2842
-int security_get_bools(struct selinux_state *state,
2843
- int *len, char ***names, int **values)
3014
+int security_get_bools(struct selinux_policy *policy,
3015
+ u32 *len, char ***names, int **values)
28443016 {
28453017 struct policydb *policydb;
2846
- int i, rc;
3018
+ u32 i;
3019
+ int rc;
28473020
2848
- if (!state->initialized) {
2849
- *len = 0;
2850
- *names = NULL;
2851
- *values = NULL;
2852
- return 0;
2853
- }
2854
-
2855
- read_lock(&state->ss->policy_rwlock);
2856
-
2857
- policydb = &state->ss->policydb;
3021
+ policydb = &policy->policydb;
28583022
28593023 *names = NULL;
28603024 *values = NULL;
....@@ -2885,7 +3049,6 @@
28853049 }
28863050 rc = 0;
28873051 out:
2888
- read_unlock(&state->ss->policy_rwlock);
28893052 return rc;
28903053 err:
28913054 if (*names) {
....@@ -2901,68 +3064,91 @@
29013064 }
29023065
29033066
2904
-int security_set_bools(struct selinux_state *state, int len, int *values)
3067
+int security_set_bools(struct selinux_state *state, u32 len, int *values)
29053068 {
2906
- struct policydb *policydb;
2907
- int i, rc;
2908
- int lenp, seqno = 0;
2909
- struct cond_node *cur;
3069
+ struct selinux_policy *newpolicy, *oldpolicy;
3070
+ int rc;
3071
+ u32 i, seqno = 0;
29103072
2911
- write_lock_irq(&state->ss->policy_rwlock);
3073
+ if (!selinux_initialized(state))
3074
+ return -EINVAL;
29123075
2913
- policydb = &state->ss->policydb;
3076
+ oldpolicy = rcu_dereference_protected(state->policy,
3077
+ lockdep_is_held(&state->policy_mutex));
29143078
2915
- rc = -EFAULT;
2916
- lenp = policydb->p_bools.nprim;
2917
- if (len != lenp)
2918
- goto out;
3079
+ /* Consistency check on number of booleans, should never fail */
3080
+ if (WARN_ON(len != oldpolicy->policydb.p_bools.nprim))
3081
+ return -EINVAL;
29193082
3083
+ newpolicy = kmemdup(oldpolicy, sizeof(*newpolicy), GFP_KERNEL);
3084
+ if (!newpolicy)
3085
+ return -ENOMEM;
3086
+
3087
+ /*
3088
+ * Deep copy only the parts of the policydb that might be
3089
+ * modified as a result of changing booleans.
3090
+ */
3091
+ rc = cond_policydb_dup(&newpolicy->policydb, &oldpolicy->policydb);
3092
+ if (rc) {
3093
+ kfree(newpolicy);
3094
+ return -ENOMEM;
3095
+ }
3096
+
3097
+ /* Update the boolean states in the copy */
29203098 for (i = 0; i < len; i++) {
2921
- if (!!values[i] != policydb->bool_val_to_struct[i]->state) {
3099
+ int new_state = !!values[i];
3100
+ int old_state = newpolicy->policydb.bool_val_to_struct[i]->state;
3101
+
3102
+ if (new_state != old_state) {
29223103 audit_log(audit_context(), GFP_ATOMIC,
29233104 AUDIT_MAC_CONFIG_CHANGE,
29243105 "bool=%s val=%d old_val=%d auid=%u ses=%u",
2925
- sym_name(policydb, SYM_BOOLS, i),
2926
- !!values[i],
2927
- policydb->bool_val_to_struct[i]->state,
3106
+ sym_name(&newpolicy->policydb, SYM_BOOLS, i),
3107
+ new_state,
3108
+ old_state,
29283109 from_kuid(&init_user_ns, audit_get_loginuid(current)),
29293110 audit_get_sessionid(current));
3111
+ newpolicy->policydb.bool_val_to_struct[i]->state = new_state;
29303112 }
2931
- if (values[i])
2932
- policydb->bool_val_to_struct[i]->state = 1;
2933
- else
2934
- policydb->bool_val_to_struct[i]->state = 0;
29353113 }
29363114
2937
- for (cur = policydb->cond_list; cur; cur = cur->next) {
2938
- rc = evaluate_cond_node(policydb, cur);
2939
- if (rc)
2940
- goto out;
2941
- }
3115
+ /* Re-evaluate the conditional rules in the copy */
3116
+ evaluate_cond_nodes(&newpolicy->policydb);
29423117
2943
- seqno = ++state->ss->latest_granting;
2944
- rc = 0;
2945
-out:
2946
- write_unlock_irq(&state->ss->policy_rwlock);
2947
- if (!rc) {
2948
- avc_ss_reset(state->avc, seqno);
2949
- selnl_notify_policyload(seqno);
2950
- selinux_status_update_policyload(state, seqno);
2951
- selinux_xfrm_notify_policyload();
2952
- }
2953
- return rc;
3118
+ /* Set latest granting seqno for new policy */
3119
+ newpolicy->latest_granting = oldpolicy->latest_granting + 1;
3120
+ seqno = newpolicy->latest_granting;
3121
+
3122
+ /* Install the new policy */
3123
+ rcu_assign_pointer(state->policy, newpolicy);
3124
+
3125
+ /*
3126
+ * Free the conditional portions of the old policydb
3127
+ * that were copied for the new policy, and the oldpolicy
3128
+ * structure itself but not what it references.
3129
+ */
3130
+ synchronize_rcu();
3131
+ selinux_policy_cond_free(oldpolicy);
3132
+
3133
+ /* Notify others of the policy change */
3134
+ selinux_notify_policy_change(state, seqno);
3135
+ return 0;
29543136 }
29553137
29563138 int security_get_bool_value(struct selinux_state *state,
2957
- int index)
3139
+ u32 index)
29583140 {
3141
+ struct selinux_policy *policy;
29593142 struct policydb *policydb;
29603143 int rc;
2961
- int len;
3144
+ u32 len;
29623145
2963
- read_lock(&state->ss->policy_rwlock);
3146
+ if (!selinux_initialized(state))
3147
+ return 0;
29643148
2965
- policydb = &state->ss->policydb;
3149
+ rcu_read_lock();
3150
+ policy = rcu_dereference(state->policy);
3151
+ policydb = &policy->policydb;
29663152
29673153 rc = -EFAULT;
29683154 len = policydb->p_bools.nprim;
....@@ -2971,31 +3157,28 @@
29713157
29723158 rc = policydb->bool_val_to_struct[index]->state;
29733159 out:
2974
- read_unlock(&state->ss->policy_rwlock);
3160
+ rcu_read_unlock();
29753161 return rc;
29763162 }
29773163
2978
-static int security_preserve_bools(struct selinux_state *state,
2979
- struct policydb *policydb)
3164
+static int security_preserve_bools(struct selinux_policy *oldpolicy,
3165
+ struct selinux_policy *newpolicy)
29803166 {
2981
- int rc, nbools = 0, *bvalues = NULL, i;
3167
+ int rc, *bvalues = NULL;
29823168 char **bnames = NULL;
29833169 struct cond_bool_datum *booldatum;
2984
- struct cond_node *cur;
3170
+ u32 i, nbools = 0;
29853171
2986
- rc = security_get_bools(state, &nbools, &bnames, &bvalues);
3172
+ rc = security_get_bools(oldpolicy, &nbools, &bnames, &bvalues);
29873173 if (rc)
29883174 goto out;
29893175 for (i = 0; i < nbools; i++) {
2990
- booldatum = hashtab_search(policydb->p_bools.table, bnames[i]);
3176
+ booldatum = symtab_search(&newpolicy->policydb.p_bools,
3177
+ bnames[i]);
29913178 if (booldatum)
29923179 booldatum->state = bvalues[i];
29933180 }
2994
- for (cur = policydb->cond_list; cur; cur = cur->next) {
2995
- rc = evaluate_cond_node(policydb, cur);
2996
- if (rc)
2997
- goto out;
2998
- }
3181
+ evaluate_cond_nodes(&newpolicy->policydb);
29993182
30003183 out:
30013184 if (bnames) {
....@@ -3014,8 +3197,9 @@
30143197 int security_sid_mls_copy(struct selinux_state *state,
30153198 u32 sid, u32 mls_sid, u32 *new_sid)
30163199 {
3017
- struct policydb *policydb = &state->ss->policydb;
3018
- struct sidtab *sidtab = state->ss->sidtab;
3200
+ struct selinux_policy *policy;
3201
+ struct policydb *policydb;
3202
+ struct sidtab *sidtab;
30193203 struct context *context1;
30203204 struct context *context2;
30213205 struct context newcon;
....@@ -3023,15 +3207,24 @@
30233207 u32 len;
30243208 int rc;
30253209
3026
- rc = 0;
3027
- if (!state->initialized || !policydb->mls_enabled) {
3210
+ if (!selinux_initialized(state)) {
30283211 *new_sid = sid;
3029
- goto out;
3212
+ return 0;
30303213 }
30313214
3215
+retry:
3216
+ rc = 0;
30323217 context_init(&newcon);
30333218
3034
- read_lock(&state->ss->policy_rwlock);
3219
+ rcu_read_lock();
3220
+ policy = rcu_dereference(state->policy);
3221
+ policydb = &policy->policydb;
3222
+ sidtab = policy->sidtab;
3223
+
3224
+ if (!policydb->mls_enabled) {
3225
+ *new_sid = sid;
3226
+ goto out_unlock;
3227
+ }
30353228
30363229 rc = -EINVAL;
30373230 context1 = sidtab_search(sidtab, sid);
....@@ -3058,24 +3251,35 @@
30583251
30593252 /* Check the validity of the new context. */
30603253 if (!policydb_context_isvalid(policydb, &newcon)) {
3061
- rc = convert_context_handle_invalid_context(state, &newcon);
3254
+ rc = convert_context_handle_invalid_context(state, policydb,
3255
+ &newcon);
30623256 if (rc) {
30633257 if (!context_struct_to_string(policydb, &newcon, &s,
30643258 &len)) {
3065
- audit_log(audit_context(),
3066
- GFP_ATOMIC, AUDIT_SELINUX_ERR,
3067
- "op=security_sid_mls_copy "
3068
- "invalid_context=%s", s);
3259
+ struct audit_buffer *ab;
3260
+
3261
+ ab = audit_log_start(audit_context(),
3262
+ GFP_ATOMIC,
3263
+ AUDIT_SELINUX_ERR);
3264
+ audit_log_format(ab,
3265
+ "op=security_sid_mls_copy invalid_context=");
3266
+ /* don't record NUL with untrusted strings */
3267
+ audit_log_n_untrustedstring(ab, s, len - 1);
3268
+ audit_log_end(ab);
30693269 kfree(s);
30703270 }
30713271 goto out_unlock;
30723272 }
30733273 }
3074
- rc = context_struct_to_sid(state, &newcon, new_sid);
3274
+ rc = sidtab_context_to_sid(sidtab, &newcon, new_sid);
3275
+ if (rc == -ESTALE) {
3276
+ rcu_read_unlock();
3277
+ context_destroy(&newcon);
3278
+ goto retry;
3279
+ }
30753280 out_unlock:
3076
- read_unlock(&state->ss->policy_rwlock);
3281
+ rcu_read_unlock();
30773282 context_destroy(&newcon);
3078
-out:
30793283 return rc;
30803284 }
30813285
....@@ -3104,8 +3308,9 @@
31043308 u32 xfrm_sid,
31053309 u32 *peer_sid)
31063310 {
3107
- struct policydb *policydb = &state->ss->policydb;
3108
- struct sidtab *sidtab = state->ss->sidtab;
3311
+ struct selinux_policy *policy;
3312
+ struct policydb *policydb;
3313
+ struct sidtab *sidtab;
31093314 int rc;
31103315 struct context *nlbl_ctx;
31113316 struct context *xfrm_ctx;
....@@ -3127,15 +3332,23 @@
31273332 return 0;
31283333 }
31293334
3335
+ if (!selinux_initialized(state))
3336
+ return 0;
3337
+
3338
+ rcu_read_lock();
3339
+ policy = rcu_dereference(state->policy);
3340
+ policydb = &policy->policydb;
3341
+ sidtab = policy->sidtab;
3342
+
31303343 /*
31313344 * We don't need to check initialized here since the only way both
31323345 * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
31333346 * security server was initialized and state->initialized was true.
31343347 */
3135
- if (!policydb->mls_enabled)
3136
- return 0;
3137
-
3138
- read_lock(&state->ss->policy_rwlock);
3348
+ if (!policydb->mls_enabled) {
3349
+ rc = 0;
3350
+ goto out;
3351
+ }
31393352
31403353 rc = -EINVAL;
31413354 nlbl_ctx = sidtab_search(sidtab, nlbl_sid);
....@@ -3162,7 +3375,7 @@
31623375 * expressive */
31633376 *peer_sid = xfrm_sid;
31643377 out:
3165
- read_unlock(&state->ss->policy_rwlock);
3378
+ rcu_read_unlock();
31663379 return rc;
31673380 }
31683381
....@@ -3179,19 +3392,13 @@
31793392 return 0;
31803393 }
31813394
3182
-int security_get_classes(struct selinux_state *state,
3395
+int security_get_classes(struct selinux_policy *policy,
31833396 char ***classes, int *nclasses)
31843397 {
3185
- struct policydb *policydb = &state->ss->policydb;
3398
+ struct policydb *policydb;
31863399 int rc;
31873400
3188
- if (!state->initialized) {
3189
- *nclasses = 0;
3190
- *classes = NULL;
3191
- return 0;
3192
- }
3193
-
3194
- read_lock(&state->ss->policy_rwlock);
3401
+ policydb = &policy->policydb;
31953402
31963403 rc = -ENOMEM;
31973404 *nclasses = policydb->p_classes.nprim;
....@@ -3199,8 +3406,8 @@
31993406 if (!*classes)
32003407 goto out;
32013408
3202
- rc = hashtab_map(policydb->p_classes.table, get_classes_callback,
3203
- *classes);
3409
+ rc = hashtab_map(&policydb->p_classes.table, get_classes_callback,
3410
+ *classes);
32043411 if (rc) {
32053412 int i;
32063413 for (i = 0; i < *nclasses; i++)
....@@ -3209,7 +3416,6 @@
32093416 }
32103417
32113418 out:
3212
- read_unlock(&state->ss->policy_rwlock);
32133419 return rc;
32143420 }
32153421
....@@ -3226,17 +3432,17 @@
32263432 return 0;
32273433 }
32283434
3229
-int security_get_permissions(struct selinux_state *state,
3435
+int security_get_permissions(struct selinux_policy *policy,
32303436 char *class, char ***perms, int *nperms)
32313437 {
3232
- struct policydb *policydb = &state->ss->policydb;
3438
+ struct policydb *policydb;
32333439 int rc, i;
32343440 struct class_datum *match;
32353441
3236
- read_lock(&state->ss->policy_rwlock);
3442
+ policydb = &policy->policydb;
32373443
32383444 rc = -EINVAL;
3239
- match = hashtab_search(policydb->p_classes.table, class);
3445
+ match = symtab_search(&policydb->p_classes, class);
32403446 if (!match) {
32413447 pr_err("SELinux: %s: unrecognized class %s\n",
32423448 __func__, class);
....@@ -3250,23 +3456,21 @@
32503456 goto out;
32513457
32523458 if (match->comdatum) {
3253
- rc = hashtab_map(match->comdatum->permissions.table,
3254
- get_permissions_callback, *perms);
3459
+ rc = hashtab_map(&match->comdatum->permissions.table,
3460
+ get_permissions_callback, *perms);
32553461 if (rc)
32563462 goto err;
32573463 }
32583464
3259
- rc = hashtab_map(match->permissions.table, get_permissions_callback,
3260
- *perms);
3465
+ rc = hashtab_map(&match->permissions.table, get_permissions_callback,
3466
+ *perms);
32613467 if (rc)
32623468 goto err;
32633469
32643470 out:
3265
- read_unlock(&state->ss->policy_rwlock);
32663471 return rc;
32673472
32683473 err:
3269
- read_unlock(&state->ss->policy_rwlock);
32703474 for (i = 0; i < *nperms; i++)
32713475 kfree((*perms)[i]);
32723476 kfree(*perms);
....@@ -3275,12 +3479,32 @@
32753479
32763480 int security_get_reject_unknown(struct selinux_state *state)
32773481 {
3278
- return state->ss->policydb.reject_unknown;
3482
+ struct selinux_policy *policy;
3483
+ int value;
3484
+
3485
+ if (!selinux_initialized(state))
3486
+ return 0;
3487
+
3488
+ rcu_read_lock();
3489
+ policy = rcu_dereference(state->policy);
3490
+ value = policy->policydb.reject_unknown;
3491
+ rcu_read_unlock();
3492
+ return value;
32793493 }
32803494
32813495 int security_get_allow_unknown(struct selinux_state *state)
32823496 {
3283
- return state->ss->policydb.allow_unknown;
3497
+ struct selinux_policy *policy;
3498
+ int value;
3499
+
3500
+ if (!selinux_initialized(state))
3501
+ return 0;
3502
+
3503
+ rcu_read_lock();
3504
+ policy = rcu_dereference(state->policy);
3505
+ value = policy->policydb.allow_unknown;
3506
+ rcu_read_unlock();
3507
+ return value;
32843508 }
32853509
32863510 /**
....@@ -3296,12 +3520,16 @@
32963520 int security_policycap_supported(struct selinux_state *state,
32973521 unsigned int req_cap)
32983522 {
3299
- struct policydb *policydb = &state->ss->policydb;
3523
+ struct selinux_policy *policy;
33003524 int rc;
33013525
3302
- read_lock(&state->ss->policy_rwlock);
3303
- rc = ebitmap_get_bit(&policydb->policycaps, req_cap);
3304
- read_unlock(&state->ss->policy_rwlock);
3526
+ if (!selinux_initialized(state))
3527
+ return 0;
3528
+
3529
+ rcu_read_lock();
3530
+ policy = rcu_dereference(state->policy);
3531
+ rc = ebitmap_get_bit(&policy->policydb.policycaps, req_cap);
3532
+ rcu_read_unlock();
33053533
33063534 return rc;
33073535 }
....@@ -3324,7 +3552,8 @@
33243552 int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
33253553 {
33263554 struct selinux_state *state = &selinux_state;
3327
- struct policydb *policydb = &state->ss->policydb;
3555
+ struct selinux_policy *policy;
3556
+ struct policydb *policydb;
33283557 struct selinux_audit_rule *tmprule;
33293558 struct role_datum *roledatum;
33303559 struct type_datum *typedatum;
....@@ -3334,7 +3563,7 @@
33343563
33353564 *rule = NULL;
33363565
3337
- if (!state->initialized)
3566
+ if (!selinux_initialized(state))
33383567 return -EOPNOTSUPP;
33393568
33403569 switch (field) {
....@@ -3367,15 +3596,17 @@
33673596
33683597 context_init(&tmprule->au_ctxt);
33693598
3370
- read_lock(&state->ss->policy_rwlock);
3599
+ rcu_read_lock();
3600
+ policy = rcu_dereference(state->policy);
3601
+ policydb = &policy->policydb;
33713602
3372
- tmprule->au_seqno = state->ss->latest_granting;
3603
+ tmprule->au_seqno = policy->latest_granting;
33733604
33743605 switch (field) {
33753606 case AUDIT_SUBJ_USER:
33763607 case AUDIT_OBJ_USER:
33773608 rc = -EINVAL;
3378
- userdatum = hashtab_search(policydb->p_users.table, rulestr);
3609
+ userdatum = symtab_search(&policydb->p_users, rulestr);
33793610 if (!userdatum)
33803611 goto out;
33813612 tmprule->au_ctxt.user = userdatum->value;
....@@ -3383,7 +3614,7 @@
33833614 case AUDIT_SUBJ_ROLE:
33843615 case AUDIT_OBJ_ROLE:
33853616 rc = -EINVAL;
3386
- roledatum = hashtab_search(policydb->p_roles.table, rulestr);
3617
+ roledatum = symtab_search(&policydb->p_roles, rulestr);
33873618 if (!roledatum)
33883619 goto out;
33893620 tmprule->au_ctxt.role = roledatum->value;
....@@ -3391,7 +3622,7 @@
33913622 case AUDIT_SUBJ_TYPE:
33923623 case AUDIT_OBJ_TYPE:
33933624 rc = -EINVAL;
3394
- typedatum = hashtab_search(policydb->p_types.table, rulestr);
3625
+ typedatum = symtab_search(&policydb->p_types, rulestr);
33953626 if (!typedatum)
33963627 goto out;
33973628 tmprule->au_ctxt.type = typedatum->value;
....@@ -3408,7 +3639,7 @@
34083639 }
34093640 rc = 0;
34103641 out:
3411
- read_unlock(&state->ss->policy_rwlock);
3642
+ rcu_read_unlock();
34123643
34133644 if (rc) {
34143645 selinux_audit_rule_free(tmprule);
....@@ -3445,10 +3676,10 @@
34453676 return 0;
34463677 }
34473678
3448
-int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
3449
- struct audit_context *actx)
3679
+int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
34503680 {
34513681 struct selinux_state *state = &selinux_state;
3682
+ struct selinux_policy *policy;
34523683 struct context *ctxt;
34533684 struct mls_level *level;
34543685 struct selinux_audit_rule *rule = vrule;
....@@ -3459,14 +3690,19 @@
34593690 return -ENOENT;
34603691 }
34613692
3462
- read_lock(&state->ss->policy_rwlock);
3693
+ if (!selinux_initialized(state))
3694
+ return 0;
34633695
3464
- if (rule->au_seqno < state->ss->latest_granting) {
3696
+ rcu_read_lock();
3697
+
3698
+ policy = rcu_dereference(state->policy);
3699
+
3700
+ if (rule->au_seqno < policy->latest_granting) {
34653701 match = -ESTALE;
34663702 goto out;
34673703 }
34683704
3469
- ctxt = sidtab_search(state->ss->sidtab, sid);
3705
+ ctxt = sidtab_search(policy->sidtab, sid);
34703706 if (unlikely(!ctxt)) {
34713707 WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
34723708 sid);
....@@ -3550,7 +3786,7 @@
35503786 }
35513787
35523788 out:
3553
- read_unlock(&state->ss->policy_rwlock);
3789
+ rcu_read_unlock();
35543790 return match;
35553791 }
35563792
....@@ -3628,18 +3864,24 @@
36283864 struct netlbl_lsm_secattr *secattr,
36293865 u32 *sid)
36303866 {
3631
- struct policydb *policydb = &state->ss->policydb;
3632
- struct sidtab *sidtab = state->ss->sidtab;
3867
+ struct selinux_policy *policy;
3868
+ struct policydb *policydb;
3869
+ struct sidtab *sidtab;
36333870 int rc;
36343871 struct context *ctx;
36353872 struct context ctx_new;
36363873
3637
- if (!state->initialized) {
3874
+ if (!selinux_initialized(state)) {
36383875 *sid = SECSID_NULL;
36393876 return 0;
36403877 }
36413878
3642
- read_lock(&state->ss->policy_rwlock);
3879
+retry:
3880
+ rc = 0;
3881
+ rcu_read_lock();
3882
+ policy = rcu_dereference(state->policy);
3883
+ policydb = &policy->policydb;
3884
+ sidtab = policy->sidtab;
36433885
36443886 if (secattr->flags & NETLBL_SECATTR_CACHE)
36453887 *sid = *(u32 *)secattr->cache->data;
....@@ -3662,25 +3904,26 @@
36623904 goto out;
36633905 }
36643906 rc = -EIDRM;
3665
- if (!mls_context_isvalid(policydb, &ctx_new))
3666
- goto out_free;
3907
+ if (!mls_context_isvalid(policydb, &ctx_new)) {
3908
+ ebitmap_destroy(&ctx_new.range.level[0].cat);
3909
+ goto out;
3910
+ }
36673911
3668
- rc = context_struct_to_sid(state, &ctx_new, sid);
3912
+ rc = sidtab_context_to_sid(sidtab, &ctx_new, sid);
3913
+ ebitmap_destroy(&ctx_new.range.level[0].cat);
3914
+ if (rc == -ESTALE) {
3915
+ rcu_read_unlock();
3916
+ goto retry;
3917
+ }
36693918 if (rc)
3670
- goto out_free;
3919
+ goto out;
36713920
36723921 security_netlbl_cache_add(secattr, *sid);
3673
-
3674
- ebitmap_destroy(&ctx_new.range.level[0].cat);
36753922 } else
36763923 *sid = SECSID_NULL;
36773924
3678
- read_unlock(&state->ss->policy_rwlock);
3679
- return 0;
3680
-out_free:
3681
- ebitmap_destroy(&ctx_new.range.level[0].cat);
36823925 out:
3683
- read_unlock(&state->ss->policy_rwlock);
3926
+ rcu_read_unlock();
36843927 return rc;
36853928 }
36863929
....@@ -3697,17 +3940,20 @@
36973940 int security_netlbl_sid_to_secattr(struct selinux_state *state,
36983941 u32 sid, struct netlbl_lsm_secattr *secattr)
36993942 {
3700
- struct policydb *policydb = &state->ss->policydb;
3943
+ struct selinux_policy *policy;
3944
+ struct policydb *policydb;
37013945 int rc;
37023946 struct context *ctx;
37033947
3704
- if (!state->initialized)
3948
+ if (!selinux_initialized(state))
37053949 return 0;
37063950
3707
- read_lock(&state->ss->policy_rwlock);
3951
+ rcu_read_lock();
3952
+ policy = rcu_dereference(state->policy);
3953
+ policydb = &policy->policydb;
37083954
37093955 rc = -ENOENT;
3710
- ctx = sidtab_search(state->ss->sidtab, sid);
3956
+ ctx = sidtab_search(policy->sidtab, sid);
37113957 if (ctx == NULL)
37123958 goto out;
37133959
....@@ -3722,7 +3968,7 @@
37223968 mls_export_netlbl_lvl(policydb, ctx, secattr);
37233969 rc = mls_export_netlbl_cat(policydb, ctx, secattr);
37243970 out:
3725
- read_unlock(&state->ss->policy_rwlock);
3971
+ rcu_read_unlock();
37263972 return rc;
37273973 }
37283974 #endif /* CONFIG_NETLABEL */
....@@ -3736,15 +3982,16 @@
37363982 int security_read_policy(struct selinux_state *state,
37373983 void **data, size_t *len)
37383984 {
3739
- struct policydb *policydb = &state->ss->policydb;
3985
+ struct selinux_policy *policy;
37403986 int rc;
37413987 struct policy_file fp;
37423988
3743
- if (!state->initialized)
3989
+ policy = rcu_dereference_protected(
3990
+ state->policy, lockdep_is_held(&state->policy_mutex));
3991
+ if (!policy)
37443992 return -EINVAL;
37453993
3746
- *len = security_policydb_len(state);
3747
-
3994
+ *len = policy->policydb.len;
37483995 *data = vmalloc_user(*len);
37493996 if (!*data)
37503997 return -ENOMEM;
....@@ -3752,10 +3999,7 @@
37523999 fp.data = *data;
37534000 fp.len = *len;
37544001
3755
- read_lock(&state->ss->policy_rwlock);
3756
- rc = policydb_write(policydb, &fp);
3757
- read_unlock(&state->ss->policy_rwlock);
3758
-
4002
+ rc = policydb_write(&policy->policydb, &fp);
37594003 if (rc)
37604004 return rc;
37614005