14 #include <linux/kernel.h>
17 #include <linux/types.h>
19 #include <linux/icmpv6.h>
20 #include <linux/socket.h>
22 #include <linux/filter.h>
25 #include <linux/export.h>
31 #include <asm/uaccess.h>
34 static inline int iov_from_user_compat_to_kern(
struct iovec *kiov,
35 struct compat_iovec __user *uiov32,
44 if (
get_user(len, &uiov32->iov_len) ||
75 kmsg->
msg_iov = compat_ptr(tmp2);
98 tot_len = iov_from_user_compat_to_kern(kern_iov,
108 #define CMSG_COMPAT_ALIGN(len) ALIGN((len), sizeof(s32))
110 #define CMSG_COMPAT_DATA(cmsg) \
111 ((void __user *)((char __user *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))))
112 #define CMSG_COMPAT_SPACE(len) \
113 (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len))
114 #define CMSG_COMPAT_LEN(len) \
115 (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len))
117 #define CMSG_COMPAT_FIRSTHDR(msg) \
118 (((msg)->msg_controllen) >= sizeof(struct compat_cmsghdr) ? \
119 (struct compat_cmsghdr __user *)((msg)->msg_control) : \
120 (struct compat_cmsghdr __user *)NULL)
122 #define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \
123 ((ucmlen) >= sizeof(struct compat_cmsghdr) && \
124 (ucmlen) <= (unsigned long) \
125 ((mhdr)->msg_controllen - \
126 ((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
128 static inline struct compat_cmsghdr
__user *cmsg_compat_nxthdr(
struct msghdr *
msg,
129 struct compat_cmsghdr __user *cmsg,
int cmsg_len)
135 return (
struct compat_cmsghdr
__user *)
ptr;
143 unsigned char *stackbuf,
int stackbuf_size)
145 struct compat_cmsghdr __user *ucmsg;
146 struct cmsghdr *kcmsg, *kcmsg_base;
152 kcmsg_base = kcmsg = (
struct cmsghdr *)stackbuf;
154 while (ucmsg !=
NULL) {
155 if (
get_user(ucmlen, &ucmsg->cmsg_len))
166 ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
176 if (kcmlen > stackbuf_size)
184 while (ucmsg !=
NULL) {
191 if ((
char *)kcmsg_base + kcmlen - (
char *)kcmsg <
CMSG_ALIGN(tmp))
203 kcmsg = (
struct cmsghdr *)((
char *)kcmsg +
tmp);
204 ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
215 if (kcmsg_base != (
struct cmsghdr *)stackbuf)
222 struct compat_cmsghdr __user *cm = (
struct compat_cmsghdr __user *) kmsg->
msg_control;
223 struct compat_cmsghdr cmhdr;
233 if (!COMPAT_USE_64BIT_TIME) {
246 for (i = 0; i <
count; i++) {
251 len =
sizeof(cts[0]) * count;
260 cmhdr.cmsg_level =
level;
261 cmhdr.cmsg_type =
type;
262 cmhdr.cmsg_len = cmlen;
278 struct compat_cmsghdr __user *cm = (
struct compat_cmsghdr __user *) kmsg->
msg_control;
279 int fdmax = (kmsg->
msg_controllen -
sizeof(
struct compat_cmsghdr)) /
sizeof(
int);
280 int fdnum = scm->
fp->count;
313 err =
put_user(cmlen, &cm->cmsg_len);
330 static int do_set_attach_filter(
struct socket *
sock,
int level,
int optname,
331 char __user *optval,
unsigned int optlen)
333 struct compat_sock_fprog
__user *fprog32 = (
struct compat_sock_fprog
__user *)optval;
350 static int do_set_sock_timeout(
struct socket *sock,
int level,
351 int optname,
char __user *optval,
unsigned int optlen)
358 if (optlen <
sizeof(*up))
372 static int compat_sock_setsockopt(
struct socket *sock,
int level,
int optname,
373 char __user *optval,
unsigned int optlen)
376 return do_set_attach_filter(sock, level, optname,
379 return do_set_sock_timeout(sock, level, optname, optval, optlen);
385 char __user *optval,
unsigned int optlen)
391 err = security_socket_setsockopt(sock, level, optname);
398 err = compat_sock_setsockopt(sock, level,
399 optname, optval, optlen);
400 else if (sock->
ops->compat_setsockopt)
401 err = sock->
ops->compat_setsockopt(sock, level,
402 optname, optval, optlen);
404 err = sock->
ops->setsockopt(sock, level,
405 optname, optval, optlen);
411 static int do_get_sock_timeout(
struct socket *sock,
int level,
int optname,
412 char __user *optval,
int __user *optlen)
422 if (len <
sizeof(*up))
431 if (
put_user(
sizeof(*up), optlen) ||
440 static int compat_sock_getsockopt(
struct socket *sock,
int level,
int optname,
441 char __user *optval,
int __user *optlen)
444 return do_get_sock_timeout(sock, level, optname, optval, optlen);
454 if (COMPAT_USE_64BIT_TIME)
461 tv = ktime_to_timeval(sk->
sk_stamp);
466 tv = ktime_to_timeval(sk->
sk_stamp);
482 if (COMPAT_USE_64BIT_TIME)
489 ts = ktime_to_timespec(sk->
sk_stamp);
494 ts = ktime_to_timespec(sk->
sk_stamp);
505 char __user *optval,
int __user *optlen)
511 err = security_socket_getsockopt(sock, level, optname);
518 err = compat_sock_getsockopt(sock, level,
519 optname, optval, optlen);
520 else if (sock->
ops->compat_getsockopt)
521 err = sock->
ops->compat_getsockopt(sock, level,
522 optname, optval, optlen);
524 err = sock->
ops->getsockopt(sock, level,
525 optname, optval, optlen);
555 #define __COMPAT_GF0_SIZE (sizeof(struct compat_group_filter) - \
556 sizeof(struct __kernel_sockaddr_storage))
560 char __user *optval,
unsigned int optlen,
561 int (*setsockopt)(
struct sock *,
int,
int,
char __user *,
unsigned int))
563 char __user *koptval = optval;
564 int koptlen = optlen;
582 koptval = (
char __user *)kgr;
606 koptval = (
char __user *)kgsr;
622 sizeof(struct compat_group_filter);
633 numsrc *
sizeof(kgf->
gf_slist[0]))))
635 koptval = (
char __user *)kgf;
642 return setsockopt(sock, level, optname, koptval, koptlen);
647 char __user *optval,
int __user *optlen,
648 int (*getsockopt)(
struct sock *,
int,
int,
char __user *,
int __user *))
657 return getsockopt(sock, level, optname, optval, optlen);
665 klen = ulen +
sizeof(*kgf) -
sizeof(*gf32);
687 err = getsockopt(sock, level, optname, (
char __user *)kgf, koptlen);
695 ulen = klen - (
sizeof(*kgf)-
sizeof(*gf32));
714 copylen = numsrc *
sizeof(gf32->gf_slist[0]);
726 #define AL(x) ((x) * sizeof(u32))
727 static unsigned char nas[21] = {
741 unsigned int vlen,
unsigned int flags)
765 unsigned int vlen,
unsigned int flags,
771 if (COMPAT_USE_64BIT_TIME)
809 ret =
sys_bind(a0, compat_ptr(a1), a[2]);
818 ret =
sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
830 ret =
sys_send(a0, compat_ptr(a1), a[2], a[3]);
833 ret =
sys_sendto(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), a[5]);
840 compat_ptr(a[4]), compat_ptr(a[5]));
847 compat_ptr(a[3]), a[4]);
851 compat_ptr(a[3]), compat_ptr(a[4]));
867 ret =
sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]);