Skip to content

Commit 7198e2e

Browse files
ccie6798James Morris
authored andcommitted
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>
1 parent 703a3cd commit 7198e2e

File tree

4 files changed

+168
-122
lines changed

4 files changed

+168
-122
lines changed

security/smack/smack.h

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <linux/security.h>
1919
#include <linux/in.h>
2020
#include <net/netlabel.h>
21+
#include <linux/list.h>
22+
#include <linux/rculist.h>
2123

2224
/*
2325
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -59,17 +61,10 @@ struct inode_smack {
5961
* A label access rule.
6062
*/
6163
struct smack_rule {
62-
char *smk_subject;
63-
char *smk_object;
64-
int smk_access;
65-
};
66-
67-
/*
68-
* An entry in the table of permitted label accesses.
69-
*/
70-
struct smk_list_entry {
71-
struct smk_list_entry *smk_next;
72-
struct smack_rule smk_rule;
64+
struct list_head list;
65+
char *smk_subject;
66+
char *smk_object;
67+
int smk_access;
7368
};
7469

7570
/*
@@ -85,7 +80,7 @@ struct smack_cipso {
8580
* An entry in the table identifying hosts.
8681
*/
8782
struct smk_netlbladdr {
88-
struct smk_netlbladdr *smk_next;
83+
struct list_head list;
8984
struct sockaddr_in smk_host; /* network address */
9085
struct in_addr smk_mask; /* network mask */
9186
char *smk_label; /* label */
@@ -113,7 +108,7 @@ struct smk_netlbladdr {
113108
* the cipso direct mapping in used internally.
114109
*/
115110
struct smack_known {
116-
struct smack_known *smk_next;
111+
struct list_head list;
117112
char smk_known[SMK_LABELLEN];
118113
u32 smk_secid;
119114
struct smack_cipso *smk_cipso;
@@ -206,16 +201,17 @@ extern int smack_cipso_direct;
206201
extern char *smack_net_ambient;
207202
extern char *smack_onlycap;
208203

209-
extern struct smack_known *smack_known;
210204
extern struct smack_known smack_known_floor;
211205
extern struct smack_known smack_known_hat;
212206
extern struct smack_known smack_known_huh;
213207
extern struct smack_known smack_known_invalid;
214208
extern struct smack_known smack_known_star;
215209
extern struct smack_known smack_known_web;
216210

217-
extern struct smk_list_entry *smack_list;
218-
extern struct smk_netlbladdr *smack_netlbladdrs;
211+
extern struct list_head smack_known_list;
212+
extern struct list_head smack_rule_list;
213+
extern struct list_head smk_netlbladdr_list;
214+
219215
extern struct security_operations smack_ops;
220216

221217
/*

security/smack/smack_access.c

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,48 +16,42 @@
1616
#include "smack.h"
1717

1818
struct smack_known smack_known_huh = {
19-
.smk_next = NULL,
2019
.smk_known = "?",
2120
.smk_secid = 2,
2221
.smk_cipso = NULL,
2322
};
2423

2524
struct smack_known smack_known_hat = {
26-
.smk_next = &smack_known_huh,
2725
.smk_known = "^",
2826
.smk_secid = 3,
2927
.smk_cipso = NULL,
3028
};
3129

3230
struct smack_known smack_known_star = {
33-
.smk_next = &smack_known_hat,
3431
.smk_known = "*",
3532
.smk_secid = 4,
3633
.smk_cipso = NULL,
3734
};
3835

3936
struct smack_known smack_known_floor = {
40-
.smk_next = &smack_known_star,
4137
.smk_known = "_",
4238
.smk_secid = 5,
4339
.smk_cipso = NULL,
4440
};
4541

4642
struct smack_known smack_known_invalid = {
47-
.smk_next = &smack_known_floor,
4843
.smk_known = "",
4944
.smk_secid = 6,
5045
.smk_cipso = NULL,
5146
};
5247

5348
struct smack_known smack_known_web = {
54-
.smk_next = &smack_known_invalid,
5549
.smk_known = "@",
5650
.smk_secid = 7,
5751
.smk_cipso = NULL,
5852
};
5953

60-
struct smack_known *smack_known = &smack_known_web;
54+
LIST_HEAD(smack_known_list);
6155

6256
/*
6357
* The initial value needs to be bigger than any of the
@@ -87,7 +81,6 @@ static u32 smack_next_secid = 10;
8781
int smk_access(char *subject_label, char *object_label, int request)
8882
{
8983
u32 may = MAY_NOT;
90-
struct smk_list_entry *sp;
9184
struct smack_rule *srp;
9285

9386
/*
@@ -139,9 +132,8 @@ int smk_access(char *subject_label, char *object_label, int request)
139132
* access (e.g. read is included in readwrite) it's
140133
* good.
141134
*/
142-
for (sp = smack_list; sp != NULL; sp = sp->smk_next) {
143-
srp = &sp->smk_rule;
144-
135+
rcu_read_lock();
136+
list_for_each_entry_rcu(srp, &smack_rule_list, list) {
145137
if (srp->smk_subject == subject_label ||
146138
strcmp(srp->smk_subject, subject_label) == 0) {
147139
if (srp->smk_object == object_label ||
@@ -151,6 +143,7 @@ int smk_access(char *subject_label, char *object_label, int request)
151143
}
152144
}
153145
}
146+
rcu_read_unlock();
154147
/*
155148
* This is a bit map operation.
156149
*/
@@ -228,14 +221,17 @@ struct smack_known *smk_import_entry(const char *string, int len)
228221

229222
mutex_lock(&smack_known_lock);
230223

231-
for (skp = smack_known; skp != NULL; skp = skp->smk_next)
232-
if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
224+
found = 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;
233228
break;
229+
}
230+
}
234231

235-
if (skp == NULL) {
232+
if (found == 0) {
236233
skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
237234
if (skp != NULL) {
238-
skp->smk_next = smack_known;
239235
strncpy(skp->smk_known, smack, SMK_MAXLEN);
240236
skp->smk_secid = smack_next_secid++;
241237
skp->smk_cipso = NULL;
@@ -244,8 +240,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
244240
* Make sure that the entry is actually
245241
* filled before putting it on the list.
246242
*/
247-
smp_mb();
248-
smack_known = skp;
243+
list_add_rcu(&skp->list, &smack_known_list);
249244
}
250245
}
251246

@@ -283,14 +278,19 @@ char *smack_from_secid(const u32 secid)
283278
{
284279
struct smack_known *skp;
285280

286-
for (skp = smack_known; skp != NULL; skp = skp->smk_next)
287-
if (skp->smk_secid == secid)
281+
rcu_read_lock();
282+
list_for_each_entry_rcu(skp, &smack_known_list, list) {
283+
if (skp->smk_secid == secid) {
284+
rcu_read_unlock();
288285
return skp->smk_known;
286+
}
287+
}
289288

290289
/*
291290
* If we got this far someone asked for the translation
292291
* of a secid that is not on the list.
293292
*/
293+
rcu_read_unlock();
294294
return smack_known_invalid.smk_known;
295295
}
296296

@@ -305,9 +305,14 @@ u32 smack_to_secid(const char *smack)
305305
{
306306
struct smack_known *skp;
307307

308-
for (skp = smack_known; skp != NULL; skp = skp->smk_next)
309-
if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
308+
rcu_read_lock();
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();
310312
return skp->smk_secid;
313+
}
314+
}
315+
rcu_read_unlock();
311316
return 0;
312317
}
313318

@@ -332,7 +337,8 @@ void smack_from_cipso(u32 level, char *cp, char *result)
332337
struct smack_known *kp;
333338
char *final = NULL;
334339

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) {
336342
if (kp->smk_cipso == NULL)
337343
continue;
338344

@@ -344,6 +350,7 @@ void smack_from_cipso(u32 level, char *cp, char *result)
344350

345351
spin_unlock_bh(&kp->smk_cipsolock);
346352
}
353+
rcu_read_unlock();
347354
if (final == NULL)
348355
final = smack_known_huh.smk_known;
349356
strncpy(result, final, SMK_MAXLEN);
@@ -360,13 +367,19 @@ void smack_from_cipso(u32 level, char *cp, char *result)
360367
int smack_to_cipso(const char *smack, struct smack_cipso *cp)
361368
{
362369
struct smack_known *kp;
370+
int found = 0;
363371

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) {
365374
if (kp->smk_known == smack ||
366-
strcmp(kp->smk_known, smack) == 0)
375+
strcmp(kp->smk_known, smack) == 0) {
376+
found = 1;
367377
break;
378+
}
379+
}
380+
rcu_read_unlock();
368381

369-
if (kp == NULL || kp->smk_cipso == NULL)
382+
if (found == 0 || kp->smk_cipso == NULL)
370383
return -ENOENT;
371384

372385
memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));

security/smack/smack_lsm.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,18 +1508,20 @@ static char *smack_host_label(struct sockaddr_in *sip)
15081508
if (siap->s_addr == 0)
15091509
return NULL;
15101510

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) {
15121513
/*
15131514
* we break after finding the first match because
15141515
* the list is sorted from longest to shortest mask
15151516
* so we have found the most specific match
15161517
*/
15171518
if ((&snp->smk_host.sin_addr)->s_addr ==
15181519
(siap->s_addr & (&snp->smk_mask)->s_addr)) {
1520+
rcu_read_unlock();
15191521
return snp->smk_label;
15201522
}
15211523
}
1522-
1524+
rcu_read_unlock();
15231525
return NULL;
15241526
}
15251527

@@ -2930,6 +2932,17 @@ struct security_operations smack_ops = {
29302932
.release_secctx = smack_release_secctx,
29312933
};
29322934

2935+
2936+
static __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+
29332946
/**
29342947
* smack_init - initialize the smack system
29352948
*
@@ -2950,6 +2963,8 @@ static __init int smack_init(void)
29502963
cred = (struct cred *) current->cred;
29512964
cred->security = &smack_known_floor.smk_known;
29522965

2966+
/* initilize the smack_know_list */
2967+
init_smack_know_list();
29532968
/*
29542969
* Initialize locks
29552970
*/

0 commit comments

Comments
 (0)