]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/compat.c
USB: set default y for CONFIG_USB_DEVICE_CLASS
[linux-2.6-omap-h63xx.git] / fs / compat.c
index 9cf75df9b2bb4753356ca9e3e5ae527b49329268..4db6216e5266a590b0330ff4c8c2868eb84c1013 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/tsacct_kern.h>
 #include <linux/security.h>
 #include <linux/highmem.h>
+#include <linux/signal.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
 #include <linux/eventpoll.h>
@@ -1543,9 +1544,10 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
 {
        fd_set_bits fds;
-       char *bits;
+       void *bits;
        int size, max_fds, ret = -EINVAL;
        struct fdtable *fdt;
+       long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
 
        if (n < 0)
                goto out_nofds;
@@ -1563,11 +1565,14 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
         * since we used fdset we need to allocate memory in units of
         * long-words.
         */
-       ret = -ENOMEM;
        size = FDS_BYTES(n);
-       bits = kmalloc(6 * size, GFP_KERNEL);
-       if (!bits)
-               goto out_nofds;
+       bits = stack_fds;
+       if (size > sizeof(stack_fds) / 6) {
+               bits = kmalloc(6 * size, GFP_KERNEL);
+               ret = -ENOMEM;
+               if (!bits)
+                       goto out_nofds;
+       }
        fds.in      = (unsigned long *)  bits;
        fds.out     = (unsigned long *) (bits +   size);
        fds.ex      = (unsigned long *) (bits + 2*size);
@@ -1599,7 +1604,8 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
            compat_set_fd_set(n, exp, fds.res_ex))
                ret = -EFAULT;
 out:
-       kfree(bits);
+       if (bits != stack_fds)
+               kfree(bits);
 out_nofds:
        return ret;
 }
@@ -2199,3 +2205,46 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
 #endif /* TIF_RESTORE_SIGMASK */
 
 #endif /* CONFIG_EPOLL */
+
+#ifdef CONFIG_SIGNALFD
+
+asmlinkage long compat_sys_signalfd(int ufd,
+                                   const compat_sigset_t __user *sigmask,
+                                   compat_size_t sigsetsize)
+{
+       compat_sigset_t ss32;
+       sigset_t tmp;
+       sigset_t __user *ksigmask;
+
+       if (sigsetsize != sizeof(compat_sigset_t))
+               return -EINVAL;
+       if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+               return -EFAULT;
+       sigset_from_compat(&tmp, &ss32);
+       ksigmask = compat_alloc_user_space(sizeof(sigset_t));
+       if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
+               return -EFAULT;
+
+       return sys_signalfd(ufd, ksigmask, sizeof(sigset_t));
+}
+
+#endif /* CONFIG_SIGNALFD */
+
+#ifdef CONFIG_TIMERFD
+
+asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags,
+                                  const struct compat_itimerspec __user *utmr)
+{
+       struct itimerspec t;
+       struct itimerspec __user *ut;
+
+       if (get_compat_itimerspec(&t, utmr))
+               return -EFAULT;
+       ut = compat_alloc_user_space(sizeof(*ut));
+       if (copy_to_user(ut, &t, sizeof(t)))
+               return -EFAULT;
+
+       return sys_timerfd(ufd, clockid, flags, ut);
+}
+
+#endif /* CONFIG_TIMERFD */