From 0b884d25f5212bd0323d179c570962bbf822e330 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:12:07 -0400 Subject: [PATCH 1/9] sel_write_validatetrans(): don't open-code memdup_user_nul() Signed-off-by: Al Viro --- security/selinux/selinuxfs.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 50062e70140d..0940892de84d 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -656,14 +656,12 @@ static ssize_t sel_write_validatetrans(struct file *file, if (*ppos != 0) goto out; - rc = -ENOMEM; - req = kzalloc(count + 1, GFP_KERNEL); - if (!req) - goto out; - - rc = -EFAULT; - if (copy_from_user(req, buf, count)) + req = memdup_user_nul(buf, count); + if (IS_ERR(req)) { + rc = PTR_ERR(req); + req = NULL; goto out; + } rc = -ENOMEM; oldcon = kzalloc(count + 1, GFP_KERNEL); From 02412e9b4e54e124fe0890b30b891d3e6f3adf38 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:15:25 -0400 Subject: [PATCH 2/9] ima_write_policy(): don't open-code memdup_user_nul() Signed-off-by: Al Viro --- security/integrity/ima/ima_fs.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index ca303e5d2b94..ad491c51e833 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -323,16 +323,11 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, if (*ppos != 0) goto out; - result = -ENOMEM; - data = kmalloc(datalen + 1, GFP_KERNEL); - if (!data) + data = memdup_user_nul(buf, datalen); + if (IS_ERR(data)) { + result = PTR_ERR(data); goto out; - - *(data + datalen) = '\0'; - - result = -EFAULT; - if (copy_from_user(data, buf, datalen)) - goto out_free; + } result = mutex_lock_interruptible(&ima_write_mutex); if (result < 0) From 7f2d17c67ae3a0954e35092564f1cf58726b2c44 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:16:28 -0400 Subject: [PATCH 3/9] xfrm_user_policy(): don't open-code memdup_user() Signed-off-by: Al Viro --- net/xfrm/xfrm_state.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index fc3c5aa38754..5780cdad2260 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2023,13 +2023,9 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen if (optlen <= 0 || optlen > PAGE_SIZE) return -EMSGSIZE; - data = kmalloc(optlen, GFP_KERNEL); - if (!data) - return -ENOMEM; - - err = -EFAULT; - if (copy_from_user(data, optval, optlen)) - goto out; + data = memdup_user(optval, optlen); + if (IS_ERR(data)) + return PTR_ERR(data); err = -EINVAL; rcu_read_lock(); @@ -2047,7 +2043,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen err = 0; } -out: kfree(data); return err; } From aa47cc1c3c7bd0df82b241aa2e3df36977b0c24b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:20:33 -0400 Subject: [PATCH 4/9] irda: don't open-code memdup_user() and no, GFP_ATOMIC does not make any sense there... Signed-off-by: Al Viro --- net/irda/af_irda.c | 48 ++++++++++++---------------------------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 8d77ad5cadaf..2e6990f8b80b 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1901,16 +1901,10 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, goto out; } - ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); - if (ias_opt == NULL) { - err = -ENOMEM; - goto out; - } - /* Copy query to the driver. */ - if (copy_from_user(ias_opt, optval, optlen)) { - kfree(ias_opt); - err = -EFAULT; + ias_opt = memdup_user(optval, optlen); + if (IS_ERR(ias_opt)) { + err = PTR_ERR(ias_opt); goto out; } @@ -2032,16 +2026,10 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, goto out; } - ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); - if (ias_opt == NULL) { - err = -ENOMEM; - goto out; - } - /* Copy query to the driver. */ - if (copy_from_user(ias_opt, optval, optlen)) { - kfree(ias_opt); - err = -EFAULT; + ias_opt = memdup_user(optval, optlen); + if (IS_ERR(ias_opt)) { + err = PTR_ERR(ias_opt); goto out; } @@ -2317,16 +2305,10 @@ bed: goto out; } - ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); - if (ias_opt == NULL) { - err = -ENOMEM; - goto out; - } - /* Copy query to the driver. */ - if (copy_from_user(ias_opt, optval, len)) { - kfree(ias_opt); - err = -EFAULT; + ias_opt = memdup_user(optval, len); + if (IS_ERR(ias_opt)) { + err = PTR_ERR(ias_opt); goto out; } @@ -2381,16 +2363,10 @@ bed: goto out; } - ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC); - if (ias_opt == NULL) { - err = -ENOMEM; - goto out; - } - /* Copy query to the driver. */ - if (copy_from_user(ias_opt, optval, len)) { - kfree(ias_opt); - err = -EFAULT; + ias_opt = memdup_user(optval, len); + if (IS_ERR(ias_opt)) { + err = PTR_ERR(ias_opt); goto out; } From 43727da90ec8955f1351ad582c6bc8f1c1ab8ab8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:22:53 -0400 Subject: [PATCH 5/9] do_ipv6_setsockopt(): don't open-code memdup_user() Signed-off-by: Al Viro --- net/ipv6/ipv6_sockglue.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index a531ba032b85..f8298c9a3160 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -735,14 +735,9 @@ done: retv = -ENOBUFS; break; } - gsf = kmalloc(optlen, GFP_KERNEL); - if (!gsf) { - retv = -ENOBUFS; - break; - } - retv = -EFAULT; - if (copy_from_user(gsf, optval, optlen)) { - kfree(gsf); + gsf = memdup_user(optval, optlen); + if (IS_ERR(gsf)) { + retv = PTR_ERR(gsf); break; } /* numsrc >= (4G-140)/128 overflow in 32 bits */ From a2c841d94209f5775d354b563f4dccd76b876dc0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:26:06 -0400 Subject: [PATCH 6/9] do_ip_setsockopt(): don't open-code memdup_user() Signed-off-by: Al Viro --- net/ipv4/ip_sockglue.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index ec4fe3d4b5c9..ecc4b4a2413e 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -934,14 +934,9 @@ static int do_ip_setsockopt(struct sock *sk, int level, err = -ENOBUFS; break; } - msf = kmalloc(optlen, GFP_KERNEL); - if (!msf) { - err = -ENOBUFS; - break; - } - err = -EFAULT; - if (copy_from_user(msf, optval, optlen)) { - kfree(msf); + msf = memdup_user(optval, optlen); + if (IS_ERR(msf)) { + err = PTR_ERR(msf); break; } /* numsrc >= (1G-4) overflow in 32 bits */ @@ -1090,14 +1085,11 @@ static int do_ip_setsockopt(struct sock *sk, int level, err = -ENOBUFS; break; } - gsf = kmalloc(optlen, GFP_KERNEL); - if (!gsf) { - err = -ENOBUFS; + gsf = memdup_user(optval, optlen); + if (IS_ERR(gsf)) { + err = PTR_ERR(gsf); break; } - err = -EFAULT; - if (copy_from_user(gsf, optval, optlen)) - goto mc_msf_out; /* numsrc >= (4G-140)/128 overflow in 32 bits */ if (gsf->gf_numsrc >= 0x1ffffff || From 30e7e3ecf39e578ffab6d5944c79c1d30dee0d3f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:31:26 -0400 Subject: [PATCH 7/9] ethtool: don't open-code memdup_user() Signed-off-by: Al Viro --- net/core/ethtool.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 03111a2d6653..674b6c9cec18 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -2322,16 +2322,12 @@ static int ethtool_set_tunable(struct net_device *dev, void __user *useraddr) ret = ethtool_tunable_valid(&tuna); if (ret) return ret; - data = kmalloc(tuna.len, GFP_USER); - if (!data) - return -ENOMEM; useraddr += sizeof(tuna); - ret = -EFAULT; - if (copy_from_user(data, useraddr, tuna.len)) - goto out; + data = memdup_user(useraddr, tuna.len); + if (IS_ERR(data)) + return PTR_ERR(data); ret = ops->set_tunable(dev, &tuna, data); -out: kfree(data); return ret; } @@ -2507,18 +2503,14 @@ static int set_phy_tunable(struct net_device *dev, void __user *useraddr) ret = ethtool_phy_tunable_valid(&tuna); if (ret) return ret; - data = kmalloc(tuna.len, GFP_USER); - if (!data) - return -ENOMEM; useraddr += sizeof(tuna); - ret = -EFAULT; - if (copy_from_user(data, useraddr, tuna.len)) - goto out; + data = memdup_user(useraddr, tuna.len); + if (IS_ERR(data)) + return PTR_ERR(data); mutex_lock(&phydev->lock); ret = phydev->drv->set_tunable(phydev, &tuna, data); mutex_unlock(&phydev->lock); -out: kfree(data); return ret; } From a9bd8dfa539493db265e46a496c1a89279ab31d1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:39:01 -0400 Subject: [PATCH 8/9] kimage_file_prepare_segments(): don't open-code memdup_user() Signed-off-by: Al Viro --- kernel/kexec_file.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index b118735fea9d..766e7e4d3ad9 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -162,16 +162,10 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, } if (cmdline_len) { - image->cmdline_buf = kzalloc(cmdline_len, GFP_KERNEL); - if (!image->cmdline_buf) { - ret = -ENOMEM; - goto out; - } - - ret = copy_from_user(image->cmdline_buf, cmdline_ptr, - cmdline_len); - if (ret) { - ret = -EFAULT; + image->cmdline_buf = memdup_user(cmdline_ptr, cmdline_len); + if (IS_ERR(image->cmdline_buf)) { + ret = PTR_ERR(image->cmdline_buf); + image->cmdline_buf = NULL; goto out; } From e4448ed87ccdbacb74871736f63220642242b32f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 May 2017 18:43:00 -0400 Subject: [PATCH 9/9] bpf: don't open-code memdup_user() Signed-off-by: Al Viro --- kernel/bpf/syscall.c | 45 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index fd2411fd6914..4b8b10bddfde 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -322,14 +322,11 @@ static int map_lookup_elem(union bpf_attr *attr) if (IS_ERR(map)) return PTR_ERR(map); - err = -ENOMEM; - key = kmalloc(map->key_size, GFP_USER); - if (!key) + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); goto err_put; - - err = -EFAULT; - if (copy_from_user(key, ukey, map->key_size) != 0) - goto free_key; + } if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH || @@ -402,14 +399,11 @@ static int map_update_elem(union bpf_attr *attr) if (IS_ERR(map)) return PTR_ERR(map); - err = -ENOMEM; - key = kmalloc(map->key_size, GFP_USER); - if (!key) + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); goto err_put; - - err = -EFAULT; - if (copy_from_user(key, ukey, map->key_size) != 0) - goto free_key; + } if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH || @@ -488,14 +482,11 @@ static int map_delete_elem(union bpf_attr *attr) if (IS_ERR(map)) return PTR_ERR(map); - err = -ENOMEM; - key = kmalloc(map->key_size, GFP_USER); - if (!key) + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); goto err_put; - - err = -EFAULT; - if (copy_from_user(key, ukey, map->key_size) != 0) - goto free_key; + } preempt_disable(); __this_cpu_inc(bpf_prog_active); @@ -507,7 +498,6 @@ static int map_delete_elem(union bpf_attr *attr) if (!err) trace_bpf_map_delete_elem(map, ufd, key); -free_key: kfree(key); err_put: fdput(f); @@ -536,14 +526,11 @@ static int map_get_next_key(union bpf_attr *attr) return PTR_ERR(map); if (ukey) { - err = -ENOMEM; - key = kmalloc(map->key_size, GFP_USER); - if (!key) + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); goto err_put; - - err = -EFAULT; - if (copy_from_user(key, ukey, map->key_size) != 0) - goto free_key; + } } else { key = NULL; }