aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smack_access.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack/smack_access.c')
-rw-r--r--security/smack/smack_access.c63
1 files changed, 38 insertions, 25 deletions
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index cfa19ca125e3..58564195bb09 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -16,48 +16,42 @@
16#include "smack.h" 16#include "smack.h"
17 17
18struct smack_known smack_known_huh = { 18struct smack_known smack_known_huh = {
19 .smk_next = NULL,
20 .smk_known = "?", 19 .smk_known = "?",
21 .smk_secid = 2, 20 .smk_secid = 2,
22 .smk_cipso = NULL, 21 .smk_cipso = NULL,
23}; 22};
24 23
25struct smack_known smack_known_hat = { 24struct smack_known smack_known_hat = {
26 .smk_next = &smack_known_huh,
27 .smk_known = "^", 25 .smk_known = "^",
28 .smk_secid = 3, 26 .smk_secid = 3,
29 .smk_cipso = NULL, 27 .smk_cipso = NULL,
30}; 28};
31 29
32struct smack_known smack_known_star = { 30struct smack_known smack_known_star = {
33 .smk_next = &smack_known_hat,
34 .smk_known = "*", 31 .smk_known = "*",
35 .smk_secid = 4, 32 .smk_secid = 4,
36 .smk_cipso = NULL, 33 .smk_cipso = NULL,
37}; 34};
38 35
39struct smack_known smack_known_floor = { 36struct smack_known smack_known_floor = {
40 .smk_next = &smack_known_star,
41 .smk_known = "_", 37 .smk_known = "_",
42 .smk_secid = 5, 38 .smk_secid = 5,
43 .smk_cipso = NULL, 39 .smk_cipso = NULL,
44}; 40};
45 41
46struct smack_known smack_known_invalid = { 42struct smack_known smack_known_invalid = {
47 .smk_next = &smack_known_floor,
48 .smk_known = "", 43 .smk_known = "",
49 .smk_secid = 6, 44 .smk_secid = 6,
50 .smk_cipso = NULL, 45 .smk_cipso = NULL,
51}; 46};
52 47
53struct smack_known smack_known_web = { 48struct smack_known smack_known_web = {
54 .smk_next = &smack_known_invalid,
55 .smk_known = "@", 49 .smk_known = "@",
56 .smk_secid = 7, 50 .smk_secid = 7,
57 .smk_cipso = NULL, 51 .smk_cipso = NULL,
58}; 52};
59 53
60struct smack_known *smack_known = &smack_known_web; 54LIST_HEAD(smack_known_list);
61 55
62/* 56/*
63 * The initial value needs to be bigger than any of the 57 * The initial value needs to be bigger than any of the
@@ -87,7 +81,6 @@ static u32 smack_next_secid = 10;
87int smk_access(char *subject_label, char *object_label, int request) 81int smk_access(char *subject_label, char *object_label, int request)
88{ 82{
89 u32 may = MAY_NOT; 83 u32 may = MAY_NOT;
90 struct smk_list_entry *sp;
91 struct smack_rule *srp; 84 struct smack_rule *srp;
92 85
93 /* 86 /*
@@ -139,9 +132,8 @@ int smk_access(char *subject_label, char *object_label, int request)
139 * access (e.g. read is included in readwrite) it's 132 * access (e.g. read is included in readwrite) it's
140 * good. 133 * good.
141 */ 134 */
142 for (sp = smack_list; sp != NULL; sp = sp->smk_next) { 135 rcu_read_lock();
143 srp = &sp->smk_rule; 136 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
144
145 if (srp->smk_subject == subject_label || 137 if (srp->smk_subject == subject_label ||
146 strcmp(srp->smk_subject, subject_label) == 0) { 138 strcmp(srp->smk_subject, subject_label) == 0) {
147 if (srp->smk_object == object_label || 139 if (srp->smk_object == object_label ||
@@ -151,6 +143,7 @@ int smk_access(char *subject_label, char *object_label, int request)
151 } 143 }
152 } 144 }
153 } 145 }
146 rcu_read_unlock();
154 /* 147 /*
155 * This is a bit map operation. 148 * This is a bit map operation.
156 */ 149 */
@@ -228,14 +221,17 @@ struct smack_known *smk_import_entry(const char *string, int len)
228 221
229 mutex_lock(&smack_known_lock); 222 mutex_lock(&smack_known_lock);
230 223
231 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 224 found = 0;
232 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) 225 list_for_each_entry_rcu(skp, &smack_known_list, list) {
226 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
227 found = 1;
233 break; 228 break;
229 }
230 }
234 231
235 if (skp == NULL) { 232 if (found == 0) {
236 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); 233 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
237 if (skp != NULL) { 234 if (skp != NULL) {
238 skp->smk_next = smack_known;
239 strncpy(skp->smk_known, smack, SMK_MAXLEN); 235 strncpy(skp->smk_known, smack, SMK_MAXLEN);
240 skp->smk_secid = smack_next_secid++; 236 skp->smk_secid = smack_next_secid++;
241 skp->smk_cipso = NULL; 237 skp->smk_cipso = NULL;
@@ -244,8 +240,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
244 * Make sure that the entry is actually 240 * Make sure that the entry is actually
245 * filled before putting it on the list. 241 * filled before putting it on the list.
246 */ 242 */
247 smp_mb(); 243 list_add_rcu(&skp->list, &smack_known_list);
248 smack_known = skp;
249 } 244 }
250 } 245 }
251 246
@@ -283,14 +278,19 @@ char *smack_from_secid(const u32 secid)
283{ 278{
284 struct smack_known *skp; 279 struct smack_known *skp;
285 280
286 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 281 rcu_read_lock();
287 if (skp->smk_secid == secid) 282 list_for_each_entry_rcu(skp, &smack_known_list, list) {
283 if (skp->smk_secid == secid) {
284 rcu_read_unlock();
288 return skp->smk_known; 285 return skp->smk_known;
286 }
287 }
289 288
290 /* 289 /*
291 * If we got this far someone asked for the translation 290 * If we got this far someone asked for the translation
292 * of a secid that is not on the list. 291 * of a secid that is not on the list.
293 */ 292 */
293 rcu_read_unlock();
294 return smack_known_invalid.smk_known; 294 return smack_known_invalid.smk_known;
295} 295}
296 296
@@ -305,9 +305,14 @@ u32 smack_to_secid(const char *smack)
305{ 305{
306 struct smack_known *skp; 306 struct smack_known *skp;
307 307
308 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 308 rcu_read_lock();
309 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) 309 list_for_each_entry_rcu(skp, &smack_known_list, list) {
310 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
311 rcu_read_unlock();
310 return skp->smk_secid; 312 return skp->smk_secid;
313 }
314 }
315 rcu_read_unlock();
311 return 0; 316 return 0;
312} 317}
313 318
@@ -332,7 +337,8 @@ void smack_from_cipso(u32 level, char *cp, char *result)
332 struct smack_known *kp; 337 struct smack_known *kp;
333 char *final = NULL; 338 char *final = NULL;
334 339
335 for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) { 340 rcu_read_lock();
341 list_for_each_entry(kp, &smack_known_list, list) {
336 if (kp->smk_cipso == NULL) 342 if (kp->smk_cipso == NULL)
337 continue; 343 continue;
338 344
@@ -344,6 +350,7 @@ void smack_from_cipso(u32 level, char *cp, char *result)
344 350
345 spin_unlock_bh(&kp->smk_cipsolock); 351 spin_unlock_bh(&kp->smk_cipsolock);
346 } 352 }
353 rcu_read_unlock();
347 if (final == NULL) 354 if (final == NULL)
348 final = smack_known_huh.smk_known; 355 final = smack_known_huh.smk_known;
349 strncpy(result, final, SMK_MAXLEN); 356 strncpy(result, final, SMK_MAXLEN);
@@ -360,13 +367,19 @@ void smack_from_cipso(u32 level, char *cp, char *result)
360int smack_to_cipso(const char *smack, struct smack_cipso *cp) 367int smack_to_cipso(const char *smack, struct smack_cipso *cp)
361{ 368{
362 struct smack_known *kp; 369 struct smack_known *kp;
370 int found = 0;
363 371
364 for (kp = smack_known; kp != NULL; kp = kp->smk_next) 372 rcu_read_lock();
373 list_for_each_entry_rcu(kp, &smack_known_list, list) {
365 if (kp->smk_known == smack || 374 if (kp->smk_known == smack ||
366 strcmp(kp->smk_known, smack) == 0) 375 strcmp(kp->smk_known, smack) == 0) {
376 found = 1;
367 break; 377 break;
378 }
379 }
380 rcu_read_unlock();
368 381
369 if (kp == NULL || kp->smk_cipso == NULL) 382 if (found == 0 || kp->smk_cipso == NULL)
370 return -ENOENT; 383 return -ENOENT;
371 384
372 memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso)); 385 memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));