Skip to content

Commit

Permalink
smack: convert smack to standard linux lists
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Casey Schaufler <[email protected]>
  • Loading branch information
ccie6798 authored and James Morris committed Mar 25, 2009
1 parent 703a3cd commit 7198e2e
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 122 deletions.
28 changes: 12 additions & 16 deletions security/smack/smack.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <linux/security.h>
#include <linux/in.h>
#include <net/netlabel.h>
#include <linux/list.h>
#include <linux/rculist.h>

/*
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
Expand Down Expand Up @@ -59,17 +61,10 @@ struct inode_smack {
* A label access rule.
*/
struct smack_rule {
char *smk_subject;
char *smk_object;
int smk_access;
};

/*
* An entry in the table of permitted label accesses.
*/
struct smk_list_entry {
struct smk_list_entry *smk_next;
struct smack_rule smk_rule;
struct list_head list;
char *smk_subject;
char *smk_object;
int smk_access;
};

/*
Expand All @@ -85,7 +80,7 @@ struct smack_cipso {
* An entry in the table identifying hosts.
*/
struct smk_netlbladdr {
struct smk_netlbladdr *smk_next;
struct list_head list;
struct sockaddr_in smk_host; /* network address */
struct in_addr smk_mask; /* network mask */
char *smk_label; /* label */
Expand Down Expand Up @@ -113,7 +108,7 @@ struct smk_netlbladdr {
* the cipso direct mapping in used internally.
*/
struct smack_known {
struct smack_known *smk_next;
struct list_head list;
char smk_known[SMK_LABELLEN];
u32 smk_secid;
struct smack_cipso *smk_cipso;
Expand Down Expand Up @@ -206,16 +201,17 @@ extern int smack_cipso_direct;
extern char *smack_net_ambient;
extern char *smack_onlycap;

extern struct smack_known *smack_known;
extern struct smack_known smack_known_floor;
extern struct smack_known smack_known_hat;
extern struct smack_known smack_known_huh;
extern struct smack_known smack_known_invalid;
extern struct smack_known smack_known_star;
extern struct smack_known smack_known_web;

extern struct smk_list_entry *smack_list;
extern struct smk_netlbladdr *smack_netlbladdrs;
extern struct list_head smack_known_list;
extern struct list_head smack_rule_list;
extern struct list_head smk_netlbladdr_list;

extern struct security_operations smack_ops;

/*
Expand Down
63 changes: 38 additions & 25 deletions security/smack/smack_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,42 @@
#include "smack.h"

struct smack_known smack_known_huh = {
.smk_next = NULL,
.smk_known = "?",
.smk_secid = 2,
.smk_cipso = NULL,
};

struct smack_known smack_known_hat = {
.smk_next = &smack_known_huh,
.smk_known = "^",
.smk_secid = 3,
.smk_cipso = NULL,
};

struct smack_known smack_known_star = {
.smk_next = &smack_known_hat,
.smk_known = "*",
.smk_secid = 4,
.smk_cipso = NULL,
};

struct smack_known smack_known_floor = {
.smk_next = &smack_known_star,
.smk_known = "_",
.smk_secid = 5,
.smk_cipso = NULL,
};

struct smack_known smack_known_invalid = {
.smk_next = &smack_known_floor,
.smk_known = "",
.smk_secid = 6,
.smk_cipso = NULL,
};

struct smack_known smack_known_web = {
.smk_next = &smack_known_invalid,
.smk_known = "@",
.smk_secid = 7,
.smk_cipso = NULL,
};

struct smack_known *smack_known = &smack_known_web;
LIST_HEAD(smack_known_list);

/*
* The initial value needs to be bigger than any of the
Expand Down Expand Up @@ -87,7 +81,6 @@ static u32 smack_next_secid = 10;
int smk_access(char *subject_label, char *object_label, int request)
{
u32 may = MAY_NOT;
struct smk_list_entry *sp;
struct smack_rule *srp;

/*
Expand Down Expand Up @@ -139,9 +132,8 @@ int smk_access(char *subject_label, char *object_label, int request)
* access (e.g. read is included in readwrite) it's
* good.
*/
for (sp = smack_list; sp != NULL; sp = sp->smk_next) {
srp = &sp->smk_rule;

rcu_read_lock();
list_for_each_entry_rcu(srp, &smack_rule_list, list) {
if (srp->smk_subject == subject_label ||
strcmp(srp->smk_subject, subject_label) == 0) {
if (srp->smk_object == object_label ||
Expand All @@ -151,6 +143,7 @@ int smk_access(char *subject_label, char *object_label, int request)
}
}
}
rcu_read_unlock();
/*
* This is a bit map operation.
*/
Expand Down Expand Up @@ -228,14 +221,17 @@ struct smack_known *smk_import_entry(const char *string, int len)

mutex_lock(&smack_known_lock);

for (skp = smack_known; skp != NULL; skp = skp->smk_next)
if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
found = 0;
list_for_each_entry_rcu(skp, &smack_known_list, list) {
if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
found = 1;
break;
}
}

if (skp == NULL) {
if (found == 0) {
skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
if (skp != NULL) {
skp->smk_next = smack_known;
strncpy(skp->smk_known, smack, SMK_MAXLEN);
skp->smk_secid = smack_next_secid++;
skp->smk_cipso = NULL;
Expand All @@ -244,8 +240,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
* Make sure that the entry is actually
* filled before putting it on the list.
*/
smp_mb();
smack_known = skp;
list_add_rcu(&skp->list, &smack_known_list);
}
}

Expand Down Expand Up @@ -283,14 +278,19 @@ char *smack_from_secid(const u32 secid)
{
struct smack_known *skp;

for (skp = smack_known; skp != NULL; skp = skp->smk_next)
if (skp->smk_secid == secid)
rcu_read_lock();
list_for_each_entry_rcu(skp, &smack_known_list, list) {
if (skp->smk_secid == secid) {
rcu_read_unlock();
return skp->smk_known;
}
}

/*
* If we got this far someone asked for the translation
* of a secid that is not on the list.
*/
rcu_read_unlock();
return smack_known_invalid.smk_known;
}

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

for (skp = smack_known; skp != NULL; skp = skp->smk_next)
if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
rcu_read_lock();
list_for_each_entry_rcu(skp, &smack_known_list, list) {
if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
rcu_read_unlock();
return skp->smk_secid;
}
}
rcu_read_unlock();
return 0;
}

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

for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) {
rcu_read_lock();
list_for_each_entry(kp, &smack_known_list, list) {
if (kp->smk_cipso == NULL)
continue;

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

spin_unlock_bh(&kp->smk_cipsolock);
}
rcu_read_unlock();
if (final == NULL)
final = smack_known_huh.smk_known;
strncpy(result, final, SMK_MAXLEN);
Expand All @@ -360,13 +367,19 @@ void smack_from_cipso(u32 level, char *cp, char *result)
int smack_to_cipso(const char *smack, struct smack_cipso *cp)
{
struct smack_known *kp;
int found = 0;

for (kp = smack_known; kp != NULL; kp = kp->smk_next)
rcu_read_lock();
list_for_each_entry_rcu(kp, &smack_known_list, list) {
if (kp->smk_known == smack ||
strcmp(kp->smk_known, smack) == 0)
strcmp(kp->smk_known, smack) == 0) {
found = 1;
break;
}
}
rcu_read_unlock();

if (kp == NULL || kp->smk_cipso == NULL)
if (found == 0 || kp->smk_cipso == NULL)
return -ENOENT;

memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
Expand Down
19 changes: 17 additions & 2 deletions security/smack/smack_lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1508,18 +1508,20 @@ static char *smack_host_label(struct sockaddr_in *sip)
if (siap->s_addr == 0)
return NULL;

for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
rcu_read_lock();
list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) {
/*
* we break after finding the first match because
* the list is sorted from longest to shortest mask
* so we have found the most specific match
*/
if ((&snp->smk_host.sin_addr)->s_addr ==
(siap->s_addr & (&snp->smk_mask)->s_addr)) {
rcu_read_unlock();
return snp->smk_label;
}
}

rcu_read_unlock();
return NULL;
}

Expand Down Expand Up @@ -2930,6 +2932,17 @@ struct security_operations smack_ops = {
.release_secctx = smack_release_secctx,
};


static __init void init_smack_know_list(void)
{
list_add(&smack_known_huh.list, &smack_known_list);
list_add(&smack_known_hat.list, &smack_known_list);
list_add(&smack_known_star.list, &smack_known_list);
list_add(&smack_known_floor.list, &smack_known_list);
list_add(&smack_known_invalid.list, &smack_known_list);
list_add(&smack_known_web.list, &smack_known_list);
}

/**
* smack_init - initialize the smack system
*
Expand All @@ -2950,6 +2963,8 @@ static __init int smack_init(void)
cred = (struct cred *) current->cred;
cred->security = &smack_known_floor.smk_known;

/* initilize the smack_know_list */
init_smack_know_list();
/*
* Initialize locks
*/
Expand Down
Loading

0 comments on commit 7198e2e

Please sign in to comment.