]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - security/smack/smack_lsm.c
smack: use GFP_NOFS while holding inode_smack::smk_lock
[mirror_ubuntu-bionic-kernel.git] / security / smack / smack_lsm.c
index 1211c333c722be6bc3ff03cb09f7a88bbdf2bff6..80ef8813ba9d7e604168122820b135a7206ea613 100644 (file)
@@ -269,7 +269,7 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
        if (!(ip->i_opflags & IOP_XATTR))
                return ERR_PTR(-EOPNOTSUPP);
 
-       buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
+       buffer = kzalloc(SMK_LONGLABEL, GFP_NOFS);
        if (buffer == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -908,7 +908,8 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
 
                if (rc != 0)
                        return rc;
-       } else if (bprm->unsafe)
+       }
+       if (bprm->unsafe & ~LSM_UNSAFE_PTRACE)
                return -EPERM;
 
        bsp->smk_task = isp->smk_task;
@@ -3768,15 +3769,19 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        struct smack_known *skp = NULL;
        int rc = 0;
        struct smk_audit_info ad;
+       u16 family = sk->sk_family;
 #ifdef CONFIG_AUDIT
        struct lsm_network_audit net;
 #endif
 #if IS_ENABLED(CONFIG_IPV6)
        struct sockaddr_in6 sadd;
        int proto;
+
+       if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+               family = PF_INET;
 #endif /* CONFIG_IPV6 */
 
-       switch (sk->sk_family) {
+       switch (family) {
        case PF_INET:
 #ifdef CONFIG_SECURITY_SMACK_NETFILTER
                /*
@@ -3794,7 +3799,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                 */
                netlbl_secattr_init(&secattr);
 
-               rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
+               rc = netlbl_skbuff_getattr(skb, family, &secattr);
                if (rc == 0)
                        skp = smack_from_secattr(&secattr, ssp);
                else
@@ -3807,7 +3812,7 @@ access_check:
 #endif
 #ifdef CONFIG_AUDIT
                smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-               ad.a.u.net->family = sk->sk_family;
+               ad.a.u.net->family = family;
                ad.a.u.net->netif = skb->skb_iif;
                ipv4_skb_to_auditdata(skb, &ad.a, NULL);
 #endif
@@ -3821,7 +3826,7 @@ access_check:
                rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in,
                                        MAY_WRITE, rc);
                if (rc != 0)
-                       netlbl_skbuff_err(skb, sk->sk_family, rc, 0);
+                       netlbl_skbuff_err(skb, family, rc, 0);
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case PF_INET6:
@@ -3835,9 +3840,11 @@ access_check:
                        skp = smack_ipv6host_label(&sadd);
                if (skp == NULL)
                        skp = smack_net_ambient;
+               if (skb == NULL)
+                       break;
 #ifdef CONFIG_AUDIT
                smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-               ad.a.u.net->family = sk->sk_family;
+               ad.a.u.net->family = family;
                ad.a.u.net->netif = skb->skb_iif;
                ipv6_skb_to_auditdata(skb, &ad.a, NULL);
 #endif /* CONFIG_AUDIT */
@@ -4152,6 +4159,12 @@ static int smack_key_permission(key_ref_t key_ref,
        int request = 0;
        int rc;
 
+       /*
+        * Validate requested permissions
+        */
+       if (perm & ~KEY_NEED_ALL)
+               return -EINVAL;
+
        keyp = key_ref_to_ptr(key_ref);
        if (keyp == NULL)
                return -EINVAL;
@@ -4173,10 +4186,10 @@ static int smack_key_permission(key_ref_t key_ref,
        ad.a.u.key_struct.key = keyp->serial;
        ad.a.u.key_struct.key_desc = keyp->description;
 #endif
-       if (perm & KEY_NEED_READ)
-               request = MAY_READ;
+       if (perm & (KEY_NEED_READ | KEY_NEED_SEARCH | KEY_NEED_VIEW))
+               request |= MAY_READ;
        if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR))
-               request = MAY_WRITE;
+               request |= MAY_WRITE;
        rc = smk_access(tkp, skp, request, &ad);
        rc = smk_bu_note("key access", tkp, skp, request, rc);
        return rc;