History

packet: compat support for sock_fprog

Socket option PACKET_FANOUT_DATA takes a struct sock_fprog as argument if PACKET_FANOUT has mode PACKET_FANOUT_CBPF. This structure contains a pointer into user memory. If userland is 32-bit and kernel is 64-bit the two disagree about the layout of struct sock_fprog. Add compat setsockopt support to convert a 32-bit compat_sock_fprog to a 64-bit sock_fprog. This is analogous to compat_sock_fprog support for SO_REUSEPORT added in commit 1957598840f4 ("soreuseport: add compat case for setsockopt SO_ATTACH_REUSEPORT_CBPF").

Willem de Bruijn committed 10 years ago

Commit 719c44d1 parent ca8bdaf3 files · +41 −2Browse files

Unified · Split

3 files
  1. include/net/compat.h +1 −0
  2. net/compat.c +15 −2
  3. net/packet/af_packet.c +25 −0
include/net/compat.h+1−0
@@ -42,6 +42,7 @@ int compat_sock_get_timestampns(struct sock *, struct timespec __user *); · 41 unmodified lines
4242
4343 int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
4444 struct sockaddr __user **, struct iovec **);
45+struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval);
4546 asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
4647 unsigned int);
4748 asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
net/compat.c+15−2
@@ -309,8 +309,8 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) · 308 unmodified lines
309309 __scm_destroy(scm);
310310 }
311311
312−static int do_set_attach_filter(struct socket *sock, int level, int optname,
313− char __user *optval, unsigned int optlen)
312+/* allocate a 64-bit sock_fprog on the user stack for duration of syscall. */
313+struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval)
314314 {
315315 struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
316316 struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
@@ -323,6 +323,19 @@ static int do_set_attach_filter(struct socket *sock, int level, int optname, · 6 unmodified lines
323323 __get_user(ptr, &fprog32->filter) ||
324324 __put_user(len, &kfprog->len) ||
325325 __put_user(compat_ptr(ptr), &kfprog->filter))
326+ return NULL;
327+
328+ return kfprog;
329+}
330+EXPORT_SYMBOL_GPL(get_compat_bpf_fprog);
331+
332+static int do_set_attach_filter(struct socket *sock, int level, int optname,
333+ char __user *optval, unsigned int optlen)
334+{
335+ struct sock_fprog __user *kfprog;
336+
337+ kfprog = get_compat_bpf_fprog(optval);
338+ if (!kfprog)
326339 return -EFAULT;
327340
328341 return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
net/packet/af_packet.c+25−0
@@ -93,6 +93,7 @@ · 92 unmodified lines
9393 #include <net/inet_common.h>
9494 #endif
9595 #include <linux/bpf.h>
96+#include <net/compat.h>
9697
9798 #include "internal.h"
9899
@@ -3940,6 +3941,27 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, · 3841 unmodified lines
39403941 }
39413942
39423943
3944+#ifdef CONFIG_COMPAT
3945+static int compat_packet_setsockopt(struct socket *sock, int level, int optname,
3946+ char __user *optval, unsigned int optlen)
3947+{
3948+ struct packet_sock *po = pkt_sk(sock->sk);
3949+
3950+ if (level != SOL_PACKET)
3951+ return -ENOPROTOOPT;
3952+
3953+ if (optname == PACKET_FANOUT_DATA &&
3954+ po->fanout && po->fanout->type == PACKET_FANOUT_CBPF) {
3955+ optval = (char __user *)get_compat_bpf_fprog(optval);
3956+ if (!optval)
3957+ return -EFAULT;
3958+ optlen = sizeof(struct sock_fprog);
3959+ }
3960+
3961+ return packet_setsockopt(sock, level, optname, optval, optlen);
3962+}
3963+#endif
3964+
39433965 static int packet_notifier(struct notifier_block *this,
39443966 unsigned long msg, void *ptr)
39453967 {
@@ -4416,6 +4438,9 @@ static const struct proto_ops packet_ops = { · 470 unmodified lines
44164438 .shutdown = sock_no_shutdown,
44174439 .setsockopt = packet_setsockopt,
44184440 .getsockopt = packet_getsockopt,
4441+#ifdef CONFIG_COMPAT
4442+ .compat_setsockopt = compat_packet_setsockopt,
4443+#endif
44194444 .sendmsg = packet_sendmsg,
44204445 .recvmsg = packet_recvmsg,
44214446 .mmap = packet_mmap,