]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/select.c
select: deal with math overflow from borderline valid userland data
[linux-2.6-omap-h63xx.git] / fs / select.c
index 5e61b43d07660eebc089c0f37ee430139241e535..87df51eadcf2bd170ab0271e189cf8a580aa1adb 100644 (file)
  * better solutions..
  */
 
-static unsigned long __estimate_accuracy(struct timespec *tv)
+static long __estimate_accuracy(struct timespec *tv)
 {
-       unsigned long slack;
+       long slack;
        int divfactor = 1000;
 
-       if (task_nice(current))
+       if (task_nice(current) > 0)
                divfactor = divfactor / 5;
 
        slack = tv->tv_nsec / divfactor;
@@ -54,10 +54,13 @@ static unsigned long __estimate_accuracy(struct timespec *tv)
 
        if (slack > 100 * NSEC_PER_MSEC)
                slack =  100 * NSEC_PER_MSEC;
+
+       if (slack < 0)
+               slack = 0;
        return slack;
 }
 
-static unsigned long estimate_accuracy(struct timespec *tv)
+static long estimate_accuracy(struct timespec *tv)
 {
        unsigned long ret;
        struct timespec now;
@@ -66,8 +69,7 @@ static unsigned long estimate_accuracy(struct timespec *tv)
         * Realtime tasks get a slack of 0 for obvious reasons.
         */
 
-       if (current->policy == SCHED_FIFO ||
-               current->policy == SCHED_RR)
+       if (rt_task(current))
                return 0;
 
        ktime_get_ts(&now);
@@ -331,7 +333,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
                timed_out = 1;
        }
 
-       if (end_time)
+       if (end_time && !timed_out)
                slack = estimate_accuracy(end_time);
 
        retval = 0;
@@ -517,8 +519,9 @@ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
                        return -EFAULT;
 
                to = &end_time;
-               if (poll_select_set_timeout(to, tv.tv_sec,
-                                           tv.tv_usec * NSEC_PER_USEC))
+               if (poll_select_set_timeout(to,
+                               tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
+                               (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
                        return -EINVAL;
        }
 
@@ -657,7 +660,7 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
                timed_out = 1;
        }
 
-       if (end_time)
+       if (end_time && !timed_out)
                slack = estimate_accuracy(end_time);
 
        for (;;) {