summaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h3
-rw-r--r--security/smack/smack_access.c3
-rw-r--r--security/smack/smack_lsm.c11
-rw-r--r--security/smack/smackfs.c38
4 files changed, 45 insertions, 10 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 5e5a3bcb599..42ef313f985 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -132,6 +132,8 @@ struct smack_known {
#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
+#define SMACK_CIPSO_OPTION "-CIPSO"
+
/*
* How communications on this socket are treated.
* Usually it's determined by the underlying netlabel code
@@ -199,6 +201,7 @@ u32 smack_to_secid(const char *);
extern int smack_cipso_direct;
extern char *smack_net_ambient;
extern char *smack_onlycap;
+extern const char *smack_cipso_option;
extern struct smack_known smack_known_floor;
extern struct smack_known smack_known_hat;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 58564195bb0..ac0a2707f6d 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -261,6 +261,9 @@ char *smk_import(const char *string, int len)
{
struct smack_known *skp;
+ /* labels cannot begin with a '-' */
+ if (string[0] == '-')
+ return NULL;
skp = smk_import_entry(string, len);
if (skp == NULL)
return NULL;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 8ed502c2ad4..921514902ec 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -609,6 +609,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
if (!capable(CAP_MAC_ADMIN))
rc = -EPERM;
+ /* a label cannot be void and cannot begin with '-' */
+ if (size == 0 || (size > 0 && ((char *)value)[0] == '-'))
+ rc = -EINVAL;
} else
rc = cap_inode_setxattr(dentry, name, value, size, flags);
@@ -1323,8 +1326,12 @@ static char *smack_host_label(struct sockaddr_in *sip)
* so we have found the most specific match
*/
if ((&snp->smk_host.sin_addr)->s_addr ==
- (siap->s_addr & (&snp->smk_mask)->s_addr))
+ (siap->s_addr & (&snp->smk_mask)->s_addr)) {
+ /* we have found the special CIPSO option */
+ if (snp->smk_label == smack_cipso_option)
+ return NULL;
return snp->smk_label;
+ }
return NULL;
}
@@ -1486,7 +1493,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
struct socket *sock;
int rc = 0;
- if (value == NULL || size > SMK_LABELLEN)
+ if (value == NULL || size > SMK_LABELLEN || size == 0)
return -EACCES;
sp = smk_import(value, size);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 856c8a28752..e03a7e19c73 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -86,6 +86,9 @@ LIST_HEAD(smack_rule_list);
static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
+const char *smack_cipso_option = SMACK_CIPSO_OPTION;
+
+
#define SEQ_READ_FINISHED 1
/*
@@ -565,6 +568,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
goto unlockedout;
}
+ /* labels cannot begin with a '-' */
+ if (data[0] == '-') {
+ rc = -EINVAL;
+ goto unlockedout;
+ }
data[count] = '\0';
rule = data;
/*
@@ -808,9 +816,18 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
if (m > BEBITS)
return -EINVAL;
- sp = smk_import(smack, 0);
- if (sp == NULL)
- return -EINVAL;
+ /* if smack begins with '-', its an option, don't import it */
+ if (smack[0] != '-') {
+ sp = smk_import(smack, 0);
+ if (sp == NULL)
+ return -EINVAL;
+ } else {
+ /* check known options */
+ if (strcmp(smack, smack_cipso_option) == 0)
+ sp = (char *)smack_cipso_option;
+ else
+ return -EINVAL;
+ }
for (temp_mask = 0; m > 0; m--) {
temp_mask |= mask_bits;
@@ -849,18 +866,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
smk_netlbladdr_insert(skp);
}
} else {
- rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
- &skp->smk_host.sin_addr, &skp->smk_mask,
- PF_INET, &audit_info);
+ /* we delete the unlabeled entry, only if the previous label
+ * wasnt the special CIPSO option */
+ if (skp->smk_label != smack_cipso_option)
+ rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
+ &skp->smk_host.sin_addr, &skp->smk_mask,
+ PF_INET, &audit_info);
+ else
+ rc = 0;
skp->smk_label = sp;
}
/*
* Now tell netlabel about the single label nature of
* this host so that incoming packets get labeled.
+ * but only if we didn't get the special CIPSO option
*/
-
- if (rc == 0)
+ if (rc == 0 && sp != smack_cipso_option)
rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
&skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
smack_to_secid(skp->smk_label), &audit_info);