diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 18980472f5b0..045646da97cc 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -410,14 +410,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 || @@ -493,14 +490,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 || @@ -579,14 +573,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); @@ -598,7 +589,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); @@ -627,14 +617,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; } 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; } 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; } 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 || diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 85404e7c3114..02d795fe3d7f 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 */ 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; } diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 9010a3632d6f..00eed842c491 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -649,14 +649,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);