aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c336
1 files changed, 286 insertions, 50 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 818634120b69..18b21b4c9e3a 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -53,6 +53,8 @@
53#include <asm/mmu_context.h> 53#include <asm/mmu_context.h>
54#include <asm/ioctls.h> 54#include <asm/ioctls.h>
55 55
56extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
57
56/* 58/*
57 * Not all architectures have sys_utime, so implement this in terms 59 * Not all architectures have sys_utime, so implement this in terms
58 * of sys_utimes. 60 * of sys_utimes.
@@ -68,10 +70,10 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __
68 tv[0].tv_usec = 0; 70 tv[0].tv_usec = 0;
69 tv[1].tv_usec = 0; 71 tv[1].tv_usec = 0;
70 } 72 }
71 return do_utimes(filename, t ? tv : NULL); 73 return do_utimes(AT_FDCWD, filename, t ? tv : NULL);
72} 74}
73 75
74asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) 76asmlinkage long compat_sys_futimesat(int dfd, char __user *filename, struct compat_timeval __user *t)
75{ 77{
76 struct timeval tv[2]; 78 struct timeval tv[2];
77 79
@@ -82,14 +84,19 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _
82 get_user(tv[1].tv_usec, &t[1].tv_usec)) 84 get_user(tv[1].tv_usec, &t[1].tv_usec))
83 return -EFAULT; 85 return -EFAULT;
84 } 86 }
85 return do_utimes(filename, t ? tv : NULL); 87 return do_utimes(dfd, filename, t ? tv : NULL);
88}
89
90asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
91{
92 return compat_sys_futimesat(AT_FDCWD, filename, t);
86} 93}
87 94
88asmlinkage long compat_sys_newstat(char __user * filename, 95asmlinkage long compat_sys_newstat(char __user * filename,
89 struct compat_stat __user *statbuf) 96 struct compat_stat __user *statbuf)
90{ 97{
91 struct kstat stat; 98 struct kstat stat;
92 int error = vfs_stat(filename, &stat); 99 int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
93 100
94 if (!error) 101 if (!error)
95 error = cp_compat_stat(&stat, statbuf); 102 error = cp_compat_stat(&stat, statbuf);
@@ -100,10 +107,31 @@ asmlinkage long compat_sys_newlstat(char __user * filename,
100 struct compat_stat __user *statbuf) 107 struct compat_stat __user *statbuf)
101{ 108{
102 struct kstat stat; 109 struct kstat stat;
103 int error = vfs_lstat(filename, &stat); 110 int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
111
112 if (!error)
113 error = cp_compat_stat(&stat, statbuf);
114 return error;
115}
116
117asmlinkage long compat_sys_newfstatat(int dfd, char __user *filename,
118 struct compat_stat __user *statbuf, int flag)
119{
120 struct kstat stat;
121 int error = -EINVAL;
122
123 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
124 goto out;
125
126 if (flag & AT_SYMLINK_NOFOLLOW)
127 error = vfs_lstat_fd(dfd, filename, &stat);
128 else
129 error = vfs_stat_fd(dfd, filename, &stat);
104 130
105 if (!error) 131 if (!error)
106 error = cp_compat_stat(&stat, statbuf); 132 error = cp_compat_stat(&stat, statbuf);
133
134out:
107 return error; 135 return error;
108} 136}
109 137
@@ -494,9 +522,21 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
494 ret = sys_fcntl(fd, cmd, (unsigned long)&f); 522 ret = sys_fcntl(fd, cmd, (unsigned long)&f);
495 set_fs(old_fs); 523 set_fs(old_fs);
496 if (cmd == F_GETLK && ret == 0) { 524 if (cmd == F_GETLK && ret == 0) {
497 if ((f.l_start >= COMPAT_OFF_T_MAX) || 525 /* GETLK was successfule and we need to return the data...
498 ((f.l_start + f.l_len) > COMPAT_OFF_T_MAX)) 526 * but it needs to fit in the compat structure.
527 * l_start shouldn't be too big, unless the original
528 * start + end is greater than COMPAT_OFF_T_MAX, in which
529 * case the app was asking for trouble, so we return
530 * -EOVERFLOW in that case.
531 * l_len could be too big, in which case we just truncate it,
532 * and only allow the app to see that part of the conflicting
533 * lock that might make sense to it anyway
534 */
535
536 if (f.l_start > COMPAT_OFF_T_MAX)
499 ret = -EOVERFLOW; 537 ret = -EOVERFLOW;
538 if (f.l_len > COMPAT_OFF_T_MAX)
539 f.l_len = COMPAT_OFF_T_MAX;
500 if (ret == 0) 540 if (ret == 0)
501 ret = put_compat_flock(&f, compat_ptr(arg)); 541 ret = put_compat_flock(&f, compat_ptr(arg));
502 } 542 }
@@ -515,9 +555,11 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
515 (unsigned long)&f); 555 (unsigned long)&f);
516 set_fs(old_fs); 556 set_fs(old_fs);
517 if (cmd == F_GETLK64 && ret == 0) { 557 if (cmd == F_GETLK64 && ret == 0) {
518 if ((f.l_start >= COMPAT_LOFF_T_MAX) || 558 /* need to return lock information - see above for commentary */
519 ((f.l_start + f.l_len) > COMPAT_LOFF_T_MAX)) 559 if (f.l_start > COMPAT_LOFF_T_MAX)
520 ret = -EOVERFLOW; 560 ret = -EOVERFLOW;
561 if (f.l_len > COMPAT_LOFF_T_MAX)
562 f.l_len = COMPAT_LOFF_T_MAX;
521 if (ret == 0) 563 if (ret == 0)
522 ret = put_compat_flock64(&f, compat_ptr(arg)); 564 ret = put_compat_flock64(&f, compat_ptr(arg));
523 } 565 }
@@ -1170,7 +1212,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
1170 } 1212 }
1171 1213
1172 ret = rw_verify_area(type, file, pos, tot_len); 1214 ret = rw_verify_area(type, file, pos, tot_len);
1173 if (ret) 1215 if (ret < 0)
1174 goto out; 1216 goto out;
1175 1217
1176 fnv = NULL; 1218 fnv = NULL;
@@ -1276,7 +1318,17 @@ out:
1276asmlinkage long 1318asmlinkage long
1277compat_sys_open(const char __user *filename, int flags, int mode) 1319compat_sys_open(const char __user *filename, int flags, int mode)
1278{ 1320{
1279 return do_sys_open(filename, flags, mode); 1321 return do_sys_open(AT_FDCWD, filename, flags, mode);
1322}
1323
1324/*
1325 * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
1326 * O_LARGEFILE flag.
1327 */
1328asmlinkage long
1329compat_sys_openat(int dfd, const char __user *filename, int flags, int mode)
1330{
1331 return do_sys_open(dfd, filename, flags, mode);
1280} 1332}
1281 1333
1282/* 1334/*
@@ -1523,7 +1575,7 @@ out_ret:
1523 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1575 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1524 * 64-bit unsigned longs. 1576 * 64-bit unsigned longs.
1525 */ 1577 */
1526static inline 1578static
1527int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1579int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1528 unsigned long *fdset) 1580 unsigned long *fdset)
1529{ 1581{
@@ -1556,7 +1608,7 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1556 return 0; 1608 return 0;
1557} 1609}
1558 1610
1559static inline 1611static
1560void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1612void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1561 unsigned long *fdset) 1613 unsigned long *fdset)
1562{ 1614{
@@ -1607,36 +1659,14 @@ static void select_bits_free(void *bits, int size)
1607#define MAX_SELECT_SECONDS \ 1659#define MAX_SELECT_SECONDS \
1608 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) 1660 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1609 1661
1610asmlinkage long 1662int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1611compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, 1663 compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
1612 compat_ulong_t __user *exp, struct compat_timeval __user *tvp)
1613{ 1664{
1614 fd_set_bits fds; 1665 fd_set_bits fds;
1615 char *bits; 1666 char *bits;
1616 long timeout;
1617 int size, max_fdset, ret = -EINVAL; 1667 int size, max_fdset, ret = -EINVAL;
1618 struct fdtable *fdt; 1668 struct fdtable *fdt;
1619 1669
1620 timeout = MAX_SCHEDULE_TIMEOUT;
1621 if (tvp) {
1622 time_t sec, usec;
1623
1624 if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
1625 || __get_user(sec, &tvp->tv_sec)
1626 || __get_user(usec, &tvp->tv_usec)) {
1627 ret = -EFAULT;
1628 goto out_nofds;
1629 }
1630
1631 if (sec < 0 || usec < 0)
1632 goto out_nofds;
1633
1634 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1635 timeout = ROUND_UP(usec, 1000000/HZ);
1636 timeout += sec * (unsigned long) HZ;
1637 }
1638 }
1639
1640 if (n < 0) 1670 if (n < 0)
1641 goto out_nofds; 1671 goto out_nofds;
1642 1672
@@ -1673,19 +1703,7 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
1673 zero_fd_set(n, fds.res_out); 1703 zero_fd_set(n, fds.res_out);
1674 zero_fd_set(n, fds.res_ex); 1704 zero_fd_set(n, fds.res_ex);
1675 1705
1676 ret = do_select(n, &fds, &timeout); 1706 ret = do_select(n, &fds, timeout);
1677
1678 if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1679 time_t sec = 0, usec = 0;
1680 if (timeout) {
1681 sec = timeout / HZ;
1682 usec = timeout % HZ;
1683 usec *= (1000000/HZ);
1684 }
1685 if (put_user(sec, &tvp->tv_sec) ||
1686 put_user(usec, &tvp->tv_usec))
1687 ret = -EFAULT;
1688 }
1689 1707
1690 if (ret < 0) 1708 if (ret < 0)
1691 goto out; 1709 goto out;
@@ -1706,6 +1724,224 @@ out_nofds:
1706 return ret; 1724 return ret;
1707} 1725}
1708 1726
1727asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1728 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1729 struct compat_timeval __user *tvp)
1730{
1731 s64 timeout = -1;
1732 struct compat_timeval tv;
1733 int ret;
1734
1735 if (tvp) {
1736 if (copy_from_user(&tv, tvp, sizeof(tv)))
1737 return -EFAULT;
1738
1739 if (tv.tv_sec < 0 || tv.tv_usec < 0)
1740 return -EINVAL;
1741
1742 /* Cast to u64 to make GCC stop complaining */
1743 if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
1744 timeout = -1; /* infinite */
1745 else {
1746 timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
1747 timeout += tv.tv_sec * HZ;
1748 }
1749 }
1750
1751 ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
1752
1753 if (tvp) {
1754 if (current->personality & STICKY_TIMEOUTS)
1755 goto sticky;
1756 tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
1757 tv.tv_sec = timeout;
1758 if (copy_to_user(tvp, &tv, sizeof(tv))) {
1759sticky:
1760 /*
1761 * If an application puts its timeval in read-only
1762 * memory, we don't want the Linux-specific update to
1763 * the timeval to cause a fault after the select has
1764 * completed successfully. However, because we're not
1765 * updating the timeval, we can't restart the system
1766 * call.
1767 */
1768 if (ret == -ERESTARTNOHAND)
1769 ret = -EINTR;
1770 }
1771 }
1772
1773 return ret;
1774}
1775
1776#ifdef TIF_RESTORE_SIGMASK
1777asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1778 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1779 struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
1780 compat_size_t sigsetsize)
1781{
1782 compat_sigset_t ss32;
1783 sigset_t ksigmask, sigsaved;
1784 long timeout = MAX_SCHEDULE_TIMEOUT;
1785 struct compat_timespec ts;
1786 int ret;
1787
1788 if (tsp) {
1789 if (copy_from_user(&ts, tsp, sizeof(ts)))
1790 return -EFAULT;
1791
1792 if (ts.tv_sec < 0 || ts.tv_nsec < 0)
1793 return -EINVAL;
1794 }
1795
1796 if (sigmask) {
1797 if (sigsetsize != sizeof(compat_sigset_t))
1798 return -EINVAL;
1799 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1800 return -EFAULT;
1801 sigset_from_compat(&ksigmask, &ss32);
1802
1803 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1804 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1805 }
1806
1807 do {
1808 if (tsp) {
1809 if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
1810 timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1811 timeout += ts.tv_sec * (unsigned long)HZ;
1812 ts.tv_sec = 0;
1813 ts.tv_nsec = 0;
1814 } else {
1815 ts.tv_sec -= MAX_SELECT_SECONDS;
1816 timeout = MAX_SELECT_SECONDS * HZ;
1817 }
1818 }
1819
1820 ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
1821
1822 } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
1823
1824 if (tsp && !(current->personality & STICKY_TIMEOUTS)) {
1825 ts.tv_sec += timeout / HZ;
1826 ts.tv_nsec += (timeout % HZ) * (1000000000/HZ);
1827 if (ts.tv_nsec >= 1000000000) {
1828 ts.tv_sec++;
1829 ts.tv_nsec -= 1000000000;
1830 }
1831 (void)copy_to_user(tsp, &ts, sizeof(ts));
1832 }
1833
1834 if (ret == -ERESTARTNOHAND) {
1835 /*
1836 * Don't restore the signal mask yet. Let do_signal() deliver
1837 * the signal on the way back to userspace, before the signal
1838 * mask is restored.
1839 */
1840 if (sigmask) {
1841 memcpy(&current->saved_sigmask, &sigsaved,
1842 sizeof(sigsaved));
1843 set_thread_flag(TIF_RESTORE_SIGMASK);
1844 }
1845 } else if (sigmask)
1846 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1847
1848 return ret;
1849}
1850
1851asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
1852 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1853 struct compat_timespec __user *tsp, void __user *sig)
1854{
1855 compat_size_t sigsetsize = 0;
1856 compat_uptr_t up = 0;
1857
1858 if (sig) {
1859 if (!access_ok(VERIFY_READ, sig,
1860 sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
1861 __get_user(up, (compat_uptr_t __user *)sig) ||
1862 __get_user(sigsetsize,
1863 (compat_size_t __user *)(sig+sizeof(up))))
1864 return -EFAULT;
1865 }
1866 return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up),
1867 sigsetsize);
1868}
1869
1870asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1871 unsigned int nfds, struct compat_timespec __user *tsp,
1872 const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
1873{
1874 compat_sigset_t ss32;
1875 sigset_t ksigmask, sigsaved;
1876 struct compat_timespec ts;
1877 s64 timeout = -1;
1878 int ret;
1879
1880 if (tsp) {
1881 if (copy_from_user(&ts, tsp, sizeof(ts)))
1882 return -EFAULT;
1883
1884 /* We assume that ts.tv_sec is always lower than
1885 the number of seconds that can be expressed in
1886 an s64. Otherwise the compiler bitches at us */
1887 timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
1888 timeout += ts.tv_sec * HZ;
1889 }
1890
1891 if (sigmask) {
1892 if (sigsetsize |= sizeof(compat_sigset_t))
1893 return -EINVAL;
1894 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1895 return -EFAULT;
1896 sigset_from_compat(&ksigmask, &ss32);
1897
1898 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1899 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1900 }
1901
1902 ret = do_sys_poll(ufds, nfds, &timeout);
1903
1904 /* We can restart this syscall, usually */
1905 if (ret == -EINTR) {
1906 /*
1907 * Don't restore the signal mask yet. Let do_signal() deliver
1908 * the signal on the way back to userspace, before the signal
1909 * mask is restored.
1910 */
1911 if (sigmask) {
1912 memcpy(&current->saved_sigmask, &sigsaved,
1913 sizeof(sigsaved));
1914 set_thread_flag(TIF_RESTORE_SIGMASK);
1915 }
1916 ret = -ERESTARTNOHAND;
1917 } else if (sigmask)
1918 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1919
1920 if (tsp && timeout >= 0) {
1921 if (current->personality & STICKY_TIMEOUTS)
1922 goto sticky;
1923 /* Yes, we know it's actually an s64, but it's also positive. */
1924 ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
1925 ts.tv_sec = timeout;
1926 if (copy_to_user(tsp, &ts, sizeof(ts))) {
1927sticky:
1928 /*
1929 * If an application puts its timeval in read-only
1930 * memory, we don't want the Linux-specific update to
1931 * the timeval to cause a fault after the select has
1932 * completed successfully. However, because we're not
1933 * updating the timeval, we can't restart the system
1934 * call.
1935 */
1936 if (ret == -ERESTARTNOHAND && timeout >= 0)
1937 ret = -EINTR;
1938 }
1939 }
1940
1941 return ret;
1942}
1943#endif /* TIF_RESTORE_SIGMASK */
1944
1709#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) 1945#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
1710/* Stuff for NFS server syscalls... */ 1946/* Stuff for NFS server syscalls... */
1711struct compat_nfsctl_svc { 1947struct compat_nfsctl_svc {