summaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2020-07-17 08:23:13 +0200
committerDavid S. Miller <davem@davemloft.net>2020-07-19 18:16:40 -0700
commit4d295e54611509854a12c26f95a6f4430731d614 (patch)
tree11f6ced04b1be8c3c59e8d62031c1e4c9f157a36 /net/core
parentd8a9b38f83ea91341f80beb0a07a5777c6acf7a4 (diff)
downloadlinux-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.c23
-rw-r--r--net/core/sock.c30
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)) {