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>
This commit is contained in:
committed by
David S. Miller
parent
d8a9b38f83
commit
4d295e5461
+1
-44
@@ -335,49 +335,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)
|
||||
{
|
||||
@@ -396,7 +353,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,
|
||||
|
||||
Reference in New Issue
Block a user