mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
Smack: allow for significantly longer Smack labels v4
V4 updated to current linux-security#next Targeted for git://gitorious.org/smack-next/kernel.git Modern application runtime environments like to use naming schemes that are structured and generated without human intervention. Even though the Smack limit of 23 characters for a label name is perfectly rational for human use there have been complaints that the limit is a problem in environments where names are composed from a set or sources, including vendor, author, distribution channel and application name. Names like softwarehouse-pgwodehouse-coolappstore-mellowmuskrats are becoming harder to avoid. This patch introduces long label support in Smack. Labels are now limited to 255 characters instead of the old 23. The primary reason for limiting the labels to 23 characters was so they could be directly contained in CIPSO category sets. This is still done were possible, but for labels that are too large a mapping is required. This is perfectly safe for communication that stays "on the box" and doesn't require much coordination between boxes beyond what would have been required to keep label names consistent. The bulk of this patch is in smackfs, adding and updating administrative interfaces. Because existing APIs can't be changed new ones that do much the same things as old ones have been introduced. The Smack specific CIPSO data representation has been removed and replaced with the data format used by netlabel. The CIPSO header is now computed when a label is imported rather than on use. This results in improved IP performance. The smack label is now allocated separately from the containing structure, allowing for larger strings. Four new /smack interfaces have been introduced as four of the old interfaces strictly required labels be specified in fixed length arrays. The access interface is supplemented with the check interface: access "Subject Object rwxat" access2 "Subject Object rwaxt" The load interface is supplemented with the rules interface: load "Subject Object rwxat" load2 "Subject Object rwaxt" The load-self interface is supplemented with the self-rules interface: load-self "Subject Object rwxat" load-self2 "Subject Object rwaxt" The cipso interface is supplemented with the wire interface: cipso "Subject lvl cnt c1 c2 ..." cipso2 "Subject lvl cnt c1 c2 ..." The old interfaces are maintained for compatibility. Signed-off-by: Casey Schaufler <[email protected]>
This commit is contained in:
parent
ceffec5541
commit
f7112e6c9a
5 changed files with 1105 additions and 566 deletions
|
|
@ -23,13 +23,19 @@
|
|||
#include <linux/lsm_audit.h>
|
||||
|
||||
/*
|
||||
* Smack labels were limited to 23 characters for a long time.
|
||||
*/
|
||||
#define SMK_LABELLEN 24
|
||||
#define SMK_LONGLABEL 256
|
||||
|
||||
/*
|
||||
* Maximum number of bytes for the levels in a CIPSO IP option.
|
||||
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
|
||||
* bigger than can be used, and 24 is the next lower multiple
|
||||
* of 8, and there are too many issues if there isn't space set
|
||||
* aside for the terminating null byte.
|
||||
*/
|
||||
#define SMK_MAXLEN 23
|
||||
#define SMK_LABELLEN (SMK_MAXLEN+1)
|
||||
#define SMK_CIPSOLEN 24
|
||||
|
||||
struct superblock_smack {
|
||||
char *smk_root;
|
||||
|
|
@ -78,15 +84,6 @@ struct smack_rule {
|
|||
int smk_access;
|
||||
};
|
||||
|
||||
/*
|
||||
* An entry in the table mapping smack values to
|
||||
* CIPSO level/category-set values.
|
||||
*/
|
||||
struct smack_cipso {
|
||||
int smk_level;
|
||||
char smk_catset[SMK_LABELLEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* An entry in the table identifying hosts.
|
||||
*/
|
||||
|
|
@ -114,22 +111,19 @@ struct smk_netlbladdr {
|
|||
* interfaces don't. The secid should go away when all of
|
||||
* these components have been repaired.
|
||||
*
|
||||
* If there is a cipso value associated with the label it
|
||||
* gets stored here, too. This will most likely be rare as
|
||||
* the cipso direct mapping in used internally.
|
||||
* The cipso value associated with the label gets stored here, too.
|
||||
*
|
||||
* Keep the access rules for this subject label here so that
|
||||
* the entire set of rules does not need to be examined every
|
||||
* time.
|
||||
*/
|
||||
struct smack_known {
|
||||
struct list_head list;
|
||||
char smk_known[SMK_LABELLEN];
|
||||
u32 smk_secid;
|
||||
struct smack_cipso *smk_cipso;
|
||||
spinlock_t smk_cipsolock; /* for changing cipso map */
|
||||
struct list_head smk_rules; /* access rules */
|
||||
struct mutex smk_rules_lock; /* lock for the rules */
|
||||
struct list_head list;
|
||||
char *smk_known;
|
||||
u32 smk_secid;
|
||||
struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */
|
||||
struct list_head smk_rules; /* access rules */
|
||||
struct mutex smk_rules_lock; /* lock for rules */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -166,6 +160,7 @@ struct smack_known {
|
|||
#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
|
||||
#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
|
||||
#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
|
||||
#define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */
|
||||
#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
|
||||
#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
|
||||
#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */
|
||||
|
|
@ -216,10 +211,9 @@ struct inode_smack *new_inode_smack(char *);
|
|||
int smk_access_entry(char *, char *, struct list_head *);
|
||||
int smk_access(char *, char *, int, struct smk_audit_info *);
|
||||
int smk_curacc(char *, u32, struct smk_audit_info *);
|
||||
int smack_to_cipso(const char *, struct smack_cipso *);
|
||||
char *smack_from_cipso(u32, char *);
|
||||
char *smack_from_secid(const u32);
|
||||
void smk_parse_smack(const char *string, int len, char *smack);
|
||||
char *smk_parse_smack(const char *string, int len);
|
||||
int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
|
||||
char *smk_import(const char *, int);
|
||||
struct smack_known *smk_import_entry(const char *, int);
|
||||
struct smack_known *smk_find_entry(const char *);
|
||||
|
|
@ -229,6 +223,7 @@ u32 smack_to_secid(const char *);
|
|||
* Shared data.
|
||||
*/
|
||||
extern int smack_cipso_direct;
|
||||
extern int smack_cipso_mapped;
|
||||
extern char *smack_net_ambient;
|
||||
extern char *smack_onlycap;
|
||||
extern const char *smack_cipso_option;
|
||||
|
|
@ -240,23 +235,12 @@ extern struct smack_known smack_known_invalid;
|
|||
extern struct smack_known smack_known_star;
|
||||
extern struct smack_known smack_known_web;
|
||||
|
||||
extern struct mutex smack_known_lock;
|
||||
extern struct list_head smack_known_list;
|
||||
extern struct list_head smk_netlbladdr_list;
|
||||
|
||||
extern struct security_operations smack_ops;
|
||||
|
||||
/*
|
||||
* Stricly for CIPSO level manipulation.
|
||||
* Set the category bit number in a smack label sized buffer.
|
||||
*/
|
||||
static inline void smack_catset_bit(int cat, char *catsetp)
|
||||
{
|
||||
if (cat > SMK_LABELLEN * 8)
|
||||
return;
|
||||
|
||||
catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the directory transmuting?
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -19,37 +19,31 @@
|
|||
struct smack_known smack_known_huh = {
|
||||
.smk_known = "?",
|
||||
.smk_secid = 2,
|
||||
.smk_cipso = NULL,
|
||||
};
|
||||
|
||||
struct smack_known smack_known_hat = {
|
||||
.smk_known = "^",
|
||||
.smk_secid = 3,
|
||||
.smk_cipso = NULL,
|
||||
};
|
||||
|
||||
struct smack_known smack_known_star = {
|
||||
.smk_known = "*",
|
||||
.smk_secid = 4,
|
||||
.smk_cipso = NULL,
|
||||
};
|
||||
|
||||
struct smack_known smack_known_floor = {
|
||||
.smk_known = "_",
|
||||
.smk_secid = 5,
|
||||
.smk_cipso = NULL,
|
||||
};
|
||||
|
||||
struct smack_known smack_known_invalid = {
|
||||
.smk_known = "",
|
||||
.smk_secid = 6,
|
||||
.smk_cipso = NULL,
|
||||
};
|
||||
|
||||
struct smack_known smack_known_web = {
|
||||
.smk_known = "@",
|
||||
.smk_secid = 7,
|
||||
.smk_cipso = NULL,
|
||||
};
|
||||
|
||||
LIST_HEAD(smack_known_list);
|
||||
|
|
@ -331,7 +325,7 @@ void smack_log(char *subject_label, char *object_label, int request,
|
|||
}
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(smack_known_lock);
|
||||
DEFINE_MUTEX(smack_known_lock);
|
||||
|
||||
/**
|
||||
* smk_find_entry - find a label on the list, return the list entry
|
||||
|
|
@ -345,7 +339,7 @@ struct smack_known *smk_find_entry(const char *string)
|
|||
struct smack_known *skp;
|
||||
|
||||
list_for_each_entry_rcu(skp, &smack_known_list, list) {
|
||||
if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0)
|
||||
if (strcmp(skp->smk_known, string) == 0)
|
||||
return skp;
|
||||
}
|
||||
|
||||
|
|
@ -356,27 +350,76 @@ struct smack_known *smk_find_entry(const char *string)
|
|||
* smk_parse_smack - parse smack label from a text string
|
||||
* @string: a text string that might contain a Smack label
|
||||
* @len: the maximum size, or zero if it is NULL terminated.
|
||||
* @smack: parsed smack label, or NULL if parse error
|
||||
*
|
||||
* Returns a pointer to the clean label, or NULL
|
||||
*/
|
||||
void smk_parse_smack(const char *string, int len, char *smack)
|
||||
char *smk_parse_smack(const char *string, int len)
|
||||
{
|
||||
int found;
|
||||
char *smack;
|
||||
int i;
|
||||
|
||||
if (len <= 0 || len > SMK_MAXLEN)
|
||||
len = SMK_MAXLEN;
|
||||
if (len <= 0)
|
||||
len = strlen(string) + 1;
|
||||
|
||||
for (i = 0, found = 0; i < SMK_LABELLEN; i++) {
|
||||
if (found)
|
||||
smack[i] = '\0';
|
||||
else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
|
||||
string[i] == '/' || string[i] == '"' ||
|
||||
string[i] == '\\' || string[i] == '\'') {
|
||||
smack[i] = '\0';
|
||||
found = 1;
|
||||
} else
|
||||
smack[i] = string[i];
|
||||
/*
|
||||
* Reserve a leading '-' as an indicator that
|
||||
* this isn't a label, but an option to interfaces
|
||||
* including /smack/cipso and /smack/cipso2
|
||||
*/
|
||||
if (string[0] == '-')
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
|
||||
string[i] == '"' || string[i] == '\\' || string[i] == '\'')
|
||||
break;
|
||||
|
||||
if (i == 0 || i >= SMK_LONGLABEL)
|
||||
return NULL;
|
||||
|
||||
smack = kzalloc(i + 1, GFP_KERNEL);
|
||||
if (smack != NULL) {
|
||||
strncpy(smack, string, i + 1);
|
||||
smack[i] = '\0';
|
||||
}
|
||||
return smack;
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_netlbl_mls - convert a catset to netlabel mls categories
|
||||
* @catset: the Smack categories
|
||||
* @sap: where to put the netlabel categories
|
||||
*
|
||||
* Allocates and fills attr.mls
|
||||
* Returns 0 on success, error code on failure.
|
||||
*/
|
||||
int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
|
||||
int len)
|
||||
{
|
||||
unsigned char *cp;
|
||||
unsigned char m;
|
||||
int cat;
|
||||
int rc;
|
||||
int byte;
|
||||
|
||||
sap->flags |= NETLBL_SECATTR_MLS_CAT;
|
||||
sap->attr.mls.lvl = level;
|
||||
sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
|
||||
sap->attr.mls.cat->startbit = 0;
|
||||
|
||||
for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
|
||||
for (m = 0x80; m != 0; m >>= 1, cat++) {
|
||||
if ((m & *cp) == 0)
|
||||
continue;
|
||||
rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
|
||||
cat, GFP_ATOMIC);
|
||||
if (rc < 0) {
|
||||
netlbl_secattr_catmap_free(sap->attr.mls.cat);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -390,33 +433,59 @@ void smk_parse_smack(const char *string, int len, char *smack)
|
|||
struct smack_known *smk_import_entry(const char *string, int len)
|
||||
{
|
||||
struct smack_known *skp;
|
||||
char smack[SMK_LABELLEN];
|
||||
char *smack;
|
||||
int slen;
|
||||
int rc;
|
||||
|
||||
smk_parse_smack(string, len, smack);
|
||||
if (smack[0] == '\0')
|
||||
smack = smk_parse_smack(string, len);
|
||||
if (smack == NULL)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&smack_known_lock);
|
||||
|
||||
skp = smk_find_entry(smack);
|
||||
if (skp != NULL)
|
||||
goto freeout;
|
||||
|
||||
if (skp == NULL) {
|
||||
skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
|
||||
if (skp != NULL) {
|
||||
strncpy(skp->smk_known, smack, SMK_MAXLEN);
|
||||
skp->smk_secid = smack_next_secid++;
|
||||
skp->smk_cipso = NULL;
|
||||
INIT_LIST_HEAD(&skp->smk_rules);
|
||||
spin_lock_init(&skp->smk_cipsolock);
|
||||
mutex_init(&skp->smk_rules_lock);
|
||||
/*
|
||||
* Make sure that the entry is actually
|
||||
* filled before putting it on the list.
|
||||
*/
|
||||
list_add_rcu(&skp->list, &smack_known_list);
|
||||
}
|
||||
skp = kzalloc(sizeof(*skp), GFP_KERNEL);
|
||||
if (skp == NULL)
|
||||
goto freeout;
|
||||
|
||||
skp->smk_known = smack;
|
||||
skp->smk_secid = smack_next_secid++;
|
||||
skp->smk_netlabel.domain = skp->smk_known;
|
||||
skp->smk_netlabel.flags =
|
||||
NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
|
||||
/*
|
||||
* If direct labeling works use it.
|
||||
* Otherwise use mapped labeling.
|
||||
*/
|
||||
slen = strlen(smack);
|
||||
if (slen < SMK_CIPSOLEN)
|
||||
rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
|
||||
&skp->smk_netlabel, slen);
|
||||
else
|
||||
rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
|
||||
&skp->smk_netlabel, sizeof(skp->smk_secid));
|
||||
|
||||
if (rc >= 0) {
|
||||
INIT_LIST_HEAD(&skp->smk_rules);
|
||||
mutex_init(&skp->smk_rules_lock);
|
||||
/*
|
||||
* Make sure that the entry is actually
|
||||
* filled before putting it on the list.
|
||||
*/
|
||||
list_add_rcu(&skp->list, &smack_known_list);
|
||||
goto unlockout;
|
||||
}
|
||||
|
||||
/*
|
||||
* smk_netlbl_mls failed.
|
||||
*/
|
||||
kfree(skp);
|
||||
skp = NULL;
|
||||
freeout:
|
||||
kfree(smack);
|
||||
unlockout:
|
||||
mutex_unlock(&smack_known_lock);
|
||||
|
||||
return skp;
|
||||
|
|
@ -479,79 +548,9 @@ char *smack_from_secid(const u32 secid)
|
|||
*/
|
||||
u32 smack_to_secid(const char *smack)
|
||||
{
|
||||
struct smack_known *skp;
|
||||
struct smack_known *skp = smk_find_entry(smack);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_from_cipso - find the Smack label associated with a CIPSO option
|
||||
* @level: Bell & LaPadula level from the network
|
||||
* @cp: Bell & LaPadula categories from the network
|
||||
*
|
||||
* This is a simple lookup in the label table.
|
||||
*
|
||||
* Return the matching label from the label list or NULL.
|
||||
*/
|
||||
char *smack_from_cipso(u32 level, char *cp)
|
||||
{
|
||||
struct smack_known *kp;
|
||||
char *final = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry(kp, &smack_known_list, list) {
|
||||
if (kp->smk_cipso == NULL)
|
||||
continue;
|
||||
|
||||
spin_lock_bh(&kp->smk_cipsolock);
|
||||
|
||||
if (kp->smk_cipso->smk_level == level &&
|
||||
memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0)
|
||||
final = kp->smk_known;
|
||||
|
||||
spin_unlock_bh(&kp->smk_cipsolock);
|
||||
|
||||
if (final != NULL)
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_to_cipso - find the CIPSO option to go with a Smack label
|
||||
* @smack: a pointer to the smack label in question
|
||||
* @cp: where to put the result
|
||||
*
|
||||
* Returns zero if a value is available, non-zero otherwise.
|
||||
*/
|
||||
int smack_to_cipso(const char *smack, struct smack_cipso *cp)
|
||||
{
|
||||
struct smack_known *kp;
|
||||
int found = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(kp, &smack_known_list, list) {
|
||||
if (kp->smk_known == smack ||
|
||||
strcmp(kp->smk_known, smack) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (found == 0 || kp->smk_cipso == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
|
||||
return 0;
|
||||
if (skp == NULL)
|
||||
return 0;
|
||||
return skp->smk_secid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pipe_fs_i.h>
|
||||
#include <net/netlabel.h>
|
||||
#include <net/cipso_ipv4.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/magic.h>
|
||||
|
|
@ -57,16 +56,23 @@
|
|||
static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
|
||||
{
|
||||
int rc;
|
||||
char in[SMK_LABELLEN];
|
||||
char *buffer;
|
||||
char *result = NULL;
|
||||
|
||||
if (ip->i_op->getxattr == NULL)
|
||||
return NULL;
|
||||
|
||||
rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN);
|
||||
if (rc < 0)
|
||||
buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
|
||||
if (buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
return smk_import(in, rc);
|
||||
rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
|
||||
if (rc > 0)
|
||||
result = smk_import(buffer, rc);
|
||||
|
||||
kfree(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -825,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
|
|||
* check label validity here so import wont fail on
|
||||
* post_setxattr
|
||||
*/
|
||||
if (size == 0 || size >= SMK_LABELLEN ||
|
||||
if (size == 0 || size >= SMK_LONGLABEL ||
|
||||
smk_import(value, size) == NULL)
|
||||
rc = -EINVAL;
|
||||
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
|
||||
|
|
@ -1823,65 +1829,6 @@ static char *smack_host_label(struct sockaddr_in *sip)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_set_catset - convert a capset to netlabel mls categories
|
||||
* @catset: the Smack categories
|
||||
* @sap: where to put the netlabel categories
|
||||
*
|
||||
* Allocates and fills attr.mls.cat
|
||||
*/
|
||||
static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
|
||||
{
|
||||
unsigned char *cp;
|
||||
unsigned char m;
|
||||
int cat;
|
||||
int rc;
|
||||
int byte;
|
||||
|
||||
if (!catset)
|
||||
return;
|
||||
|
||||
sap->flags |= NETLBL_SECATTR_MLS_CAT;
|
||||
sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
|
||||
sap->attr.mls.cat->startbit = 0;
|
||||
|
||||
for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
|
||||
for (m = 0x80; m != 0; m >>= 1, cat++) {
|
||||
if ((m & *cp) == 0)
|
||||
continue;
|
||||
rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
|
||||
cat, GFP_ATOMIC);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_to_secattr - fill a secattr from a smack value
|
||||
* @smack: the smack value
|
||||
* @nlsp: where the result goes
|
||||
*
|
||||
* Casey says that CIPSO is good enough for now.
|
||||
* It can be used to effect.
|
||||
* It can also be abused to effect when necessary.
|
||||
* Apologies to the TSIG group in general and GW in particular.
|
||||
*/
|
||||
static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
|
||||
{
|
||||
struct smack_cipso cipso;
|
||||
int rc;
|
||||
|
||||
nlsp->domain = smack;
|
||||
nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
|
||||
|
||||
rc = smack_to_cipso(smack, &cipso);
|
||||
if (rc == 0) {
|
||||
nlsp->attr.mls.lvl = cipso.smk_level;
|
||||
smack_set_catset(cipso.smk_catset, nlsp);
|
||||
} else {
|
||||
nlsp->attr.mls.lvl = smack_cipso_direct;
|
||||
smack_set_catset(smack, nlsp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_netlabel - Set the secattr on a socket
|
||||
* @sk: the socket
|
||||
|
|
@ -1894,8 +1841,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
|
|||
*/
|
||||
static int smack_netlabel(struct sock *sk, int labeled)
|
||||
{
|
||||
struct smack_known *skp;
|
||||
struct socket_smack *ssp = sk->sk_security;
|
||||
struct netlbl_lsm_secattr secattr;
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
|
|
@ -1913,10 +1860,8 @@ static int smack_netlabel(struct sock *sk, int labeled)
|
|||
labeled == SMACK_UNLABELED_SOCKET)
|
||||
netlbl_sock_delattr(sk);
|
||||
else {
|
||||
netlbl_secattr_init(&secattr);
|
||||
smack_to_secattr(ssp->smk_out, &secattr);
|
||||
rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
|
||||
netlbl_secattr_destroy(&secattr);
|
||||
skp = smk_find_entry(ssp->smk_out);
|
||||
rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
|
||||
}
|
||||
|
||||
bh_unlock_sock(sk);
|
||||
|
|
@ -1989,7 +1934,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
|
|||
struct socket *sock;
|
||||
int rc = 0;
|
||||
|
||||
if (value == NULL || size > SMK_LABELLEN || size == 0)
|
||||
if (value == NULL || size > SMK_LONGLABEL || size == 0)
|
||||
return -EACCES;
|
||||
|
||||
sp = smk_import(value, size);
|
||||
|
|
@ -2785,7 +2730,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
|
|||
if (!capable(CAP_MAC_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (value == NULL || size == 0 || size >= SMK_LABELLEN)
|
||||
if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(name, "current") != 0)
|
||||
|
|
@ -2921,10 +2866,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
|
||||
struct socket_smack *ssp)
|
||||
{
|
||||
struct smack_known *skp;
|
||||
char smack[SMK_LABELLEN];
|
||||
struct smack_known *kp;
|
||||
char *sp;
|
||||
int pcat;
|
||||
int found = 0;
|
||||
|
||||
if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
|
||||
/*
|
||||
|
|
@ -2932,59 +2876,27 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
|
|||
* If there are flags but no level netlabel isn't
|
||||
* behaving the way we expect it to.
|
||||
*
|
||||
* Get the categories, if any
|
||||
* Look it up in the label table
|
||||
* Without guidance regarding the smack value
|
||||
* for the packet fall back on the network
|
||||
* ambient value.
|
||||
*/
|
||||
memset(smack, '\0', SMK_LABELLEN);
|
||||
if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
|
||||
for (pcat = -1;;) {
|
||||
pcat = netlbl_secattr_catmap_walk(
|
||||
sap->attr.mls.cat, pcat + 1);
|
||||
if (pcat < 0)
|
||||
break;
|
||||
smack_catset_bit(pcat, smack);
|
||||
}
|
||||
/*
|
||||
* If it is CIPSO using smack direct mapping
|
||||
* we are already done. WeeHee.
|
||||
*/
|
||||
if (sap->attr.mls.lvl == smack_cipso_direct) {
|
||||
/*
|
||||
* The label sent is usually on the label list.
|
||||
*
|
||||
* If it is not we may still want to allow the
|
||||
* delivery.
|
||||
*
|
||||
* If the recipient is accepting all packets
|
||||
* because it is using the star ("*") label
|
||||
* for SMACK64IPIN provide the web ("@") label
|
||||
* so that a directed response will succeed.
|
||||
* This is not very correct from a MAC point
|
||||
* of view, but gets around the problem that
|
||||
* locking prevents adding the newly discovered
|
||||
* label to the list.
|
||||
* The case where the recipient is not using
|
||||
* the star label should obviously fail.
|
||||
* The easy way to do this is to provide the
|
||||
* star label as the subject label.
|
||||
*/
|
||||
skp = smk_find_entry(smack);
|
||||
if (skp != NULL)
|
||||
return skp->smk_known;
|
||||
if (ssp != NULL &&
|
||||
ssp->smk_in == smack_known_star.smk_known)
|
||||
return smack_known_web.smk_known;
|
||||
return smack_known_star.smk_known;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry(kp, &smack_known_list, list) {
|
||||
if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl)
|
||||
continue;
|
||||
if (memcmp(sap->attr.mls.cat,
|
||||
kp->smk_netlabel.attr.mls.cat,
|
||||
SMK_CIPSOLEN) != 0)
|
||||
continue;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Look it up in the supplied table if it is not
|
||||
* a direct mapping.
|
||||
*/
|
||||
sp = smack_from_cipso(sap->attr.mls.lvl, smack);
|
||||
if (sp != NULL)
|
||||
return sp;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (found)
|
||||
return kp->smk_known;
|
||||
|
||||
if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
|
||||
return smack_known_web.smk_known;
|
||||
return smack_known_star.smk_known;
|
||||
|
|
@ -3184,11 +3096,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|||
struct request_sock *req)
|
||||
{
|
||||
u16 family = sk->sk_family;
|
||||
struct smack_known *skp;
|
||||
struct socket_smack *ssp = sk->sk_security;
|
||||
struct netlbl_lsm_secattr secattr;
|
||||
struct sockaddr_in addr;
|
||||
struct iphdr *hdr;
|
||||
char *sp;
|
||||
char *hsp;
|
||||
int rc;
|
||||
struct smk_audit_info ad;
|
||||
#ifdef CONFIG_AUDIT
|
||||
|
|
@ -3235,16 +3149,14 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|||
hdr = ip_hdr(skb);
|
||||
addr.sin_addr.s_addr = hdr->saddr;
|
||||
rcu_read_lock();
|
||||
if (smack_host_label(&addr) == NULL) {
|
||||
rcu_read_unlock();
|
||||
netlbl_secattr_init(&secattr);
|
||||
smack_to_secattr(sp, &secattr);
|
||||
rc = netlbl_req_setattr(req, &secattr);
|
||||
netlbl_secattr_destroy(&secattr);
|
||||
} else {
|
||||
rcu_read_unlock();
|
||||
hsp = smack_host_label(&addr);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (hsp == NULL) {
|
||||
skp = smk_find_entry(sp);
|
||||
rc = netlbl_req_setattr(req, &skp->smk_netlabel);
|
||||
} else
|
||||
netlbl_req_delattr(req);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -3668,15 +3580,6 @@ struct security_operations smack_ops = {
|
|||
|
||||
static __init void init_smack_known_list(void)
|
||||
{
|
||||
/*
|
||||
* Initialize CIPSO locks
|
||||
*/
|
||||
spin_lock_init(&smack_known_huh.smk_cipsolock);
|
||||
spin_lock_init(&smack_known_hat.smk_cipsolock);
|
||||
spin_lock_init(&smack_known_star.smk_cipsolock);
|
||||
spin_lock_init(&smack_known_floor.smk_cipsolock);
|
||||
spin_lock_init(&smack_known_invalid.smk_cipsolock);
|
||||
spin_lock_init(&smack_known_web.smk_cipsolock);
|
||||
/*
|
||||
* Initialize rule list locks
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue