diff --git a/include/linux/socket.h b/include/linux/socket.h index d0e77f6..86ecf27 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -272,8 +272,10 @@ struct ucred { descriptor received through SCM_RIGHTS */ #if defined(CONFIG_COMPAT) +#define MSG_CMSG_COMPAT64 0x20000000 /* This message needs 64 bit timestamp */ #define MSG_CMSG_COMPAT 0x80000000 /* This message needs 32 bit fixups */ #else +#define MSG_CMSG_COMPAT64 0 /* We never have 64 bit timestamp */ #define MSG_CMSG_COMPAT 0 /* We never have 32 bit fixups */ #endif diff --git a/net/compat.c b/net/compat.c index c578d93..555b951 100644 --- a/net/compat.c +++ b/net/compat.c @@ -229,24 +229,26 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat return 0; /* XXX: return error? check spec. */ } - if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { - struct timeval *tv = (struct timeval *)data; - ctv.tv_sec = tv->tv_sec; - ctv.tv_usec = tv->tv_usec; - data = &ctv; - len = sizeof(ctv); - } - if (level == SOL_SOCKET && - (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) { - int count = type == SCM_TIMESTAMPNS ? 1 : 3; - int i; - struct timespec *ts = (struct timespec *)data; - for (i = 0; i < count; i++) { - cts[i].tv_sec = ts[i].tv_sec; - cts[i].tv_nsec = ts[i].tv_nsec; + if ((MSG_CMSG_COMPAT64 & kmsg->msg_flags) == 0) { + if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { + struct timeval *tv = (struct timeval *)data; + ctv.tv_sec = tv->tv_sec; + ctv.tv_usec = tv->tv_usec; + data = &ctv; + len = sizeof(ctv); + } + if (level == SOL_SOCKET && + (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) { + int count = type == SCM_TIMESTAMPNS ? 1 : 3; + int i; + struct timespec *ts = (struct timespec *)data; + for (i = 0; i < count; i++) { + cts[i].tv_sec = ts[i].tv_sec; + cts[i].tv_nsec = ts[i].tv_nsec; + } + data = &cts; + len = sizeof(cts[0]) * count; } - data = &cts; - len = sizeof(cts[0]) * count; } cmlen = CMSG_COMPAT_LEN(len); @@ -781,6 +783,52 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, return datagrams; } +asmlinkage long compat_sys_sendmsg64(int fd, struct compat_msghdr __user *msg, + unsigned flags) +{ + return sys_sendmsg(fd, (struct msghdr __user *)msg, + flags | MSG_CMSG_COMPAT | MSG_CMSG_COMPAT64); +} + +asmlinkage long compat_sys_sendmmsg64(int fd, struct compat_mmsghdr __user *mmsg, + unsigned vlen, unsigned int flags) +{ + return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT | MSG_CMSG_COMPAT64); +} + +asmlinkage long compat_sys_recvmsg64(int fd, struct compat_msghdr __user *msg, + unsigned int flags) +{ + return sys_recvmsg(fd, (struct msghdr __user *)msg, + flags | MSG_CMSG_COMPAT | MSG_CMSG_COMPAT64); +} + +asmlinkage long compat_sys_recv64(int fd, void __user *buf, size_t len, + unsigned flags) +{ + return sys_recv(fd, buf, len, + flags | MSG_CMSG_COMPAT | MSG_CMSG_COMPAT64); +} + +asmlinkage long compat_sys_recvfrom64(int fd, void __user *buf, size_t len, + unsigned flags, struct sockaddr __user *addr, + int __user *addrlen) +{ + return sys_recvfrom(fd, buf, len, + flags | MSG_CMSG_COMPAT | MSG_CMSG_COMPAT64, + addr, addrlen); +} + +asmlinkage long compat_sys_recvmmsg64(int fd, struct compat_mmsghdr __user *mmsg, + unsigned vlen, unsigned int flags, + struct timespec __user *timeout) +{ + return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT | MSG_CMSG_COMPAT64, + timeout); +} + asmlinkage long compat_sys_socketcall(int call, u32 __user *args) { int ret; diff --git a/net/socket.c b/net/socket.c index 24a7740..fae5472 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2133,7 +2133,7 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, total_len = err; cmsg_ptr = (unsigned long)msg_sys->msg_control; - msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); + msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT|MSG_CMSG_COMPAT64); if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT;