Merge branch 'pandora-27-omap1' into rev2
[pandora-kernel.git] / net / compat.c
index 6e1b03b..67fb6a3 100644 (file)
@@ -722,9 +722,10 @@ EXPORT_SYMBOL(compat_mc_getsockopt);
 
 /* Argument list sizes for compat_sys_socketcall */
 #define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+static unsigned char nas[19]={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(6),AL(2),AL(5),AL(5),AL(3),AL(3),
+                               AL(6)};
 #undef AL
 
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
@@ -737,13 +738,52 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns
        return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
+asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
+                                  int __user *upeer_addrlen,
+                                  const compat_sigset_t __user *sigmask,
+                                  compat_size_t sigsetsize, int flags)
+{
+       compat_sigset_t ss32;
+       sigset_t ksigmask, sigsaved;
+       int ret;
+
+       if (sigmask) {
+               if (sigsetsize != sizeof(compat_sigset_t))
+                       return -EINVAL;
+               if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+                       return -EFAULT;
+               sigset_from_compat(&ksigmask, &ss32);
+
+               sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+               sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+       }
+
+       ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
+
+       if (ret == -ERESTARTNOHAND) {
+               /*
+                * Don't restore the signal mask yet. Let do_signal() deliver
+                * the signal on the way back to userspace, before the signal
+                * mask is restored.
+                */
+               if (sigmask) {
+                       memcpy(&current->saved_sigmask, &sigsaved,
+                              sizeof(sigsaved));
+                       set_restore_sigmask();
+               }
+       } else if (sigmask)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+       return ret;
+}
+
 asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
 {
        int ret;
        u32 a[6];
        u32 a0, a1;
 
-       if (call < SYS_SOCKET || call > SYS_RECVMSG)
+       if (call < SYS_SOCKET || call > SYS_PACCEPT)
                return -EINVAL;
        if (copy_from_user(a, args, nas[call]))
                return -EFAULT;
@@ -764,7 +804,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
                ret = sys_listen(a0, a1);
                break;
        case SYS_ACCEPT:
-               ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2]));
+               ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
                break;
        case SYS_GETSOCKNAME:
                ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
@@ -804,6 +844,10 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
        case SYS_RECVMSG:
                ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
                break;
+       case SYS_PACCEPT:
+               ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]),
+                                        compat_ptr(a[3]), a[4], a[5]);
+               break;
        default:
                ret = -EINVAL;
                break;