aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 075d0509970d..424767c954a0 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1436,6 +1436,57 @@ out_ret:
1436 1436
1437#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) 1437#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
1438 1438
1439static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1440 int timeval, int ret)
1441{
1442 struct timespec ts;
1443
1444 if (!p)
1445 return ret;
1446
1447 if (current->personality & STICKY_TIMEOUTS)
1448 goto sticky;
1449
1450 /* No update for zero timeout */
1451 if (!end_time->tv_sec && !end_time->tv_nsec)
1452 return ret;
1453
1454 ktime_get_ts(&ts);
1455 ts = timespec_sub(*end_time, ts);
1456 if (ts.tv_sec < 0)
1457 ts.tv_sec = ts.tv_nsec = 0;
1458
1459 if (timeval) {
1460 struct compat_timeval rtv;
1461
1462 rtv.tv_sec = ts.tv_sec;
1463 rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1464
1465 if (!copy_to_user(p, &rtv, sizeof(rtv)))
1466 return ret;
1467 } else {
1468 struct compat_timespec rts;
1469
1470 rts.tv_sec = ts.tv_sec;
1471 rts.tv_nsec = ts.tv_nsec;
1472
1473 if (!copy_to_user(p, &rts, sizeof(rts)))
1474 return ret;
1475 }
1476 /*
1477 * If an application puts its timeval in read-only memory, we
1478 * don't want the Linux-specific update to the timeval to
1479 * cause a fault after the select has completed
1480 * successfully. However, because we're not updating the
1481 * timeval, we can't restart the system call.
1482 */
1483
1484sticky:
1485 if (ret == -ERESTARTNOHAND)
1486 ret = -EINTR;
1487 return ret;
1488}
1489
1439/* 1490/*
1440 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1491 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1441 * 64-bit unsigned longs. 1492 * 64-bit unsigned longs.