aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorEtienne Basset <etienne.basset@numericable.fr>2009-03-24 15:53:24 -0400
committerJames Morris <jmorris@namei.org>2009-03-25 18:17:04 -0400
commit7198e2eeb44b3fe7cc97f997824002da47a9c644 (patch)
tree4989ad0f9727ac4b861189217760517aa8beea43 /security/smack
parent703a3cd72817e99201cef84a8a7aecc60b2b3581 (diff)
smack: convert smack to standard linux lists
the following patch (on top of 2.6.29) converts Smack lists to standard linux lists Please review and consider for inclusion in 2.6.30-rc regards, Etienne Signed-off-by: Etienne Basset <etienne.basset@numericable.fr> Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h28
-rw-r--r--security/smack/smack_access.c63
-rw-r--r--security/smack/smack_lsm.c19
-rw-r--r--security/smack/smackfs.c180
4 files changed, 168 insertions, 122 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index b79582e4fbfd..64164f8fde70 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -18,6 +18,8 @@
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/in.h> 19#include <linux/in.h>
20#include <net/netlabel.h> 20#include <net/netlabel.h>
21#include <linux/list.h>
22#include <linux/rculist.h>
21 23
22/* 24/*
23 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is 25 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -59,17 +61,10 @@ struct inode_smack {
59 * A label access rule. 61 * A label access rule.
60 */ 62 */
61struct smack_rule { 63struct smack_rule {
62 char *smk_subject; 64 struct list_head list;
63 char *smk_object; 65 char *smk_subject;
64 int smk_access; 66 char *smk_object;
65}; 67 int smk_access;
66
67/*
68 * An entry in the table of permitted label accesses.
69 */
70struct smk_list_entry {
71 struct smk_list_entry *smk_next;
72 struct smack_rule smk_rule;
73}; 68};
74 69
75/* 70/*
@@ -85,7 +80,7 @@ struct smack_cipso {
85 * An entry in the table identifying hosts. 80 * An entry in the table identifying hosts.
86 */ 81 */
87struct smk_netlbladdr { 82struct smk_netlbladdr {
88 struct smk_netlbladdr *smk_next; 83 struct list_head list;
89 struct sockaddr_in smk_host; /* network address */ 84 struct sockaddr_in smk_host; /* network address */
90 struct in_addr smk_mask; /* network mask */ 85 struct in_addr smk_mask; /* network mask */
91 char *smk_label; /* label */ 86 char *smk_label; /* label */
@@ -113,7 +108,7 @@ struct smk_netlbladdr {
113 * the cipso direct mapping in used internally. 108 * the cipso direct mapping in used internally.
114 */ 109 */
115struct smack_known { 110struct smack_known {
116 struct smack_known *smk_next; 111 struct list_head list;
117 char smk_known[SMK_LABELLEN]; 112 char smk_known[SMK_LABELLEN];
118 u32 smk_secid; 113 u32 smk_secid;
119 struct smack_cipso *smk_cipso; 114 struct smack_cipso *smk_cipso;
@@ -206,7 +201,6 @@ extern int smack_cipso_direct;
206extern char *smack_net_ambient; 201extern char *smack_net_ambient;
207extern char *smack_onlycap; 202extern char *smack_onlycap;
208 203
209extern struct smack_known *smack_known;
210extern struct smack_known smack_known_floor; 204extern struct smack_known smack_known_floor;
211extern struct smack_known smack_known_hat; 205extern struct smack_known smack_known_hat;
212extern struct smack_known smack_known_huh; 206extern struct smack_known smack_known_huh;
@@ -214,8 +208,10 @@ extern struct smack_known smack_known_invalid;
214extern struct smack_known smack_known_star; 208extern struct smack_known smack_known_star;
215extern struct smack_known smack_known_web; 209extern struct smack_known smack_known_web;
216 210
217extern struct smk_list_entry *smack_list; 211extern struct list_head smack_known_list;
218extern struct smk_netlbladdr *smack_netlbladdrs; 212extern struct list_head smack_rule_list;
213extern struct list_head smk_netlbladdr_list;
214
219extern struct security_operations smack_ops; 215extern struct security_operations smack_ops;
220 216
221/* 217/*
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));
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 84b62b5e9e2c..fd20d15f5b9a 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1508,7 +1508,8 @@ static char *smack_host_label(struct sockaddr_in *sip)
1508 if (siap->s_addr == 0) 1508 if (siap->s_addr == 0)
1509 return NULL; 1509 return NULL;
1510 1510
1511 for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) { 1511 rcu_read_lock();
1512 list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) {
1512 /* 1513 /*
1513 * we break after finding the first match because 1514 * we break after finding the first match because
1514 * the list is sorted from longest to shortest mask 1515 * the list is sorted from longest to shortest mask
@@ -1516,10 +1517,11 @@ static char *smack_host_label(struct sockaddr_in *sip)
1516 */ 1517 */
1517 if ((&snp->smk_host.sin_addr)->s_addr == 1518 if ((&snp->smk_host.sin_addr)->s_addr ==
1518 (siap->s_addr & (&snp->smk_mask)->s_addr)) { 1519 (siap->s_addr & (&snp->smk_mask)->s_addr)) {
1520 rcu_read_unlock();
1519 return snp->smk_label; 1521 return snp->smk_label;
1520 } 1522 }
1521 } 1523 }
1522 1524 rcu_read_unlock();
1523 return NULL; 1525 return NULL;
1524} 1526}
1525 1527
@@ -2930,6 +2932,17 @@ struct security_operations smack_ops = {
2930 .release_secctx = smack_release_secctx, 2932 .release_secctx = smack_release_secctx,
2931}; 2933};
2932 2934
2935
2936static __init void init_smack_know_list(void)
2937{
2938 list_add(&smack_known_huh.list, &smack_known_list);
2939 list_add(&smack_known_hat.list, &smack_known_list);
2940 list_add(&smack_known_star.list, &smack_known_list);
2941 list_add(&smack_known_floor.list, &smack_known_list);
2942 list_add(&smack_known_invalid.list, &smack_known_list);
2943 list_add(&smack_known_web.list, &smack_known_list);
2944}
2945
2933/** 2946/**
2934 * smack_init - initialize the smack system 2947 * smack_init - initialize the smack system
2935 * 2948 *
@@ -2950,6 +2963,8 @@ static __init int smack_init(void)
2950 cred = (struct cred *) current->cred; 2963 cred = (struct cred *) current->cred;
2951 cred->security = &smack_known_floor.smk_known; 2964 cred->security = &smack_known_floor.smk_known;
2952 2965
2966 /* initilize the smack_know_list */
2967 init_smack_know_list();
2953 /* 2968 /*
2954 * Initialize locks 2969 * Initialize locks
2955 */ 2970 */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index a1b57e4dba3e..856c8a287523 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -80,10 +80,11 @@ char *smack_onlycap;
80 * Packets are sent there unlabeled, but only from tasks that 80 * Packets are sent there unlabeled, but only from tasks that
81 * can write to the specified label. 81 * can write to the specified label.
82 */ 82 */
83struct smk_netlbladdr *smack_netlbladdrs; 83
84LIST_HEAD(smk_netlbladdr_list);
85LIST_HEAD(smack_rule_list);
84 86
85static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 87static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
86struct smk_list_entry *smack_list;
87 88
88#define SEQ_READ_FINISHED 1 89#define SEQ_READ_FINISHED 1
89 90
@@ -134,24 +135,27 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
134{ 135{
135 if (*pos == SEQ_READ_FINISHED) 136 if (*pos == SEQ_READ_FINISHED)
136 return NULL; 137 return NULL;
137 138 if (list_empty(&smack_rule_list))
138 return smack_list; 139 return NULL;
140 return smack_rule_list.next;
139} 141}
140 142
141static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) 143static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
142{ 144{
143 struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next; 145 struct list_head *list = v;
144 146
145 if (skp == NULL) 147 if (list_is_last(list, &smack_rule_list)) {
146 *pos = SEQ_READ_FINISHED; 148 *pos = SEQ_READ_FINISHED;
147 149 return NULL;
148 return skp; 150 }
151 return list->next;
149} 152}
150 153
151static int load_seq_show(struct seq_file *s, void *v) 154static int load_seq_show(struct seq_file *s, void *v)
152{ 155{
153 struct smk_list_entry *slp = (struct smk_list_entry *) v; 156 struct list_head *list = v;
154 struct smack_rule *srp = &slp->smk_rule; 157 struct smack_rule *srp =
158 list_entry(list, struct smack_rule, list);
155 159
156 seq_printf(s, "%s %s", (char *)srp->smk_subject, 160 seq_printf(s, "%s %s", (char *)srp->smk_subject,
157 (char *)srp->smk_object); 161 (char *)srp->smk_object);
@@ -212,32 +216,23 @@ static int smk_open_load(struct inode *inode, struct file *file)
212 */ 216 */
213static int smk_set_access(struct smack_rule *srp) 217static int smk_set_access(struct smack_rule *srp)
214{ 218{
215 struct smk_list_entry *sp; 219 struct smack_rule *sp;
216 struct smk_list_entry *newp;
217 int ret = 0; 220 int ret = 0;
218 221 int found;
219 mutex_lock(&smack_list_lock); 222 mutex_lock(&smack_list_lock);
220 223
221 for (sp = smack_list; sp != NULL; sp = sp->smk_next) 224 found = 0;
222 if (sp->smk_rule.smk_subject == srp->smk_subject && 225 list_for_each_entry_rcu(sp, &smack_rule_list, list) {
223 sp->smk_rule.smk_object == srp->smk_object) { 226 if (sp->smk_subject == srp->smk_subject &&
224 sp->smk_rule.smk_access = srp->smk_access; 227 sp->smk_object == srp->smk_object) {
228 found = 1;
229 sp->smk_access = srp->smk_access;
225 break; 230 break;
226 } 231 }
227
228 if (sp == NULL) {
229 newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL);
230 if (newp == NULL) {
231 ret = -ENOMEM;
232 goto out;
233 }
234
235 newp->smk_rule = *srp;
236 newp->smk_next = smack_list;
237 smack_list = newp;
238 } 232 }
233 if (found == 0)
234 list_add_rcu(&srp->list, &smack_rule_list);
239 235
240out:
241 mutex_unlock(&smack_list_lock); 236 mutex_unlock(&smack_list_lock);
242 237
243 return ret; 238 return ret;
@@ -261,7 +256,7 @@ out:
261static ssize_t smk_write_load(struct file *file, const char __user *buf, 256static ssize_t smk_write_load(struct file *file, const char __user *buf,
262 size_t count, loff_t *ppos) 257 size_t count, loff_t *ppos)
263{ 258{
264 struct smack_rule rule; 259 struct smack_rule *rule;
265 char *data; 260 char *data;
266 int rc = -EINVAL; 261 int rc = -EINVAL;
267 262
@@ -272,9 +267,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
272 */ 267 */
273 if (!capable(CAP_MAC_ADMIN)) 268 if (!capable(CAP_MAC_ADMIN))
274 return -EPERM; 269 return -EPERM;
275 if (*ppos != 0) 270
276 return -EINVAL; 271 if (*ppos != 0 || count != SMK_LOADLEN)
277 if (count != SMK_LOADLEN)
278 return -EINVAL; 272 return -EINVAL;
279 273
280 data = kzalloc(count, GFP_KERNEL); 274 data = kzalloc(count, GFP_KERNEL);
@@ -286,25 +280,31 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
286 goto out; 280 goto out;
287 } 281 }
288 282
289 rule.smk_subject = smk_import(data, 0); 283 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
290 if (rule.smk_subject == NULL) 284 if (rule == NULL) {
285 rc = -ENOMEM;
291 goto out; 286 goto out;
287 }
292 288
293 rule.smk_object = smk_import(data + SMK_LABELLEN, 0); 289 rule->smk_subject = smk_import(data, 0);
294 if (rule.smk_object == NULL) 290 if (rule->smk_subject == NULL)
295 goto out; 291 goto out_free_rule;
296 292
297 rule.smk_access = 0; 293 rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
294 if (rule->smk_object == NULL)
295 goto out_free_rule;
296
297 rule->smk_access = 0;
298 298
299 switch (data[SMK_LABELLEN + SMK_LABELLEN]) { 299 switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
300 case '-': 300 case '-':
301 break; 301 break;
302 case 'r': 302 case 'r':
303 case 'R': 303 case 'R':
304 rule.smk_access |= MAY_READ; 304 rule->smk_access |= MAY_READ;
305 break; 305 break;
306 default: 306 default:
307 goto out; 307 goto out_free_rule;
308 } 308 }
309 309
310 switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { 310 switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
@@ -312,10 +312,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
312 break; 312 break;
313 case 'w': 313 case 'w':
314 case 'W': 314 case 'W':
315 rule.smk_access |= MAY_WRITE; 315 rule->smk_access |= MAY_WRITE;
316 break; 316 break;
317 default: 317 default:
318 goto out; 318 goto out_free_rule;
319 } 319 }
320 320
321 switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { 321 switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
@@ -323,10 +323,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
323 break; 323 break;
324 case 'x': 324 case 'x':
325 case 'X': 325 case 'X':
326 rule.smk_access |= MAY_EXEC; 326 rule->smk_access |= MAY_EXEC;
327 break; 327 break;
328 default: 328 default:
329 goto out; 329 goto out_free_rule;
330 } 330 }
331 331
332 switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { 332 switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
@@ -334,17 +334,20 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
334 break; 334 break;
335 case 'a': 335 case 'a':
336 case 'A': 336 case 'A':
337 rule.smk_access |= MAY_APPEND; 337 rule->smk_access |= MAY_APPEND;
338 break; 338 break;
339 default: 339 default:
340 goto out; 340 goto out_free_rule;
341 } 341 }
342 342
343 rc = smk_set_access(&rule); 343 rc = smk_set_access(rule);
344 344
345 if (!rc) 345 if (!rc)
346 rc = count; 346 rc = count;
347 goto out;
347 348
349out_free_rule:
350 kfree(rule);
348out: 351out:
349 kfree(data); 352 kfree(data);
350 return rc; 353 return rc;
@@ -433,24 +436,26 @@ static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
433{ 436{
434 if (*pos == SEQ_READ_FINISHED) 437 if (*pos == SEQ_READ_FINISHED)
435 return NULL; 438 return NULL;
439 if (list_empty(&smack_known_list))
440 return NULL;
436 441
437 return smack_known; 442 return smack_known_list.next;
438} 443}
439 444
440static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) 445static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
441{ 446{
442 struct smack_known *skp = ((struct smack_known *) v)->smk_next; 447 struct list_head *list = v;
443 448
444 /* 449 /*
445 * Omit labels with no associated cipso value 450 * labels with no associated cipso value wont be printed
451 * in cipso_seq_show
446 */ 452 */
447 while (skp != NULL && !skp->smk_cipso) 453 if (list_is_last(list, &smack_known_list)) {
448 skp = skp->smk_next;
449
450 if (skp == NULL)
451 *pos = SEQ_READ_FINISHED; 454 *pos = SEQ_READ_FINISHED;
455 return NULL;
456 }
452 457
453 return skp; 458 return list->next;
454} 459}
455 460
456/* 461/*
@@ -459,7 +464,9 @@ static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
459 */ 464 */
460static int cipso_seq_show(struct seq_file *s, void *v) 465static int cipso_seq_show(struct seq_file *s, void *v)
461{ 466{
462 struct smack_known *skp = (struct smack_known *) v; 467 struct list_head *list = v;
468 struct smack_known *skp =
469 list_entry(list, struct smack_known, list);
463 struct smack_cipso *scp = skp->smk_cipso; 470 struct smack_cipso *scp = skp->smk_cipso;
464 char *cbp; 471 char *cbp;
465 char sep = '/'; 472 char sep = '/';
@@ -638,18 +645,21 @@ static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
638{ 645{
639 if (*pos == SEQ_READ_FINISHED) 646 if (*pos == SEQ_READ_FINISHED)
640 return NULL; 647 return NULL;
641 648 if (list_empty(&smk_netlbladdr_list))
642 return smack_netlbladdrs; 649 return NULL;
650 return smk_netlbladdr_list.next;
643} 651}
644 652
645static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) 653static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
646{ 654{
647 struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next; 655 struct list_head *list = v;
648 656
649 if (skp == NULL) 657 if (list_is_last(list, &smk_netlbladdr_list)) {
650 *pos = SEQ_READ_FINISHED; 658 *pos = SEQ_READ_FINISHED;
659 return NULL;
660 }
651 661
652 return skp; 662 return list->next;
653} 663}
654#define BEBITS (sizeof(__be32) * 8) 664#define BEBITS (sizeof(__be32) * 8)
655 665
@@ -658,7 +668,9 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
658 */ 668 */
659static int netlbladdr_seq_show(struct seq_file *s, void *v) 669static int netlbladdr_seq_show(struct seq_file *s, void *v)
660{ 670{
661 struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v; 671 struct list_head *list = v;
672 struct smk_netlbladdr *skp =
673 list_entry(list, struct smk_netlbladdr, list);
662 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; 674 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
663 int maskn; 675 int maskn;
664 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr); 676 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
@@ -702,30 +714,36 @@ static int smk_open_netlbladdr(struct inode *inode, struct file *file)
702 * 714 *
703 * This helper insert netlabel in the smack_netlbladdrs list 715 * This helper insert netlabel in the smack_netlbladdrs list
704 * sorted by netmask length (longest to smallest) 716 * sorted by netmask length (longest to smallest)
717 * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
718 *
705 */ 719 */
706static void smk_netlbladdr_insert(struct smk_netlbladdr *new) 720static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
707{ 721{
708 struct smk_netlbladdr *m; 722 struct smk_netlbladdr *m, *m_next;
709 723
710 if (smack_netlbladdrs == NULL) { 724 if (list_empty(&smk_netlbladdr_list)) {
711 smack_netlbladdrs = new; 725 list_add_rcu(&new->list, &smk_netlbladdr_list);
712 return; 726 return;
713 } 727 }
714 728
729 m = list_entry(rcu_dereference(smk_netlbladdr_list.next),
730 struct smk_netlbladdr, list);
731
715 /* the comparison '>' is a bit hacky, but works */ 732 /* the comparison '>' is a bit hacky, but works */
716 if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) { 733 if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
717 new->smk_next = smack_netlbladdrs; 734 list_add_rcu(&new->list, &smk_netlbladdr_list);
718 smack_netlbladdrs = new;
719 return; 735 return;
720 } 736 }
721 for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) { 737
722 if (m->smk_next == NULL) { 738 list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
723 m->smk_next = new; 739 if (list_is_last(&m->list, &smk_netlbladdr_list)) {
740 list_add_rcu(&new->list, &m->list);
724 return; 741 return;
725 } 742 }
726 if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) { 743 m_next = list_entry(rcu_dereference(m->list.next),
727 new->smk_next = m->smk_next; 744 struct smk_netlbladdr, list);
728 m->smk_next = new; 745 if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
746 list_add_rcu(&new->list, &m->list);
729 return; 747 return;
730 } 748 }
731 } 749 }
@@ -755,6 +773,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
755 struct netlbl_audit audit_info; 773 struct netlbl_audit audit_info;
756 struct in_addr mask; 774 struct in_addr mask;
757 unsigned int m; 775 unsigned int m;
776 int found;
758 u32 mask_bits = (1<<31); 777 u32 mask_bits = (1<<31);
759 __be32 nsa; 778 __be32 nsa;
760 u32 temp_mask; 779 u32 temp_mask;
@@ -808,14 +827,17 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
808 827
809 nsa = newname.sin_addr.s_addr; 828 nsa = newname.sin_addr.s_addr;
810 /* try to find if the prefix is already in the list */ 829 /* try to find if the prefix is already in the list */
811 for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next) 830 found = 0;
831 list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
812 if (skp->smk_host.sin_addr.s_addr == nsa && 832 if (skp->smk_host.sin_addr.s_addr == nsa &&
813 skp->smk_mask.s_addr == mask.s_addr) 833 skp->smk_mask.s_addr == mask.s_addr) {
834 found = 1;
814 break; 835 break;
815 836 }
837 }
816 smk_netlabel_audit_set(&audit_info); 838 smk_netlabel_audit_set(&audit_info);
817 839
818 if (skp == NULL) { 840 if (found == 0) {
819 skp = kzalloc(sizeof(*skp), GFP_KERNEL); 841 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
820 if (skp == NULL) 842 if (skp == NULL)
821 rc = -ENOMEM; 843 rc = -ENOMEM;