diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-10-20 00:10:27 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-10-20 00:10:27 -0300 |
commit | d0b2f91bede3bd5e3d24dd6803e56eee959c1797 (patch) | |
tree | 7fee4ab0509879c373c4f2cbd5b8a5be5b4041ee /security/smack | |
parent | e914f8eb445e8f74b00303c19c2ffceaedd16a05 (diff) |
Linux-libre 4.8.2-gnupck-4.8.2-gnu
Diffstat (limited to 'security/smack')
-rw-r--r-- | security/smack/smack.h | 8 | ||||
-rw-r--r-- | security/smack/smack_access.c | 4 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 39 |
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: |