summaryrefslogtreecommitdiff
path: root/security/smack
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-20 00:10:27 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-20 00:10:27 -0300
commitd0b2f91bede3bd5e3d24dd6803e56eee959c1797 (patch)
tree7fee4ab0509879c373c4f2cbd5b8a5be5b4041ee /security/smack
parente914f8eb445e8f74b00303c19c2ffceaedd16a05 (diff)
Linux-libre 4.8.2-gnupck-4.8.2-gnu
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h8
-rw-r--r--security/smack/smack_access.c4
-rw-r--r--security/smack/smack_lsm.c39
3 files changed, 44 insertions, 7 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 6c91156ae..26e58f180 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -90,9 +90,15 @@ struct superblock_smack {
struct smack_known *smk_floor;
struct smack_known *smk_hat;
struct smack_known *smk_default;
- int smk_initialized;
+ int smk_flags;
};
+/*
+ * Superblock flags
+ */
+#define SMK_SB_INITIALIZED 0x01
+#define SMK_SB_UNTRUSTED 0x02
+
struct socket_smack {
struct smack_known *smk_out; /* outbound label */
struct smack_known *smk_in; /* inbound label */
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index a283f9e79..23e5808a0 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -413,7 +413,7 @@ void smk_insert_entry(struct smack_known *skp)
unsigned int hash;
struct hlist_head *head;
- hash = full_name_hash(skp->smk_known, strlen(skp->smk_known));
+ hash = full_name_hash(NULL, skp->smk_known, strlen(skp->smk_known));
head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
hlist_add_head_rcu(&skp->smk_hashed, head);
@@ -433,7 +433,7 @@ struct smack_known *smk_find_entry(const char *string)
struct hlist_head *head;
struct smack_known *skp;
- hash = full_name_hash(string, strlen(string));
+ hash = full_name_hash(NULL, string, strlen(string));
head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
hlist_for_each_entry_rcu(skp, head, smk_hashed)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 6777295f4..87a9741b0 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -549,7 +549,7 @@ static int smack_sb_alloc_security(struct super_block *sb)
sbsp->smk_floor = &smack_known_floor;
sbsp->smk_hat = &smack_known_hat;
/*
- * smk_initialized will be zero from kzalloc.
+ * SMK_SB_INITIALIZED will be zero from kzalloc.
*/
sb->s_security = sbsp;
@@ -766,10 +766,10 @@ static int smack_set_mnt_opts(struct super_block *sb,
int num_opts = opts->num_mnt_opts;
int transmute = 0;
- if (sp->smk_initialized)
+ if (sp->smk_flags & SMK_SB_INITIALIZED)
return 0;
- sp->smk_initialized = 1;
+ sp->smk_flags |= SMK_SB_INITIALIZED;
for (i = 0; i < num_opts; i++) {
switch (opts->mnt_opts_flags[i]) {
@@ -821,6 +821,17 @@ static int smack_set_mnt_opts(struct super_block *sb,
skp = smk_of_current();
sp->smk_root = skp;
sp->smk_default = skp;
+ /*
+ * For a handful of fs types with no user-controlled
+ * backing store it's okay to trust security labels
+ * in the filesystem. The rest are untrusted.
+ */
+ if (sb->s_user_ns != &init_user_ns &&
+ sb->s_magic != SYSFS_MAGIC && sb->s_magic != TMPFS_MAGIC &&
+ sb->s_magic != RAMFS_MAGIC) {
+ transmute = 1;
+ sp->smk_flags |= SMK_SB_UNTRUSTED;
+ }
}
/*
@@ -908,6 +919,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
struct inode *inode = file_inode(bprm->file);
struct task_smack *bsp = bprm->cred->security;
struct inode_smack *isp;
+ struct superblock_smack *sbsp;
int rc;
if (bprm->cred_prepared)
@@ -917,6 +929,11 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task)
return 0;
+ sbsp = inode->i_sb->s_security;
+ if ((sbsp->smk_flags & SMK_SB_UNTRUSTED) &&
+ isp->smk_task != sbsp->smk_root)
+ return 0;
+
if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
struct task_struct *tracer;
rc = 0;
@@ -1203,6 +1220,7 @@ static int smack_inode_rename(struct inode *old_inode,
*/
static int smack_inode_permission(struct inode *inode, int mask)
{
+ struct superblock_smack *sbsp = inode->i_sb->s_security;
struct smk_audit_info ad;
int no_block = mask & MAY_NOT_BLOCK;
int rc;
@@ -1214,6 +1232,11 @@ static int smack_inode_permission(struct inode *inode, int mask)
if (mask == 0)
return 0;
+ if (sbsp->smk_flags & SMK_SB_UNTRUSTED) {
+ if (smk_of_inode(inode) != sbsp->smk_root)
+ return -EACCES;
+ }
+
/* May be droppable after audit */
if (no_block)
return -ECHILD;
@@ -1708,6 +1731,7 @@ static int smack_mmap_file(struct file *file,
struct task_smack *tsp;
struct smack_known *okp;
struct inode_smack *isp;
+ struct superblock_smack *sbsp;
int may;
int mmay;
int tmay;
@@ -1719,6 +1743,10 @@ static int smack_mmap_file(struct file *file,
isp = file_inode(file)->i_security;
if (isp->smk_mmap == NULL)
return 0;
+ sbsp = file_inode(file)->i_sb->s_security;
+ if (sbsp->smk_flags & SMK_SB_UNTRUSTED &&
+ isp->smk_mmap != sbsp->smk_root)
+ return -EACCES;
mkp = isp->smk_mmap;
tsp = current_security();
@@ -2227,6 +2255,9 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
struct smack_known *tkp = smk_of_task_struct(p);
int rc;
+ if (!sig)
+ return 0; /* null signal; existence test */
+
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
smk_ad_setfield_u_tsk(&ad, p);
/*
@@ -3992,7 +4023,7 @@ access_check:
rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in,
MAY_WRITE, rc);
if (rc != 0)
- netlbl_skbuff_err(skb, rc, 0);
+ netlbl_skbuff_err(skb, sk->sk_family, rc, 0);
break;
#if IS_ENABLED(CONFIG_IPV6)
case PF_INET6: