BACKPORT: 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.

Change-Id: Ie62fb625ef94ad6d2148531c279e87e82524aae0
Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
Christoph Hellwig 2020-07-17 08:23:13 +02:00 • committed by basamaryan
commit a13a4c9122
No known key found for this signature in database
GPG key ID: 210D5384FB2A5885
6 changed files with 40 additions and 96 deletions

View file

@ -318,49 +318,6 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
__scm_destroy(scm);
}
/* allocate a 64-bit sock_fprog on the user stack for duration of syscall. */
struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval)
{
struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
struct compat_sock_fprog f32;
struct sock_fprog f;
if (copy_from_user(&f32, fprog32, sizeof(*fprog32)))
return NULL;
memset(&f, 0, sizeof(f));
f.len = f32.len;
f.filter = compat_ptr(f32.filter);
if (copy_to_user(kfprog, &f, sizeof(struct sock_fprog)))
return NULL;
return kfprog;
}
EXPORT_SYMBOL_GPL(get_compat_bpf_fprog);
static int do_set_attach_filter(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
struct sock_fprog __user *kfprog;
kfprog = get_compat_bpf_fprog(optval);
if (!kfprog)
return -EFAULT;
return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
sizeof(struct sock_fprog));
}
static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
if (optname == SO_ATTACH_FILTER ||
optname == SO_ATTACH_REUSEPORT_CBPF)
return do_set_attach_filter(sock, level, optname,
optval, optlen);
return sock_setsockopt(sock, level, optname, optval, optlen);
}
static int __compat_sys_setsockopt(int fd, int level, int optname,
char __user *optval, unsigned int optlen)
{
@ -379,7 +336,7 @@ static int __compat_sys_setsockopt(int fd, int level, int optname,
}
if (level == SOL_SOCKET)
err = compat_sock_setsockopt(sock, level,
err = sock_setsockopt(sock, level,
optname, optval, optlen);
else if (sock->ops->compat_setsockopt)
err = sock->ops->compat_setsockopt(sock, level,