diff options
Diffstat (limited to 'security/smack/smack_access.c')
-rw-r--r-- | security/smack/smack_access.c | 63 |
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 | ||
18 | struct smack_known smack_known_huh = { | 18 | struct 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 | ||
25 | struct smack_known smack_known_hat = { | 24 | struct 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 | ||
32 | struct smack_known smack_known_star = { | 30 | struct 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 | ||
39 | struct smack_known smack_known_floor = { | 36 | struct 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 | ||
46 | struct smack_known smack_known_invalid = { | 42 | struct 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 | ||
53 | struct smack_known smack_known_web = { | 48 | struct 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 | ||
60 | struct smack_known *smack_known = &smack_known_web; | 54 | LIST_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; | |||
87 | int smk_access(char *subject_label, char *object_label, int request) | 81 | int 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) | |||
360 | int smack_to_cipso(const char *smack, struct smack_cipso *cp) | 367 | int 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)); |