diff options
author | Christoph Hellwig <hch@lst.de> | 2020-07-17 08:23:13 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-07-19 18:16:40 -0700 |
commit | 4d295e54611509854a12c26f95a6f4430731d614 (patch) | |
tree | 11f6ced04b1be8c3c59e8d62031c1e4c9f157a36 /net/core | |
parent | d8a9b38f83ea91341f80beb0a07a5777c6acf7a4 (diff) | |
download | linux-4d295e54611509854a12c26f95a6f4430731d614.tar.gz linux-4d295e54611509854a12c26f95a6f4430731d614.tar.bz2 linux-4d295e54611509854a12c26f95a6f4430731d614.zip |
net: simplify cBPF setsockopt compat handling
Add a helper that copies either a native or compat bpf_fprog from
userspace after verifying the length, and remove the compat setsockopt
handlers that now aren't required.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/filter.c | 23 | ||||
-rw-r--r-- | net/core/sock.c | 30 |
2 files changed, 33 insertions, 20 deletions
diff --git a/net/core/filter.c b/net/core/filter.c index bdd2382e655d..2bf6624796d8 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -77,6 +77,29 @@ #include <net/transp_v6.h> #include <linux/btf_ids.h> +int copy_bpf_fprog_from_user(struct sock_fprog *dst, void __user *src, int len) +{ + if (in_compat_syscall()) { + struct compat_sock_fprog f32; + + if (len != sizeof(f32)) + return -EINVAL; + if (copy_from_user(&f32, src, sizeof(f32))) + return -EFAULT; + memset(dst, 0, sizeof(*dst)); + dst->len = f32.len; + dst->filter = compat_ptr(f32.filter); + } else { + if (len != sizeof(*dst)) + return -EINVAL; + if (copy_from_user(dst, src, sizeof(*dst))) + return -EFAULT; + } + + return 0; +} +EXPORT_SYMBOL_GPL(copy_bpf_fprog_from_user); + /** * sk_filter_trim_cap - run a packet through a socket filter * @sk: sock associated with &sk_buff diff --git a/net/core/sock.c b/net/core/sock.c index 11d6f77dd562..e085df794825 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1059,19 +1059,14 @@ set_sndbuf: ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen, optname == SO_SNDTIMEO_OLD); break; - case SO_ATTACH_FILTER: - ret = -EINVAL; - if (optlen == sizeof(struct sock_fprog)) { - struct sock_fprog fprog; - - ret = -EFAULT; - if (copy_from_user(&fprog, optval, sizeof(fprog))) - break; + case SO_ATTACH_FILTER: { + struct sock_fprog fprog; + ret = copy_bpf_fprog_from_user(&fprog, optval, optlen); + if (!ret) ret = sk_attach_filter(&fprog, sk); - } break; - + } case SO_ATTACH_BPF: ret = -EINVAL; if (optlen == sizeof(u32)) { @@ -1085,19 +1080,14 @@ set_sndbuf: } break; - case SO_ATTACH_REUSEPORT_CBPF: - ret = -EINVAL; - if (optlen == sizeof(struct sock_fprog)) { - struct sock_fprog fprog; - - ret = -EFAULT; - if (copy_from_user(&fprog, optval, sizeof(fprog))) - break; + case SO_ATTACH_REUSEPORT_CBPF: { + struct sock_fprog fprog; + ret = copy_bpf_fprog_from_user(&fprog, optval, optlen); + if (!ret) ret = sk_reuseport_attach_filter(&fprog, sk); - } break; - + } case SO_ATTACH_REUSEPORT_EBPF: ret = -EINVAL; if (optlen == sizeof(u32)) { |