From 0817534ff9ea809fac1322c5c8c574be8483ea57 Mon Sep 17 00:00:00 2001 From: Pawan Gupta Date: Sat, 28 Aug 2021 23:41:40 -0700 Subject: [PATCH 1/7] smackfs: Fix use-after-free in netlbl_catmap_walk() Syzkaller reported use-after-free bug as described in [1]. The bug is triggered when smk_set_cipso() tries to free stale category bitmaps while there are concurrent reader(s) using the same bitmaps. Wait for RCU grace period to finish before freeing the category bitmaps in smk_set_cipso(). This makes sure that there are no more readers using the stale bitmaps and freeing them should be safe. [1] https://lore.kernel.org/netdev/000000000000a814c505ca657a4e@google.com/ Reported-by: syzbot+3f91de0b813cc3d19a80@syzkaller.appspotmail.com Signed-off-by: Pawan Gupta Signed-off-by: Casey Schaufler --- security/smack/smackfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 3a75d2a8f517..9d853c0e55b8 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -831,6 +831,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file) static ssize_t smk_set_cipso(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int format) { + struct netlbl_lsm_catmap *old_cat; struct smack_known *skp; struct netlbl_lsm_secattr ncats; char mapcatset[SMK_CIPSOLEN]; @@ -920,9 +921,11 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); if (rc >= 0) { - netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat); + old_cat = skp->smk_netlabel.attr.mls.cat; skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat; skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; + synchronize_rcu(); + netlbl_catmap_free(old_cat); rc = count; /* * This mapping may have been cached, so clear the cache. From 222a96b31c242d6736868da679d8c733719a3716 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 23 Sep 2021 19:05:03 +0200 Subject: [PATCH 2/7] smack: Guard smack_ipv6_lock definition within a SMACK_IPV6_PORT_LABELING block The mutex smack_ipv6_lock is only used with the SMACK_IPV6_PORT_LABELING block but its definition is outside of the block. This leads to a defined-but-not-used warning on PREEMPT_RT. Moving smack_ipv6_lock down to the block where it is used where it used raises the question why is smk_ipv6_port_list read if nothing is added to it. Turns out, only smk_ipv6_port_check() is using it outside of an ifdef SMACK_IPV6_PORT_LABELING block. However two of three caller invoke smk_ipv6_port_check() from a ifdef block and only one is using __is_defined() macro which requires the function and smk_ipv6_port_list to be around. Put the lock and list inside an ifdef SMACK_IPV6_PORT_LABELING block to avoid the warning regarding unused mutex. Extend the ifdef-block to also cover smk_ipv6_port_check(). Make smack_socket_connect() use ifdef instead of __is_defined() to avoid complains about missing function. Cc: Casey Schaufler Cc: James Morris Cc: "Serge E. Hallyn" Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index cacbe7518519..95bd604c3819 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -51,8 +51,10 @@ #define SMK_RECEIVING 1 #define SMK_SENDING 2 +#ifdef SMACK_IPV6_PORT_LABELING static DEFINE_MUTEX(smack_ipv6_lock); static LIST_HEAD(smk_ipv6_port_list); +#endif struct kmem_cache *smack_rule_cache; int smack_enabled __initdata; @@ -2603,7 +2605,6 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) mutex_unlock(&smack_ipv6_lock); return; } -#endif /** * smk_ipv6_port_check - check Smack port access @@ -2666,6 +2667,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, return smk_ipv6_check(skp, object, address, act); } +#endif /** * smack_inode_setsecurity - set smack xattrs @@ -2852,8 +2854,9 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, rc = smk_ipv6_check(ssp->smk_out, rsp, sip, SMK_CONNECTING); } - if (__is_defined(SMACK_IPV6_PORT_LABELING)) - rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING); +#ifdef SMACK_IPV6_PORT_LABELING + rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING); +#endif return rc; } From 387ef964460f14fe1c1ea29aba70e22731ea7cf7 Mon Sep 17 00:00:00 2001 From: Vishal Goel Date: Fri, 17 Sep 2021 13:08:14 +0530 Subject: [PATCH 3/7] Smack:- Use overlay inode label in smack_inode_copy_up() Currently in "smack_inode_copy_up()" function, process label is changed with the label on parent inode. Due to which, process is assigned directory label and whatever file or directory created by the process are also getting directory label which is wrong label. Changes has been done to use label of overlay inode instead of parent inode. Signed-off-by: Vishal Goel Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 95bd604c3819..5ea4815a0242 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4637,7 +4637,7 @@ static int smack_inode_copy_up(struct dentry *dentry, struct cred **new) /* * Get label from overlay inode and set it in create_sid */ - isp = smack_inode(d_inode(dentry->d_parent)); + isp = smack_inode(d_inode(dentry)); skp = isp->smk_inode; tsp->smk_task = skp; *new = new_creds; From f8de49ef925222135aff23f13344c1a907d88a41 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 Oct 2021 16:33:09 +0200 Subject: [PATCH 4/7] smack: remove duplicated hook function ipv4 and ipv6 hook functions are identical, remove one. Signed-off-by: Florian Westphal Signed-off-by: Casey Schaufler --- security/smack/smack_netfilter.c | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c index fc7399b45373..b945c1d3a743 100644 --- a/security/smack/smack_netfilter.c +++ b/security/smack/smack_netfilter.c @@ -18,27 +18,7 @@ #include #include "smack.h" -#if IS_ENABLED(CONFIG_IPV6) - -static unsigned int smack_ipv6_output(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -{ - struct sock *sk = skb_to_full_sk(skb); - struct socket_smack *ssp; - struct smack_known *skp; - - if (sk && sk->sk_security) { - ssp = sk->sk_security; - skp = ssp->smk_out; - skb->secmark = skp->smk_secid; - } - - return NF_ACCEPT; -} -#endif /* IPV6 */ - -static unsigned int smack_ipv4_output(void *priv, +static unsigned int smack_ip_output(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -57,14 +37,14 @@ static unsigned int smack_ipv4_output(void *priv, static const struct nf_hook_ops smack_nf_ops[] = { { - .hook = smack_ipv4_output, + .hook = smack_ip_output, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_SELINUX_FIRST, }, #if IS_ENABLED(CONFIG_IPV6) { - .hook = smack_ipv6_output, + .hook = smack_ip_output, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_SELINUX_FIRST, From b57d02091b8f5eae1fce5652bb2b53857cd3c720 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Wed, 13 Oct 2021 14:56:43 -0700 Subject: [PATCH 5/7] Smack: fix W=1 build warnings A couple of functions had malformed comment blocks. Namespace parameters were added without updating the comment blocks. These are all repaired in the Smack code, so "% make W=1 security/smack" is warning free. Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5ea4815a0242..8cbcb89bbbe3 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -391,7 +391,7 @@ static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead, /** * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* - * @mode - input mode in form of PTRACE_MODE_* + * @mode: input mode in form of PTRACE_MODE_* * * Returns a converted MAY_* mode usable by smack rules */ @@ -1215,6 +1215,7 @@ static int smack_inode_getattr(const struct path *path) /** * smack_inode_setxattr - Smack check for setting xattrs + * @mnt_userns: active user namespace * @dentry: the object * @name: name of the attribute * @value: value of the attribute @@ -1341,6 +1342,7 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) /** * smack_inode_removexattr - Smack check on removexattr + * @mnt_userns: active user namespace * @dentry: the object * @name: name of the attribute * @@ -1400,6 +1402,7 @@ static int smack_inode_removexattr(struct user_namespace *mnt_userns, /** * smack_inode_getsecurity - get smack xattrs + * @mnt_userns: active user namespace * @inode: the object * @name: attribute name * @buffer: where to put the result @@ -1621,13 +1624,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, } /** - * smack_mmap_file : - * Check permissions for a mmap operation. The @file may be NULL, e.g. - * if mapping anonymous memory. - * @file contains the file structure for file to map (may be NULL). - * @reqprot contains the protection requested by the application. - * @prot contains the protection that will be applied by the kernel. - * @flags contains the operational flags. + * smack_mmap_file - Check permissions for a mmap operation. + * @file: contains the file structure for file to map (may be NULL). + * @reqprot: contains the protection requested by the application. + * @prot: contains the protection that will be applied by the kernel. + * @flags: contains the operational flags. + * + * The @file may be NULL, e.g. if mapping anonymous memory. + * * Return 0 if permission is granted. */ static int smack_mmap_file(struct file *file, @@ -3054,7 +3058,7 @@ static int smack_sem_associate(struct kern_ipc_perm *isp, int semflg) } /** - * smack_sem_shmctl - Smack access check for sem + * smack_sem_semctl - Smack access check for sem * @isp: the object * @cmd: what it wants to do * @@ -3200,7 +3204,7 @@ static int smack_msg_queue_msgsnd(struct kern_ipc_perm *isp, struct msg_msg *msg } /** - * smack_msg_queue_msgsnd - Smack access check for msg_queue + * smack_msg_queue_msgrcv - Smack access check for msg_queue * @isp: the object * @msg: unused * @target: unused @@ -3209,8 +3213,10 @@ static int smack_msg_queue_msgsnd(struct kern_ipc_perm *isp, struct msg_msg *msg * * Returns 0 if current has read and write access, error code otherwise */ -static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp, struct msg_msg *msg, - struct task_struct *target, long type, int mode) +static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp, + struct msg_msg *msg, + struct task_struct *target, long type, + int mode) { return smk_curacc_msq(isp, MAY_READWRITE); } From f91488ee15bd3cac467e2d6a361fc2d34d1052ae Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 19 Oct 2021 20:54:31 +0900 Subject: [PATCH 6/7] smackfs: use __GFP_NOFAIL for smk_cipso_doi() syzbot is reporting kernel panic at smk_cipso_doi() due to memory allocation fault injection [1]. The reason for need to use panic() was not explained. But since no fix was proposed for 18 months, for now let's use __GFP_NOFAIL for utilizing syzbot resource on other bugs. Link: https://syzkaller.appspot.com/bug?extid=89731ccb6fec15ce1c22 [1] Reported-by: syzbot Signed-off-by: Tetsuo Handa Signed-off-by: Casey Schaufler --- security/smack/smackfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 9d853c0e55b8..89989d28ffc5 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -693,9 +693,7 @@ static void smk_cipso_doi(void) printk(KERN_WARNING "%s:%d remove rc = %d\n", __func__, __LINE__, rc); - doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL); - if (doip == NULL) - panic("smack: Failed to initialize cipso DOI.\n"); + doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL | __GFP_NOFAIL); doip->map.std = NULL; doip->doi = smk_cipso_doi_value; doip->type = CIPSO_V4_MAP_PASS; From 0934ad42bb2c5df90a1b9de690f93de735b622fe Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 19 Oct 2021 20:27:26 +0900 Subject: [PATCH 7/7] smackfs: use netlbl_cfg_cipsov4_del() for deleting cipso_v4_doi syzbot is reporting UAF at cipso_v4_doi_search() [1], for smk_cipso_doi() is calling kfree() without removing from the cipso_v4_doi_list list after netlbl_cfg_cipsov4_map_add() returned an error. We need to use netlbl_cfg_cipsov4_del() in order to remove from the list and wait for RCU grace period before kfree(). Link: https://syzkaller.appspot.com/bug?extid=93dba5b91f0fed312cbd [1] Reported-by: syzbot Signed-off-by: Tetsuo Handa Fixes: 6c2e8ac0953fccdd ("netlabel: Update kernel configuration API") Signed-off-by: Casey Schaufler --- security/smack/smackfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 89989d28ffc5..658eab05599e 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -712,7 +712,7 @@ static void smk_cipso_doi(void) if (rc != 0) { printk(KERN_WARNING "%s:%d map add rc = %d\n", __func__, __LINE__, rc); - kfree(doip); + netlbl_cfg_cipsov4_del(doip->doi, &nai); return; } }