]> 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 fdd8584e536dca956dd1b8a6ec4c68f2ef8ea9f5..87df51eadcf2bd170ab0271e189cf8a580aa1adb 100644 (file)
@@ -41,9 +41,9 @@
  * 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) > 0)
@@ -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;
@@ -330,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;
@@ -516,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;
        }
 
@@ -656,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 (;;) {