Bluetooth: Fix a compile warning in RFCOMM
[linux-2.6.git] / net / compat.c
index 6a2f75f..6def90e 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/gfp.h>
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/file.h>
@@ -21,6 +22,7 @@
 #include <linux/filter.h>
 #include <linux/compat.h>
 #include <linux/security.h>
+#include <linux/export.h>
 
 #include <net/scm.h>
 #include <net/sock.h>
@@ -40,10 +42,12 @@ static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
                compat_size_t len;
 
                if (get_user(len, &uiov32->iov_len) ||
-                  get_user(buf, &uiov32->iov_base)) {
-                       tot_len = -EFAULT;
-                       break;
-               }
+                   get_user(buf, &uiov32->iov_base))
+                       return -EFAULT;
+
+               if (len > INT_MAX - tot_len)
+                       len = INT_MAX - tot_len;
+
                tot_len += len;
                kiov->iov_base = compat_ptr(buf);
                kiov->iov_len = (__kernel_size_t) len;
@@ -80,7 +84,7 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
        int tot_len;
 
        if (kern_msg->msg_namelen) {
-               if (mode==VERIFY_READ) {
+               if (mode == VERIFY_READ) {
                        int err = move_addr_to_kernel(kern_msg->msg_name,
                                                      kern_msg->msg_namelen,
                                                      kern_address);
@@ -353,7 +357,7 @@ static int do_set_attach_filter(struct socket *sock, int level, int optname,
 static int do_set_sock_timeout(struct socket *sock, int level,
                int optname, char __user *optval, unsigned int optlen)
 {
-       struct compat_timeval __user *up = (struct compat_timeval __user *) optval;
+       struct compat_timeval __user *up = (struct compat_timeval __user *)optval;
        struct timeval ktime;
        mm_segment_t old_fs;
        int err;
@@ -366,7 +370,7 @@ static int do_set_sock_timeout(struct socket *sock, int level,
                return -EFAULT;
        old_fs = get_fs();
        set_fs(KERNEL_DS);
-       err = sock_setsockopt(sock, level, optname, (char *) &ktime, sizeof(ktime));
+       err = sock_setsockopt(sock, level, optname, (char *)&ktime, sizeof(ktime));
        set_fs(old_fs);
 
        return err;
@@ -388,11 +392,10 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
                                char __user *optval, unsigned int optlen)
 {
        int err;
-       struct socket *sock;
+       struct socket *sock = sockfd_lookup(fd, &err);
 
-       if ((sock = sockfd_lookup(fd, &err))!=NULL)
-       {
-               err = security_socket_setsockopt(sock,level,optname);
+       if (sock) {
+               err = security_socket_setsockopt(sock, level, optname);
                if (err) {
                        sockfd_put(sock);
                        return err;
@@ -452,7 +455,7 @@ static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
 int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
 {
        struct compat_timeval __user *ctv =
-                       (struct compat_timeval __user*) userstamp;
+                       (struct compat_timeval __user *) userstamp;
        int err = -ENOENT;
        struct timeval tv;
 
@@ -476,7 +479,7 @@ EXPORT_SYMBOL(compat_sock_get_timestamp);
 int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp)
 {
        struct compat_timespec __user *ctv =
-                       (struct compat_timespec __user*) userstamp;
+                       (struct compat_timespec __user *) userstamp;
        int err = -ENOENT;
        struct timespec ts;
 
@@ -501,12 +504,10 @@ asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
                                char __user *optval, int __user *optlen)
 {
        int err;
-       struct socket *sock;
+       struct socket *sock = sockfd_lookup(fd, &err);
 
-       if ((sock = sockfd_lookup(fd, &err))!=NULL)
-       {
-               err = security_socket_getsockopt(sock, level,
-                                                          optname);
+       if (sock) {
+               err = security_socket_getsockopt(sock, level, optname);
                if (err) {
                        sockfd_put(sock);
                        return err;
@@ -530,7 +531,7 @@ struct compat_group_req {
        __u32                            gr_interface;
        struct __kernel_sockaddr_storage gr_group
                __attribute__ ((aligned(4)));
-} __attribute__ ((packed));
+} __packed;
 
 struct compat_group_source_req {
        __u32                            gsr_interface;
@@ -538,7 +539,7 @@ struct compat_group_source_req {
                __attribute__ ((aligned(4)));
        struct __kernel_sockaddr_storage gsr_source
                __attribute__ ((aligned(4)));
-} __attribute__ ((packed));
+} __packed;
 
 struct compat_group_filter {
        __u32                            gf_interface;
@@ -548,7 +549,7 @@ struct compat_group_filter {
        __u32                            gf_numsrc;
        struct __kernel_sockaddr_storage gf_slist[1]
                __attribute__ ((aligned(4)));
-} __attribute__ ((packed));
+} __packed;
 
 #define __COMPAT_GF0_SIZE (sizeof(struct compat_group_filter) - \
                        sizeof(struct __kernel_sockaddr_storage))
@@ -556,7 +557,7 @@ struct compat_group_filter {
 
 int compat_mc_setsockopt(struct sock *sock, int level, int optname,
        char __user *optval, unsigned int optlen,
-       int (*setsockopt)(struct sock *,int,int,char __user *,unsigned int))
+       int (*setsockopt)(struct sock *, int, int, char __user *, unsigned int))
 {
        char __user     *koptval = optval;
        int             koptlen = optlen;
@@ -639,12 +640,11 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,
        }
        return setsockopt(sock, level, optname, koptval, koptlen);
 }
-
 EXPORT_SYMBOL(compat_mc_setsockopt);
 
 int compat_mc_getsockopt(struct sock *sock, int level, int optname,
        char __user *optval, int __user *optlen,
-       int (*getsockopt)(struct sock *,int,int,char __user *,int __user *))
+       int (*getsockopt)(struct sock *, int, int, char __user *, int __user *))
 {
        struct compat_group_filter __user *gf32 = (void *)optval;
        struct group_filter __user *kgf;
@@ -680,7 +680,7 @@ int compat_mc_getsockopt(struct sock *sock, int level, int optname,
            __put_user(interface, &kgf->gf_interface) ||
            __put_user(fmode, &kgf->gf_fmode) ||
            __put_user(numsrc, &kgf->gf_numsrc) ||
-           copy_in_user(&kgf->gf_group,&gf32->gf_group,sizeof(kgf->gf_group)))
+           copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group)))
                return -EFAULT;
 
        err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen);
@@ -713,21 +713,22 @@ int compat_mc_getsockopt(struct sock *sock, int level, int optname,
                copylen = numsrc * sizeof(gf32->gf_slist[0]);
                if (copylen > klen)
                        copylen = klen;
-               if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen))
+               if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen))
                        return -EFAULT;
        }
        return err;
 }
-
 EXPORT_SYMBOL(compat_mc_getsockopt);
 
 
 /* Argument list sizes for compat_sys_socketcall */
 #define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[20]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-                               AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                               AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
-                               AL(4),AL(5)};
+static unsigned char nas[21] = {
+       AL(0), AL(3), AL(3), AL(3), AL(2), AL(3),
+       AL(3), AL(3), AL(4), AL(4), AL(4), AL(6),
+       AL(6), AL(2), AL(5), AL(5), AL(3), AL(3),
+       AL(4), AL(5), AL(4)
+};
 #undef AL
 
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
@@ -735,6 +736,13 @@ asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, uns
        return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
+asmlinkage long compat_sys_sendmmsg(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);
+}
+
 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
 {
        return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
@@ -754,22 +762,21 @@ asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len,
 
 asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
                                    unsigned vlen, unsigned int flags,
-                                   struct timespec __user *timeout)
+                                   struct compat_timespec __user *timeout)
 {
        int datagrams;
        struct timespec ktspec;
-       struct compat_timespec __user *utspec =
-                       (struct compat_timespec __user *)timeout;
 
-       if (get_user(ktspec.tv_sec, &utspec->tv_sec) ||
-           get_user(ktspec.tv_nsec, &utspec->tv_nsec))
+       if (timeout == NULL)
+               return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
+                                     flags | MSG_CMSG_COMPAT, NULL);
+
+       if (get_compat_timespec(&ktspec, timeout))
                return -EFAULT;
 
        datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
                                   flags | MSG_CMSG_COMPAT, &ktspec);
-       if (datagrams > 0 &&
-           (put_user(ktspec.tv_sec, &utspec->tv_sec) ||
-            put_user(ktspec.tv_nsec, &utspec->tv_nsec)))
+       if (datagrams > 0 && put_compat_timespec(&ktspec, timeout))
                datagrams = -EFAULT;
 
        return datagrams;
@@ -781,7 +788,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
        u32 a[6];
        u32 a0, a1;
 
-       if (call < SYS_SOCKET || call > SYS_RECVMMSG)
+       if (call < SYS_SOCKET || call > SYS_SENDMMSG)
                return -EINVAL;
        if (copy_from_user(a, args, nas[call]))
                return -EFAULT;
@@ -827,7 +834,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
                                          compat_ptr(a[4]), compat_ptr(a[5]));
                break;
        case SYS_SHUTDOWN:
-               ret = sys_shutdown(a0,a1);
+               ret = sys_shutdown(a0, a1);
                break;
        case SYS_SETSOCKOPT:
                ret = compat_sys_setsockopt(a0, a1, a[2],
@@ -840,6 +847,9 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
        case SYS_SENDMSG:
                ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]);
                break;
+       case SYS_SENDMMSG:
+               ret = compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]);
+               break;
        case SYS_RECVMSG:
                ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
                break;