aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-02 14:54:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-02 14:54:26 -0400
commit204f144c9fcac355843412b6ba1150086488a208 (patch)
tree7c06bcb63f2caf961855d2cea968d9fd94b325d7
parentda7b66ffb2815800440d9e1649282a27c805304f (diff)
parent801b25f104647d44dc5b5cce2c72e2283b3757de (diff)
Merge branch 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull fs/compat.c cleanups from Al Viro: "More moving of compat syscalls from fs/compat.c to fs/*.c where the native counterparts live. And death to compat_sys_getdents64() - the only architecture that used to need it was ia64, and _that_ has lost biarch support quite a few years ago" * 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fs/compat.c: trim unused includes move compat_rw_copy_check_uvector() over to fs/read_write.c fhandle: move compat syscalls from compat.c open: move compat syscalls from compat.c stat: move compat syscalls from compat.c fcntl: move compat syscalls from compat.c readdir: move compat syscalls from compat.c statfs: move compat syscalls from compat.c utimes: move compat syscalls from compat.c move compat select-related syscalls to fs/select.c Remove compat_sys_getdents64()
-rw-r--r--arch/arm64/include/asm/unistd.h1
-rw-r--r--arch/arm64/include/asm/unistd32.h2
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl2
-rw-r--r--arch/x86/include/asm/unistd.h1
-rw-r--r--fs/compat.c1191
-rw-r--r--fs/fcntl.c157
-rw-r--r--fs/fhandle.c13
-rw-r--r--fs/internal.h2
-rw-r--r--fs/open.c20
-rw-r--r--fs/read_write.c75
-rw-r--r--fs/readdir.c165
-rw-r--r--fs/select.c421
-rw-r--r--fs/stat.c86
-rw-r--r--fs/statfs.c140
-rw-r--r--fs/utimes.c66
-rw-r--r--include/linux/compat.h5
-rw-r--r--include/linux/poll.h56
-rw-r--r--include/uapi/asm-generic/unistd.h3
18 files changed, 1139 insertions, 1267 deletions
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index bdbeb06dc11e..a0baa9af5487 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -14,7 +14,6 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16#ifdef CONFIG_COMPAT 16#ifdef CONFIG_COMPAT
17#define __ARCH_WANT_COMPAT_SYS_GETDENTS64
18#define __ARCH_WANT_COMPAT_STAT64 17#define __ARCH_WANT_COMPAT_STAT64
19#define __ARCH_WANT_SYS_GETHOSTNAME 18#define __ARCH_WANT_SYS_GETHOSTNAME
20#define __ARCH_WANT_SYS_PAUSE 19#define __ARCH_WANT_SYS_PAUSE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index c66b51aab195..ef292160748c 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -456,7 +456,7 @@ __SYSCALL(__NR_setfsuid32, sys_setfsuid)
456#define __NR_setfsgid32 216 456#define __NR_setfsgid32 216
457__SYSCALL(__NR_setfsgid32, sys_setfsgid) 457__SYSCALL(__NR_setfsgid32, sys_setfsgid)
458#define __NR_getdents64 217 458#define __NR_getdents64 217
459__SYSCALL(__NR_getdents64, compat_sys_getdents64) 459__SYSCALL(__NR_getdents64, sys_getdents64)
460#define __NR_pivot_root 218 460#define __NR_pivot_root 218
461__SYSCALL(__NR_pivot_root, sys_pivot_root) 461__SYSCALL(__NR_pivot_root, sys_pivot_root)
462#define __NR_mincore 219 462#define __NR_mincore 219
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 0af59fa789ea..448ac2161112 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -226,7 +226,7 @@
226217 i386 pivot_root sys_pivot_root 226217 i386 pivot_root sys_pivot_root
227218 i386 mincore sys_mincore 227218 i386 mincore sys_mincore
228219 i386 madvise sys_madvise 228219 i386 madvise sys_madvise
229220 i386 getdents64 sys_getdents64 compat_sys_getdents64 229220 i386 getdents64 sys_getdents64
230221 i386 fcntl64 sys_fcntl64 compat_sys_fcntl64 230221 i386 fcntl64 sys_fcntl64 compat_sys_fcntl64
231# 222 is unused 231# 222 is unused
232# 223 is unused 232# 223 is unused
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 32712a925f26..1ba1536f627e 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -23,7 +23,6 @@
23# include <asm/unistd_64.h> 23# include <asm/unistd_64.h>
24# include <asm/unistd_64_x32.h> 24# include <asm/unistd_64_x32.h>
25# define __ARCH_WANT_COMPAT_SYS_TIME 25# define __ARCH_WANT_COMPAT_SYS_TIME
26# define __ARCH_WANT_COMPAT_SYS_GETDENTS64
27# define __ARCH_WANT_COMPAT_SYS_PREADV64 26# define __ARCH_WANT_COMPAT_SYS_PREADV64
28# define __ARCH_WANT_COMPAT_SYS_PWRITEV64 27# define __ARCH_WANT_COMPAT_SYS_PWRITEV64
29# define __ARCH_WANT_COMPAT_SYS_PREADV64V2 28# define __ARCH_WANT_COMPAT_SYS_PREADV64V2
diff --git a/fs/compat.c b/fs/compat.c
index c61b506f5bc9..190b38b39d9e 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -15,555 +15,14 @@
15 * published by the Free Software Foundation. 15 * published by the Free Software Foundation.
16 */ 16 */
17 17
18#include <linux/stddef.h>
19#include <linux/kernel.h>
20#include <linux/linkage.h>
21#include <linux/compat.h> 18#include <linux/compat.h>
22#include <linux/errno.h>
23#include <linux/time.h>
24#include <linux/cred.h>
25#include <linux/fs.h>
26#include <linux/fcntl.h>
27#include <linux/namei.h>
28#include <linux/file.h>
29#include <linux/fdtable.h>
30#include <linux/vfs.h>
31#include <linux/ioctl.h>
32#include <linux/init.h>
33#include <linux/ncp_mount.h> 19#include <linux/ncp_mount.h>
34#include <linux/nfs4_mount.h> 20#include <linux/nfs4_mount.h>
35#include <linux/syscalls.h> 21#include <linux/syscalls.h>
36#include <linux/ctype.h>
37#include <linux/dirent.h>
38#include <linux/fsnotify.h>
39#include <linux/highuid.h>
40#include <linux/personality.h>
41#include <linux/rwsem.h>
42#include <linux/tsacct_kern.h>
43#include <linux/security.h>
44#include <linux/highmem.h>
45#include <linux/signal.h>
46#include <linux/poll.h>
47#include <linux/mm.h>
48#include <linux/fs_struct.h>
49#include <linux/slab.h> 22#include <linux/slab.h>
50#include <linux/pagemap.h>
51#include <linux/aio.h>
52
53#include <linux/uaccess.h> 23#include <linux/uaccess.h>
54#include <asm/mmu_context.h>
55#include <asm/ioctls.h>
56#include "internal.h" 24#include "internal.h"
57 25
58/*
59 * Not all architectures have sys_utime, so implement this in terms
60 * of sys_utimes.
61 */
62COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
63 struct compat_utimbuf __user *, t)
64{
65 struct timespec tv[2];
66
67 if (t) {
68 if (get_user(tv[0].tv_sec, &t->actime) ||
69 get_user(tv[1].tv_sec, &t->modtime))
70 return -EFAULT;
71 tv[0].tv_nsec = 0;
72 tv[1].tv_nsec = 0;
73 }
74 return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
75}
76
77COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
78{
79 struct timespec tv[2];
80
81 if (t) {
82 if (compat_get_timespec(&tv[0], &t[0]) ||
83 compat_get_timespec(&tv[1], &t[1]))
84 return -EFAULT;
85
86 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
87 return 0;
88 }
89 return do_utimes(dfd, filename, t ? tv : NULL, flags);
90}
91
92COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
93{
94 struct timespec tv[2];
95
96 if (t) {
97 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
98 get_user(tv[0].tv_nsec, &t[0].tv_usec) ||
99 get_user(tv[1].tv_sec, &t[1].tv_sec) ||
100 get_user(tv[1].tv_nsec, &t[1].tv_usec))
101 return -EFAULT;
102 if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 ||
103 tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0)
104 return -EINVAL;
105 tv[0].tv_nsec *= 1000;
106 tv[1].tv_nsec *= 1000;
107 }
108 return do_utimes(dfd, filename, t ? tv : NULL, 0);
109}
110
111COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t)
112{
113 return compat_sys_futimesat(AT_FDCWD, filename, t);
114}
115
116static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
117{
118 struct compat_stat tmp;
119
120 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
121 return -EOVERFLOW;
122
123 memset(&tmp, 0, sizeof(tmp));
124 tmp.st_dev = old_encode_dev(stat->dev);
125 tmp.st_ino = stat->ino;
126 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
127 return -EOVERFLOW;
128 tmp.st_mode = stat->mode;
129 tmp.st_nlink = stat->nlink;
130 if (tmp.st_nlink != stat->nlink)
131 return -EOVERFLOW;
132 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
133 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
134 tmp.st_rdev = old_encode_dev(stat->rdev);
135 if ((u64) stat->size > MAX_NON_LFS)
136 return -EOVERFLOW;
137 tmp.st_size = stat->size;
138 tmp.st_atime = stat->atime.tv_sec;
139 tmp.st_atime_nsec = stat->atime.tv_nsec;
140 tmp.st_mtime = stat->mtime.tv_sec;
141 tmp.st_mtime_nsec = stat->mtime.tv_nsec;
142 tmp.st_ctime = stat->ctime.tv_sec;
143 tmp.st_ctime_nsec = stat->ctime.tv_nsec;
144 tmp.st_blocks = stat->blocks;
145 tmp.st_blksize = stat->blksize;
146 return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
147}
148
149COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
150 struct compat_stat __user *, statbuf)
151{
152 struct kstat stat;
153 int error;
154
155 error = vfs_stat(filename, &stat);
156 if (error)
157 return error;
158 return cp_compat_stat(&stat, statbuf);
159}
160
161COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
162 struct compat_stat __user *, statbuf)
163{
164 struct kstat stat;
165 int error;
166
167 error = vfs_lstat(filename, &stat);
168 if (error)
169 return error;
170 return cp_compat_stat(&stat, statbuf);
171}
172
173#ifndef __ARCH_WANT_STAT64
174COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
175 const char __user *, filename,
176 struct compat_stat __user *, statbuf, int, flag)
177{
178 struct kstat stat;
179 int error;
180
181 error = vfs_fstatat(dfd, filename, &stat, flag);
182 if (error)
183 return error;
184 return cp_compat_stat(&stat, statbuf);
185}
186#endif
187
188COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
189 struct compat_stat __user *, statbuf)
190{
191 struct kstat stat;
192 int error = vfs_fstat(fd, &stat);
193
194 if (!error)
195 error = cp_compat_stat(&stat, statbuf);
196 return error;
197}
198
199static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
200{
201
202 if (sizeof ubuf->f_blocks == 4) {
203 if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
204 kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
205 return -EOVERFLOW;
206 /* f_files and f_ffree may be -1; it's okay
207 * to stuff that into 32 bits */
208 if (kbuf->f_files != 0xffffffffffffffffULL
209 && (kbuf->f_files & 0xffffffff00000000ULL))
210 return -EOVERFLOW;
211 if (kbuf->f_ffree != 0xffffffffffffffffULL
212 && (kbuf->f_ffree & 0xffffffff00000000ULL))
213 return -EOVERFLOW;
214 }
215 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
216 __put_user(kbuf->f_type, &ubuf->f_type) ||
217 __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
218 __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
219 __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
220 __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
221 __put_user(kbuf->f_files, &ubuf->f_files) ||
222 __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
223 __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
224 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
225 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
226 __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
227 __put_user(kbuf->f_flags, &ubuf->f_flags) ||
228 __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
229 return -EFAULT;
230 return 0;
231}
232
233/*
234 * The following statfs calls are copies of code from fs/statfs.c and
235 * should be checked against those from time to time
236 */
237COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
238{
239 struct kstatfs tmp;
240 int error = user_statfs(pathname, &tmp);
241 if (!error)
242 error = put_compat_statfs(buf, &tmp);
243 return error;
244}
245
246COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
247{
248 struct kstatfs tmp;
249 int error = fd_statfs(fd, &tmp);
250 if (!error)
251 error = put_compat_statfs(buf, &tmp);
252 return error;
253}
254
255static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
256{
257 if (sizeof(ubuf->f_bsize) == 4) {
258 if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen |
259 kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL)
260 return -EOVERFLOW;
261 /* f_files and f_ffree may be -1; it's okay
262 * to stuff that into 32 bits */
263 if (kbuf->f_files != 0xffffffffffffffffULL
264 && (kbuf->f_files & 0xffffffff00000000ULL))
265 return -EOVERFLOW;
266 if (kbuf->f_ffree != 0xffffffffffffffffULL
267 && (kbuf->f_ffree & 0xffffffff00000000ULL))
268 return -EOVERFLOW;
269 }
270 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
271 __put_user(kbuf->f_type, &ubuf->f_type) ||
272 __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
273 __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
274 __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
275 __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
276 __put_user(kbuf->f_files, &ubuf->f_files) ||
277 __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
278 __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
279 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
280 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
281 __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
282 __put_user(kbuf->f_flags, &ubuf->f_flags) ||
283 __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
284 return -EFAULT;
285 return 0;
286}
287
288COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
289{
290 struct kstatfs tmp;
291 int error;
292
293 if (sz != sizeof(*buf))
294 return -EINVAL;
295
296 error = user_statfs(pathname, &tmp);
297 if (!error)
298 error = put_compat_statfs64(buf, &tmp);
299 return error;
300}
301
302COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
303{
304 struct kstatfs tmp;
305 int error;
306
307 if (sz != sizeof(*buf))
308 return -EINVAL;
309
310 error = fd_statfs(fd, &tmp);
311 if (!error)
312 error = put_compat_statfs64(buf, &tmp);
313 return error;
314}
315
316/*
317 * This is a copy of sys_ustat, just dealing with a structure layout.
318 * Given how simple this syscall is that apporach is more maintainable
319 * than the various conversion hacks.
320 */
321COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
322{
323 struct compat_ustat tmp;
324 struct kstatfs sbuf;
325 int err = vfs_ustat(new_decode_dev(dev), &sbuf);
326 if (err)
327 return err;
328
329 memset(&tmp, 0, sizeof(struct compat_ustat));
330 tmp.f_tfree = sbuf.f_bfree;
331 tmp.f_tinode = sbuf.f_ffree;
332 if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
333 return -EFAULT;
334 return 0;
335}
336
337static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
338{
339 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
340 __get_user(kfl->l_type, &ufl->l_type) ||
341 __get_user(kfl->l_whence, &ufl->l_whence) ||
342 __get_user(kfl->l_start, &ufl->l_start) ||
343 __get_user(kfl->l_len, &ufl->l_len) ||
344 __get_user(kfl->l_pid, &ufl->l_pid))
345 return -EFAULT;
346 return 0;
347}
348
349static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
350{
351 if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
352 __put_user(kfl->l_type, &ufl->l_type) ||
353 __put_user(kfl->l_whence, &ufl->l_whence) ||
354 __put_user(kfl->l_start, &ufl->l_start) ||
355 __put_user(kfl->l_len, &ufl->l_len) ||
356 __put_user(kfl->l_pid, &ufl->l_pid))
357 return -EFAULT;
358 return 0;
359}
360
361#ifndef HAVE_ARCH_GET_COMPAT_FLOCK64
362static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
363{
364 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
365 __get_user(kfl->l_type, &ufl->l_type) ||
366 __get_user(kfl->l_whence, &ufl->l_whence) ||
367 __get_user(kfl->l_start, &ufl->l_start) ||
368 __get_user(kfl->l_len, &ufl->l_len) ||
369 __get_user(kfl->l_pid, &ufl->l_pid))
370 return -EFAULT;
371 return 0;
372}
373#endif
374
375#ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64
376static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
377{
378 if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
379 __put_user(kfl->l_type, &ufl->l_type) ||
380 __put_user(kfl->l_whence, &ufl->l_whence) ||
381 __put_user(kfl->l_start, &ufl->l_start) ||
382 __put_user(kfl->l_len, &ufl->l_len) ||
383 __put_user(kfl->l_pid, &ufl->l_pid))
384 return -EFAULT;
385 return 0;
386}
387#endif
388
389static unsigned int
390convert_fcntl_cmd(unsigned int cmd)
391{
392 switch (cmd) {
393 case F_GETLK64:
394 return F_GETLK;
395 case F_SETLK64:
396 return F_SETLK;
397 case F_SETLKW64:
398 return F_SETLKW;
399 }
400
401 return cmd;
402}
403
404COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
405 compat_ulong_t, arg)
406{
407 mm_segment_t old_fs;
408 struct flock f;
409 long ret;
410 unsigned int conv_cmd;
411
412 switch (cmd) {
413 case F_GETLK:
414 case F_SETLK:
415 case F_SETLKW:
416 ret = get_compat_flock(&f, compat_ptr(arg));
417 if (ret != 0)
418 break;
419 old_fs = get_fs();
420 set_fs(KERNEL_DS);
421 ret = sys_fcntl(fd, cmd, (unsigned long)&f);
422 set_fs(old_fs);
423 if (cmd == F_GETLK && ret == 0) {
424 /* GETLK was successful and we need to return the data...
425 * but it needs to fit in the compat structure.
426 * l_start shouldn't be too big, unless the original
427 * start + end is greater than COMPAT_OFF_T_MAX, in which
428 * case the app was asking for trouble, so we return
429 * -EOVERFLOW in that case.
430 * l_len could be too big, in which case we just truncate it,
431 * and only allow the app to see that part of the conflicting
432 * lock that might make sense to it anyway
433 */
434
435 if (f.l_start > COMPAT_OFF_T_MAX)
436 ret = -EOVERFLOW;
437 if (f.l_len > COMPAT_OFF_T_MAX)
438 f.l_len = COMPAT_OFF_T_MAX;
439 if (ret == 0)
440 ret = put_compat_flock(&f, compat_ptr(arg));
441 }
442 break;
443
444 case F_GETLK64:
445 case F_SETLK64:
446 case F_SETLKW64:
447 case F_OFD_GETLK:
448 case F_OFD_SETLK:
449 case F_OFD_SETLKW:
450 ret = get_compat_flock64(&f, compat_ptr(arg));
451 if (ret != 0)
452 break;
453 old_fs = get_fs();
454 set_fs(KERNEL_DS);
455 conv_cmd = convert_fcntl_cmd(cmd);
456 ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
457 set_fs(old_fs);
458 if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
459 /* need to return lock information - see above for commentary */
460 if (f.l_start > COMPAT_LOFF_T_MAX)
461 ret = -EOVERFLOW;
462 if (f.l_len > COMPAT_LOFF_T_MAX)
463 f.l_len = COMPAT_LOFF_T_MAX;
464 if (ret == 0)
465 ret = put_compat_flock64(&f, compat_ptr(arg));
466 }
467 break;
468
469 default:
470 ret = sys_fcntl(fd, cmd, arg);
471 break;
472 }
473 return ret;
474}
475
476COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
477 compat_ulong_t, arg)
478{
479 switch (cmd) {
480 case F_GETLK64:
481 case F_SETLK64:
482 case F_SETLKW64:
483 case F_OFD_GETLK:
484 case F_OFD_SETLK:
485 case F_OFD_SETLKW:
486 return -EINVAL;
487 }
488 return compat_sys_fcntl64(fd, cmd, arg);
489}
490
491/* A write operation does a read from user space and vice versa */
492#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
493
494ssize_t compat_rw_copy_check_uvector(int type,
495 const struct compat_iovec __user *uvector, unsigned long nr_segs,
496 unsigned long fast_segs, struct iovec *fast_pointer,
497 struct iovec **ret_pointer)
498{
499 compat_ssize_t tot_len;
500 struct iovec *iov = *ret_pointer = fast_pointer;
501 ssize_t ret = 0;
502 int seg;
503
504 /*
505 * SuS says "The readv() function *may* fail if the iovcnt argument
506 * was less than or equal to 0, or greater than {IOV_MAX}. Linux has
507 * traditionally returned zero for zero segments, so...
508 */
509 if (nr_segs == 0)
510 goto out;
511
512 ret = -EINVAL;
513 if (nr_segs > UIO_MAXIOV)
514 goto out;
515 if (nr_segs > fast_segs) {
516 ret = -ENOMEM;
517 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
518 if (iov == NULL)
519 goto out;
520 }
521 *ret_pointer = iov;
522
523 ret = -EFAULT;
524 if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
525 goto out;
526
527 /*
528 * Single unix specification:
529 * We should -EINVAL if an element length is not >= 0 and fitting an
530 * ssize_t.
531 *
532 * In Linux, the total length is limited to MAX_RW_COUNT, there is
533 * no overflow possibility.
534 */
535 tot_len = 0;
536 ret = -EINVAL;
537 for (seg = 0; seg < nr_segs; seg++) {
538 compat_uptr_t buf;
539 compat_ssize_t len;
540
541 if (__get_user(len, &uvector->iov_len) ||
542 __get_user(buf, &uvector->iov_base)) {
543 ret = -EFAULT;
544 goto out;
545 }
546 if (len < 0) /* size_t not fitting in compat_ssize_t .. */
547 goto out;
548 if (type >= 0 &&
549 !access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
550 ret = -EFAULT;
551 goto out;
552 }
553 if (len > MAX_RW_COUNT - tot_len)
554 len = MAX_RW_COUNT - tot_len;
555 tot_len += len;
556 iov->iov_base = compat_ptr(buf);
557 iov->iov_len = (compat_size_t) len;
558 uvector++;
559 iov++;
560 }
561 ret = tot_len;
562
563out:
564 return ret;
565}
566
567struct compat_ncp_mount_data { 26struct compat_ncp_mount_data {
568 compat_int_t version; 27 compat_int_t version;
569 compat_uint_t ncp_fd; 28 compat_uint_t ncp_fd;
@@ -744,653 +203,3 @@ COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
744 out: 203 out:
745 return retval; 204 return retval;
746} 205}
747
748struct compat_old_linux_dirent {
749 compat_ulong_t d_ino;
750 compat_ulong_t d_offset;
751 unsigned short d_namlen;
752 char d_name[1];
753};
754
755struct compat_readdir_callback {
756 struct dir_context ctx;
757 struct compat_old_linux_dirent __user *dirent;
758 int result;
759};
760
761static int compat_fillonedir(struct dir_context *ctx, const char *name,
762 int namlen, loff_t offset, u64 ino,
763 unsigned int d_type)
764{
765 struct compat_readdir_callback *buf =
766 container_of(ctx, struct compat_readdir_callback, ctx);
767 struct compat_old_linux_dirent __user *dirent;
768 compat_ulong_t d_ino;
769
770 if (buf->result)
771 return -EINVAL;
772 d_ino = ino;
773 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
774 buf->result = -EOVERFLOW;
775 return -EOVERFLOW;
776 }
777 buf->result++;
778 dirent = buf->dirent;
779 if (!access_ok(VERIFY_WRITE, dirent,
780 (unsigned long)(dirent->d_name + namlen + 1) -
781 (unsigned long)dirent))
782 goto efault;
783 if ( __put_user(d_ino, &dirent->d_ino) ||
784 __put_user(offset, &dirent->d_offset) ||
785 __put_user(namlen, &dirent->d_namlen) ||
786 __copy_to_user(dirent->d_name, name, namlen) ||
787 __put_user(0, dirent->d_name + namlen))
788 goto efault;
789 return 0;
790efault:
791 buf->result = -EFAULT;
792 return -EFAULT;
793}
794
795COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
796 struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
797{
798 int error;
799 struct fd f = fdget_pos(fd);
800 struct compat_readdir_callback buf = {
801 .ctx.actor = compat_fillonedir,
802 .dirent = dirent
803 };
804
805 if (!f.file)
806 return -EBADF;
807
808 error = iterate_dir(f.file, &buf.ctx);
809 if (buf.result)
810 error = buf.result;
811
812 fdput_pos(f);
813 return error;
814}
815
816struct compat_linux_dirent {
817 compat_ulong_t d_ino;
818 compat_ulong_t d_off;
819 unsigned short d_reclen;
820 char d_name[1];
821};
822
823struct compat_getdents_callback {
824 struct dir_context ctx;
825 struct compat_linux_dirent __user *current_dir;
826 struct compat_linux_dirent __user *previous;
827 int count;
828 int error;
829};
830
831static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
832 loff_t offset, u64 ino, unsigned int d_type)
833{
834 struct compat_linux_dirent __user * dirent;
835 struct compat_getdents_callback *buf =
836 container_of(ctx, struct compat_getdents_callback, ctx);
837 compat_ulong_t d_ino;
838 int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
839 namlen + 2, sizeof(compat_long_t));
840
841 buf->error = -EINVAL; /* only used if we fail.. */
842 if (reclen > buf->count)
843 return -EINVAL;
844 d_ino = ino;
845 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
846 buf->error = -EOVERFLOW;
847 return -EOVERFLOW;
848 }
849 dirent = buf->previous;
850 if (dirent) {
851 if (signal_pending(current))
852 return -EINTR;
853 if (__put_user(offset, &dirent->d_off))
854 goto efault;
855 }
856 dirent = buf->current_dir;
857 if (__put_user(d_ino, &dirent->d_ino))
858 goto efault;
859 if (__put_user(reclen, &dirent->d_reclen))
860 goto efault;
861 if (copy_to_user(dirent->d_name, name, namlen))
862 goto efault;
863 if (__put_user(0, dirent->d_name + namlen))
864 goto efault;
865 if (__put_user(d_type, (char __user *) dirent + reclen - 1))
866 goto efault;
867 buf->previous = dirent;
868 dirent = (void __user *)dirent + reclen;
869 buf->current_dir = dirent;
870 buf->count -= reclen;
871 return 0;
872efault:
873 buf->error = -EFAULT;
874 return -EFAULT;
875}
876
877COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
878 struct compat_linux_dirent __user *, dirent, unsigned int, count)
879{
880 struct fd f;
881 struct compat_linux_dirent __user * lastdirent;
882 struct compat_getdents_callback buf = {
883 .ctx.actor = compat_filldir,
884 .current_dir = dirent,
885 .count = count
886 };
887 int error;
888
889 if (!access_ok(VERIFY_WRITE, dirent, count))
890 return -EFAULT;
891
892 f = fdget_pos(fd);
893 if (!f.file)
894 return -EBADF;
895
896 error = iterate_dir(f.file, &buf.ctx);
897 if (error >= 0)
898 error = buf.error;
899 lastdirent = buf.previous;
900 if (lastdirent) {
901 if (put_user(buf.ctx.pos, &lastdirent->d_off))
902 error = -EFAULT;
903 else
904 error = count - buf.count;
905 }
906 fdput_pos(f);
907 return error;
908}
909
910#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
911
912struct compat_getdents_callback64 {
913 struct dir_context ctx;
914 struct linux_dirent64 __user *current_dir;
915 struct linux_dirent64 __user *previous;
916 int count;
917 int error;
918};
919
920static int compat_filldir64(struct dir_context *ctx, const char *name,
921 int namlen, loff_t offset, u64 ino,
922 unsigned int d_type)
923{
924 struct linux_dirent64 __user *dirent;
925 struct compat_getdents_callback64 *buf =
926 container_of(ctx, struct compat_getdents_callback64, ctx);
927 int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
928 sizeof(u64));
929 u64 off;
930
931 buf->error = -EINVAL; /* only used if we fail.. */
932 if (reclen > buf->count)
933 return -EINVAL;
934 dirent = buf->previous;
935
936 if (dirent) {
937 if (signal_pending(current))
938 return -EINTR;
939 if (__put_user_unaligned(offset, &dirent->d_off))
940 goto efault;
941 }
942 dirent = buf->current_dir;
943 if (__put_user_unaligned(ino, &dirent->d_ino))
944 goto efault;
945 off = 0;
946 if (__put_user_unaligned(off, &dirent->d_off))
947 goto efault;
948 if (__put_user(reclen, &dirent->d_reclen))
949 goto efault;
950 if (__put_user(d_type, &dirent->d_type))
951 goto efault;
952 if (copy_to_user(dirent->d_name, name, namlen))
953 goto efault;
954 if (__put_user(0, dirent->d_name + namlen))
955 goto efault;
956 buf->previous = dirent;
957 dirent = (void __user *)dirent + reclen;
958 buf->current_dir = dirent;
959 buf->count -= reclen;
960 return 0;
961efault:
962 buf->error = -EFAULT;
963 return -EFAULT;
964}
965
966COMPAT_SYSCALL_DEFINE3(getdents64, unsigned int, fd,
967 struct linux_dirent64 __user *, dirent, unsigned int, count)
968{
969 struct fd f;
970 struct linux_dirent64 __user * lastdirent;
971 struct compat_getdents_callback64 buf = {
972 .ctx.actor = compat_filldir64,
973 .current_dir = dirent,
974 .count = count
975 };
976 int error;
977
978 if (!access_ok(VERIFY_WRITE, dirent, count))
979 return -EFAULT;
980
981 f = fdget_pos(fd);
982 if (!f.file)
983 return -EBADF;
984
985 error = iterate_dir(f.file, &buf.ctx);
986 if (error >= 0)
987 error = buf.error;
988 lastdirent = buf.previous;
989 if (lastdirent) {
990 typeof(lastdirent->d_off) d_off = buf.ctx.pos;
991 if (__put_user_unaligned(d_off, &lastdirent->d_off))
992 error = -EFAULT;
993 else
994 error = count - buf.count;
995 }
996 fdput_pos(f);
997 return error;
998}
999#endif /* __ARCH_WANT_COMPAT_SYS_GETDENTS64 */
1000
1001/*
1002 * Exactly like fs/open.c:sys_open(), except that it doesn't set the
1003 * O_LARGEFILE flag.
1004 */
1005COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
1006{
1007 return do_sys_open(AT_FDCWD, filename, flags, mode);
1008}
1009
1010/*
1011 * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
1012 * O_LARGEFILE flag.
1013 */
1014COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)
1015{
1016 return do_sys_open(dfd, filename, flags, mode);
1017}
1018
1019#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
1020
1021static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1022 int timeval, int ret)
1023{
1024 struct timespec ts;
1025
1026 if (!p)
1027 return ret;
1028
1029 if (current->personality & STICKY_TIMEOUTS)
1030 goto sticky;
1031
1032 /* No update for zero timeout */
1033 if (!end_time->tv_sec && !end_time->tv_nsec)
1034 return ret;
1035
1036 ktime_get_ts(&ts);
1037 ts = timespec_sub(*end_time, ts);
1038 if (ts.tv_sec < 0)
1039 ts.tv_sec = ts.tv_nsec = 0;
1040
1041 if (timeval) {
1042 struct compat_timeval rtv;
1043
1044 rtv.tv_sec = ts.tv_sec;
1045 rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1046
1047 if (!copy_to_user(p, &rtv, sizeof(rtv)))
1048 return ret;
1049 } else {
1050 struct compat_timespec rts;
1051
1052 rts.tv_sec = ts.tv_sec;
1053 rts.tv_nsec = ts.tv_nsec;
1054
1055 if (!copy_to_user(p, &rts, sizeof(rts)))
1056 return ret;
1057 }
1058 /*
1059 * If an application puts its timeval in read-only memory, we
1060 * don't want the Linux-specific update to the timeval to
1061 * cause a fault after the select has completed
1062 * successfully. However, because we're not updating the
1063 * timeval, we can't restart the system call.
1064 */
1065
1066sticky:
1067 if (ret == -ERESTARTNOHAND)
1068 ret = -EINTR;
1069 return ret;
1070}
1071
1072/*
1073 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1074 * 64-bit unsigned longs.
1075 */
1076static
1077int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1078 unsigned long *fdset)
1079{
1080 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1081 if (ufdset) {
1082 unsigned long odd;
1083
1084 if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
1085 return -EFAULT;
1086
1087 odd = nr & 1UL;
1088 nr &= ~1UL;
1089 while (nr) {
1090 unsigned long h, l;
1091 if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
1092 return -EFAULT;
1093 ufdset += 2;
1094 *fdset++ = h << 32 | l;
1095 nr -= 2;
1096 }
1097 if (odd && __get_user(*fdset, ufdset))
1098 return -EFAULT;
1099 } else {
1100 /* Tricky, must clear full unsigned long in the
1101 * kernel fdset at the end, this makes sure that
1102 * actually happens.
1103 */
1104 memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
1105 }
1106 return 0;
1107}
1108
1109static
1110int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1111 unsigned long *fdset)
1112{
1113 unsigned long odd;
1114 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1115
1116 if (!ufdset)
1117 return 0;
1118
1119 odd = nr & 1UL;
1120 nr &= ~1UL;
1121 while (nr) {
1122 unsigned long h, l;
1123 l = *fdset++;
1124 h = l >> 32;
1125 if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
1126 return -EFAULT;
1127 ufdset += 2;
1128 nr -= 2;
1129 }
1130 if (odd && __put_user(*fdset, ufdset))
1131 return -EFAULT;
1132 return 0;
1133}
1134
1135
1136/*
1137 * This is a virtual copy of sys_select from fs/select.c and probably
1138 * should be compared to it from time to time
1139 */
1140
1141/*
1142 * We can actually return ERESTARTSYS instead of EINTR, but I'd
1143 * like to be certain this leads to no problems. So I return
1144 * EINTR just for safety.
1145 *
1146 * Update: ERESTARTSYS breaks at least the xview clock binary, so
1147 * I'm trying ERESTARTNOHAND which restart only when you want to.
1148 */
1149int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1150 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1151 struct timespec *end_time)
1152{
1153 fd_set_bits fds;
1154 void *bits;
1155 int size, max_fds, ret = -EINVAL;
1156 struct fdtable *fdt;
1157 long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
1158
1159 if (n < 0)
1160 goto out_nofds;
1161
1162 /* max_fds can increase, so grab it once to avoid race */
1163 rcu_read_lock();
1164 fdt = files_fdtable(current->files);
1165 max_fds = fdt->max_fds;
1166 rcu_read_unlock();
1167 if (n > max_fds)
1168 n = max_fds;
1169
1170 /*
1171 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1172 * since we used fdset we need to allocate memory in units of
1173 * long-words.
1174 */
1175 size = FDS_BYTES(n);
1176 bits = stack_fds;
1177 if (size > sizeof(stack_fds) / 6) {
1178 bits = kmalloc(6 * size, GFP_KERNEL);
1179 ret = -ENOMEM;
1180 if (!bits)
1181 goto out_nofds;
1182 }
1183 fds.in = (unsigned long *) bits;
1184 fds.out = (unsigned long *) (bits + size);
1185 fds.ex = (unsigned long *) (bits + 2*size);
1186 fds.res_in = (unsigned long *) (bits + 3*size);
1187 fds.res_out = (unsigned long *) (bits + 4*size);
1188 fds.res_ex = (unsigned long *) (bits + 5*size);
1189
1190 if ((ret = compat_get_fd_set(n, inp, fds.in)) ||
1191 (ret = compat_get_fd_set(n, outp, fds.out)) ||
1192 (ret = compat_get_fd_set(n, exp, fds.ex)))
1193 goto out;
1194 zero_fd_set(n, fds.res_in);
1195 zero_fd_set(n, fds.res_out);
1196 zero_fd_set(n, fds.res_ex);
1197
1198 ret = do_select(n, &fds, end_time);
1199
1200 if (ret < 0)
1201 goto out;
1202 if (!ret) {
1203 ret = -ERESTARTNOHAND;
1204 if (signal_pending(current))
1205 goto out;
1206 ret = 0;
1207 }
1208
1209 if (compat_set_fd_set(n, inp, fds.res_in) ||
1210 compat_set_fd_set(n, outp, fds.res_out) ||
1211 compat_set_fd_set(n, exp, fds.res_ex))
1212 ret = -EFAULT;
1213out:
1214 if (bits != stack_fds)
1215 kfree(bits);
1216out_nofds:
1217 return ret;
1218}
1219
1220COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
1221 compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1222 struct compat_timeval __user *, tvp)
1223{
1224 struct timespec end_time, *to = NULL;
1225 struct compat_timeval tv;
1226 int ret;
1227
1228 if (tvp) {
1229 if (copy_from_user(&tv, tvp, sizeof(tv)))
1230 return -EFAULT;
1231
1232 to = &end_time;
1233 if (poll_select_set_timeout(to,
1234 tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
1235 (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
1236 return -EINVAL;
1237 }
1238
1239 ret = compat_core_sys_select(n, inp, outp, exp, to);
1240 ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
1241
1242 return ret;
1243}
1244
1245struct compat_sel_arg_struct {
1246 compat_ulong_t n;
1247 compat_uptr_t inp;
1248 compat_uptr_t outp;
1249 compat_uptr_t exp;
1250 compat_uptr_t tvp;
1251};
1252
1253COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
1254{
1255 struct compat_sel_arg_struct a;
1256
1257 if (copy_from_user(&a, arg, sizeof(a)))
1258 return -EFAULT;
1259 return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
1260 compat_ptr(a.exp), compat_ptr(a.tvp));
1261}
1262
1263static long do_compat_pselect(int n, compat_ulong_t __user *inp,
1264 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1265 struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
1266 compat_size_t sigsetsize)
1267{
1268 compat_sigset_t ss32;
1269 sigset_t ksigmask, sigsaved;
1270 struct compat_timespec ts;
1271 struct timespec end_time, *to = NULL;
1272 int ret;
1273
1274 if (tsp) {
1275 if (copy_from_user(&ts, tsp, sizeof(ts)))
1276 return -EFAULT;
1277
1278 to = &end_time;
1279 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1280 return -EINVAL;
1281 }
1282
1283 if (sigmask) {
1284 if (sigsetsize != sizeof(compat_sigset_t))
1285 return -EINVAL;
1286 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1287 return -EFAULT;
1288 sigset_from_compat(&ksigmask, &ss32);
1289
1290 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1291 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1292 }
1293
1294 ret = compat_core_sys_select(n, inp, outp, exp, to);
1295 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1296
1297 if (ret == -ERESTARTNOHAND) {
1298 /*
1299 * Don't restore the signal mask yet. Let do_signal() deliver
1300 * the signal on the way back to userspace, before the signal
1301 * mask is restored.
1302 */
1303 if (sigmask) {
1304 memcpy(&current->saved_sigmask, &sigsaved,
1305 sizeof(sigsaved));
1306 set_restore_sigmask();
1307 }
1308 } else if (sigmask)
1309 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1310
1311 return ret;
1312}
1313
1314COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
1315 compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1316 struct compat_timespec __user *, tsp, void __user *, sig)
1317{
1318 compat_size_t sigsetsize = 0;
1319 compat_uptr_t up = 0;
1320
1321 if (sig) {
1322 if (!access_ok(VERIFY_READ, sig,
1323 sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
1324 __get_user(up, (compat_uptr_t __user *)sig) ||
1325 __get_user(sigsetsize,
1326 (compat_size_t __user *)(sig+sizeof(up))))
1327 return -EFAULT;
1328 }
1329 return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
1330 sigsetsize);
1331}
1332
1333COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
1334 unsigned int, nfds, struct compat_timespec __user *, tsp,
1335 const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
1336{
1337 compat_sigset_t ss32;
1338 sigset_t ksigmask, sigsaved;
1339 struct compat_timespec ts;
1340 struct timespec end_time, *to = NULL;
1341 int ret;
1342
1343 if (tsp) {
1344 if (copy_from_user(&ts, tsp, sizeof(ts)))
1345 return -EFAULT;
1346
1347 to = &end_time;
1348 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1349 return -EINVAL;
1350 }
1351
1352 if (sigmask) {
1353 if (sigsetsize != sizeof(compat_sigset_t))
1354 return -EINVAL;
1355 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1356 return -EFAULT;
1357 sigset_from_compat(&ksigmask, &ss32);
1358
1359 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1360 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1361 }
1362
1363 ret = do_sys_poll(ufds, nfds, to);
1364
1365 /* We can restart this syscall, usually */
1366 if (ret == -EINTR) {
1367 /*
1368 * Don't restore the signal mask yet. Let do_signal() deliver
1369 * the signal on the way back to userspace, before the signal
1370 * mask is restored.
1371 */
1372 if (sigmask) {
1373 memcpy(&current->saved_sigmask, &sigsaved,
1374 sizeof(sigsaved));
1375 set_restore_sigmask();
1376 }
1377 ret = -ERESTARTNOHAND;
1378 } else if (sigmask)
1379 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1380
1381 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1382
1383 return ret;
1384}
1385
1386#ifdef CONFIG_FHANDLE
1387/*
1388 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
1389 * doesn't set the O_LARGEFILE flag.
1390 */
1391COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
1392 struct file_handle __user *, handle, int, flags)
1393{
1394 return do_handle_open(mountdirfd, handle, flags);
1395}
1396#endif
diff --git a/fs/fcntl.c b/fs/fcntl.c
index be8fbe289087..8bd81c2e89b2 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -23,6 +23,7 @@
23#include <linux/pid_namespace.h> 23#include <linux/pid_namespace.h>
24#include <linux/user_namespace.h> 24#include <linux/user_namespace.h>
25#include <linux/shmem_fs.h> 25#include <linux/shmem_fs.h>
26#include <linux/compat.h>
26 27
27#include <asm/poll.h> 28#include <asm/poll.h>
28#include <asm/siginfo.h> 29#include <asm/siginfo.h>
@@ -420,6 +421,162 @@ out:
420} 421}
421#endif 422#endif
422 423
424#ifdef CONFIG_COMPAT
425static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
426{
427 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
428 __get_user(kfl->l_type, &ufl->l_type) ||
429 __get_user(kfl->l_whence, &ufl->l_whence) ||
430 __get_user(kfl->l_start, &ufl->l_start) ||
431 __get_user(kfl->l_len, &ufl->l_len) ||
432 __get_user(kfl->l_pid, &ufl->l_pid))
433 return -EFAULT;
434 return 0;
435}
436
437static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
438{
439 if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
440 __put_user(kfl->l_type, &ufl->l_type) ||
441 __put_user(kfl->l_whence, &ufl->l_whence) ||
442 __put_user(kfl->l_start, &ufl->l_start) ||
443 __put_user(kfl->l_len, &ufl->l_len) ||
444 __put_user(kfl->l_pid, &ufl->l_pid))
445 return -EFAULT;
446 return 0;
447}
448
449#ifndef HAVE_ARCH_GET_COMPAT_FLOCK64
450static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
451{
452 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
453 __get_user(kfl->l_type, &ufl->l_type) ||
454 __get_user(kfl->l_whence, &ufl->l_whence) ||
455 __get_user(kfl->l_start, &ufl->l_start) ||
456 __get_user(kfl->l_len, &ufl->l_len) ||
457 __get_user(kfl->l_pid, &ufl->l_pid))
458 return -EFAULT;
459 return 0;
460}
461#endif
462
463#ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64
464static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
465{
466 if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
467 __put_user(kfl->l_type, &ufl->l_type) ||
468 __put_user(kfl->l_whence, &ufl->l_whence) ||
469 __put_user(kfl->l_start, &ufl->l_start) ||
470 __put_user(kfl->l_len, &ufl->l_len) ||
471 __put_user(kfl->l_pid, &ufl->l_pid))
472 return -EFAULT;
473 return 0;
474}
475#endif
476
477static unsigned int
478convert_fcntl_cmd(unsigned int cmd)
479{
480 switch (cmd) {
481 case F_GETLK64:
482 return F_GETLK;
483 case F_SETLK64:
484 return F_SETLK;
485 case F_SETLKW64:
486 return F_SETLKW;
487 }
488
489 return cmd;
490}
491
492COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
493 compat_ulong_t, arg)
494{
495 mm_segment_t old_fs;
496 struct flock f;
497 long ret;
498 unsigned int conv_cmd;
499
500 switch (cmd) {
501 case F_GETLK:
502 case F_SETLK:
503 case F_SETLKW:
504 ret = get_compat_flock(&f, compat_ptr(arg));
505 if (ret != 0)
506 break;
507 old_fs = get_fs();
508 set_fs(KERNEL_DS);
509 ret = sys_fcntl(fd, cmd, (unsigned long)&f);
510 set_fs(old_fs);
511 if (cmd == F_GETLK && ret == 0) {
512 /* GETLK was successful and we need to return the data...
513 * but it needs to fit in the compat structure.
514 * l_start shouldn't be too big, unless the original
515 * start + end is greater than COMPAT_OFF_T_MAX, in which
516 * case the app was asking for trouble, so we return
517 * -EOVERFLOW in that case.
518 * l_len could be too big, in which case we just truncate it,
519 * and only allow the app to see that part of the conflicting
520 * lock that might make sense to it anyway
521 */
522
523 if (f.l_start > COMPAT_OFF_T_MAX)
524 ret = -EOVERFLOW;
525 if (f.l_len > COMPAT_OFF_T_MAX)
526 f.l_len = COMPAT_OFF_T_MAX;
527 if (ret == 0)
528 ret = put_compat_flock(&f, compat_ptr(arg));
529 }
530 break;
531
532 case F_GETLK64:
533 case F_SETLK64:
534 case F_SETLKW64:
535 case F_OFD_GETLK:
536 case F_OFD_SETLK:
537 case F_OFD_SETLKW:
538 ret = get_compat_flock64(&f, compat_ptr(arg));
539 if (ret != 0)
540 break;
541 old_fs = get_fs();
542 set_fs(KERNEL_DS);
543 conv_cmd = convert_fcntl_cmd(cmd);
544 ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
545 set_fs(old_fs);
546 if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
547 /* need to return lock information - see above for commentary */
548 if (f.l_start > COMPAT_LOFF_T_MAX)
549 ret = -EOVERFLOW;
550 if (f.l_len > COMPAT_LOFF_T_MAX)
551 f.l_len = COMPAT_LOFF_T_MAX;
552 if (ret == 0)
553 ret = put_compat_flock64(&f, compat_ptr(arg));
554 }
555 break;
556
557 default:
558 ret = sys_fcntl(fd, cmd, arg);
559 break;
560 }
561 return ret;
562}
563
564COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
565 compat_ulong_t, arg)
566{
567 switch (cmd) {
568 case F_GETLK64:
569 case F_SETLK64:
570 case F_SETLKW64:
571 case F_OFD_GETLK:
572 case F_OFD_SETLK:
573 case F_OFD_SETLKW:
574 return -EINVAL;
575 }
576 return compat_sys_fcntl64(fd, cmd, arg);
577}
578#endif
579
423/* Table to convert sigio signal codes into poll band bitmaps */ 580/* Table to convert sigio signal codes into poll band bitmaps */
424 581
425static const long band_table[NSIGPOLL] = { 582static const long band_table[NSIGPOLL] = {
diff --git a/fs/fhandle.c b/fs/fhandle.c
index 5559168d5637..58a61f55e0d0 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -9,6 +9,7 @@
9#include <linux/fsnotify.h> 9#include <linux/fsnotify.h>
10#include <linux/personality.h> 10#include <linux/personality.h>
11#include <linux/uaccess.h> 11#include <linux/uaccess.h>
12#include <linux/compat.h>
12#include "internal.h" 13#include "internal.h"
13#include "mount.h" 14#include "mount.h"
14 15
@@ -264,3 +265,15 @@ SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
264 ret = do_handle_open(mountdirfd, handle, flags); 265 ret = do_handle_open(mountdirfd, handle, flags);
265 return ret; 266 return ret;
266} 267}
268
269#ifdef CONFIG_COMPAT
270/*
271 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
272 * doesn't set the O_LARGEFILE flag.
273 */
274COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
275 struct file_handle __user *, handle, int, flags)
276{
277 return do_handle_open(mountdirfd, handle, flags);
278}
279#endif
diff --git a/fs/internal.h b/fs/internal.h
index 11c6d89dce9c..076751d90ba2 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -108,8 +108,6 @@ extern struct file *do_filp_open(int dfd, struct filename *pathname,
108extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, 108extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
109 const char *, const struct open_flags *); 109 const char *, const struct open_flags *);
110 110
111extern long do_handle_open(int mountdirfd,
112 struct file_handle __user *ufh, int open_flag);
113extern int open_check_o_direct(struct file *f); 111extern int open_check_o_direct(struct file *f);
114extern int vfs_open(const struct path *, struct file *, const struct cred *); 112extern int vfs_open(const struct path *, struct file *, const struct cred *);
115extern struct file *filp_clone_open(struct file *); 113extern struct file *filp_clone_open(struct file *);
diff --git a/fs/open.c b/fs/open.c
index 949cef29c3bb..4d23f729dcc6 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1078,6 +1078,26 @@ SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
1078 return do_sys_open(dfd, filename, flags, mode); 1078 return do_sys_open(dfd, filename, flags, mode);
1079} 1079}
1080 1080
1081#ifdef CONFIG_COMPAT
1082/*
1083 * Exactly like sys_open(), except that it doesn't set the
1084 * O_LARGEFILE flag.
1085 */
1086COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
1087{
1088 return do_sys_open(AT_FDCWD, filename, flags, mode);
1089}
1090
1091/*
1092 * Exactly like sys_openat(), except that it doesn't set the
1093 * O_LARGEFILE flag.
1094 */
1095COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)
1096{
1097 return do_sys_open(dfd, filename, flags, mode);
1098}
1099#endif
1100
1081#ifndef __alpha__ 1101#ifndef __alpha__
1082 1102
1083/* 1103/*
diff --git a/fs/read_write.c b/fs/read_write.c
index c4f88afbc67f..47c1d4484df9 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -841,6 +841,81 @@ out:
841 return ret; 841 return ret;
842} 842}
843 843
844#ifdef CONFIG_COMPAT
845ssize_t compat_rw_copy_check_uvector(int type,
846 const struct compat_iovec __user *uvector, unsigned long nr_segs,
847 unsigned long fast_segs, struct iovec *fast_pointer,
848 struct iovec **ret_pointer)
849{
850 compat_ssize_t tot_len;
851 struct iovec *iov = *ret_pointer = fast_pointer;
852 ssize_t ret = 0;
853 int seg;
854
855 /*
856 * SuS says "The readv() function *may* fail if the iovcnt argument
857 * was less than or equal to 0, or greater than {IOV_MAX}. Linux has
858 * traditionally returned zero for zero segments, so...
859 */
860 if (nr_segs == 0)
861 goto out;
862
863 ret = -EINVAL;
864 if (nr_segs > UIO_MAXIOV)
865 goto out;
866 if (nr_segs > fast_segs) {
867 ret = -ENOMEM;
868 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
869 if (iov == NULL)
870 goto out;
871 }
872 *ret_pointer = iov;
873
874 ret = -EFAULT;
875 if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
876 goto out;
877
878 /*
879 * Single unix specification:
880 * We should -EINVAL if an element length is not >= 0 and fitting an
881 * ssize_t.
882 *
883 * In Linux, the total length is limited to MAX_RW_COUNT, there is
884 * no overflow possibility.
885 */
886 tot_len = 0;
887 ret = -EINVAL;
888 for (seg = 0; seg < nr_segs; seg++) {
889 compat_uptr_t buf;
890 compat_ssize_t len;
891
892 if (__get_user(len, &uvector->iov_len) ||
893 __get_user(buf, &uvector->iov_base)) {
894 ret = -EFAULT;
895 goto out;
896 }
897 if (len < 0) /* size_t not fitting in compat_ssize_t .. */
898 goto out;
899 if (type >= 0 &&
900 !access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
901 ret = -EFAULT;
902 goto out;
903 }
904 if (len > MAX_RW_COUNT - tot_len)
905 len = MAX_RW_COUNT - tot_len;
906 tot_len += len;
907 iov->iov_base = compat_ptr(buf);
908 iov->iov_len = (compat_size_t) len;
909 uvector++;
910 iov++;
911 }
912 ret = tot_len;
913
914out:
915 return ret;
916}
917#endif
918
844static ssize_t __do_readv_writev(int type, struct file *file, 919static ssize_t __do_readv_writev(int type, struct file *file,
845 struct iov_iter *iter, loff_t *pos, int flags) 920 struct iov_iter *iter, loff_t *pos, int flags)
846{ 921{
diff --git a/fs/readdir.c b/fs/readdir.c
index 0e8a7f355f7a..89659549c09d 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -18,6 +18,7 @@
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/syscalls.h> 19#include <linux/syscalls.h>
20#include <linux/unistd.h> 20#include <linux/unistd.h>
21#include <linux/compat.h>
21 22
22#include <linux/uaccess.h> 23#include <linux/uaccess.h>
23 24
@@ -324,3 +325,167 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
324 fdput_pos(f); 325 fdput_pos(f);
325 return error; 326 return error;
326} 327}
328
329#ifdef CONFIG_COMPAT
330struct compat_old_linux_dirent {
331 compat_ulong_t d_ino;
332 compat_ulong_t d_offset;
333 unsigned short d_namlen;
334 char d_name[1];
335};
336
337struct compat_readdir_callback {
338 struct dir_context ctx;
339 struct compat_old_linux_dirent __user *dirent;
340 int result;
341};
342
343static int compat_fillonedir(struct dir_context *ctx, const char *name,
344 int namlen, loff_t offset, u64 ino,
345 unsigned int d_type)
346{
347 struct compat_readdir_callback *buf =
348 container_of(ctx, struct compat_readdir_callback, ctx);
349 struct compat_old_linux_dirent __user *dirent;
350 compat_ulong_t d_ino;
351
352 if (buf->result)
353 return -EINVAL;
354 d_ino = ino;
355 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
356 buf->result = -EOVERFLOW;
357 return -EOVERFLOW;
358 }
359 buf->result++;
360 dirent = buf->dirent;
361 if (!access_ok(VERIFY_WRITE, dirent,
362 (unsigned long)(dirent->d_name + namlen + 1) -
363 (unsigned long)dirent))
364 goto efault;
365 if ( __put_user(d_ino, &dirent->d_ino) ||
366 __put_user(offset, &dirent->d_offset) ||
367 __put_user(namlen, &dirent->d_namlen) ||
368 __copy_to_user(dirent->d_name, name, namlen) ||
369 __put_user(0, dirent->d_name + namlen))
370 goto efault;
371 return 0;
372efault:
373 buf->result = -EFAULT;
374 return -EFAULT;
375}
376
377COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
378 struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
379{
380 int error;
381 struct fd f = fdget_pos(fd);
382 struct compat_readdir_callback buf = {
383 .ctx.actor = compat_fillonedir,
384 .dirent = dirent
385 };
386
387 if (!f.file)
388 return -EBADF;
389
390 error = iterate_dir(f.file, &buf.ctx);
391 if (buf.result)
392 error = buf.result;
393
394 fdput_pos(f);
395 return error;
396}
397
398struct compat_linux_dirent {
399 compat_ulong_t d_ino;
400 compat_ulong_t d_off;
401 unsigned short d_reclen;
402 char d_name[1];
403};
404
405struct compat_getdents_callback {
406 struct dir_context ctx;
407 struct compat_linux_dirent __user *current_dir;
408 struct compat_linux_dirent __user *previous;
409 int count;
410 int error;
411};
412
413static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
414 loff_t offset, u64 ino, unsigned int d_type)
415{
416 struct compat_linux_dirent __user * dirent;
417 struct compat_getdents_callback *buf =
418 container_of(ctx, struct compat_getdents_callback, ctx);
419 compat_ulong_t d_ino;
420 int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
421 namlen + 2, sizeof(compat_long_t));
422
423 buf->error = -EINVAL; /* only used if we fail.. */
424 if (reclen > buf->count)
425 return -EINVAL;
426 d_ino = ino;
427 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
428 buf->error = -EOVERFLOW;
429 return -EOVERFLOW;
430 }
431 dirent = buf->previous;
432 if (dirent) {
433 if (signal_pending(current))
434 return -EINTR;
435 if (__put_user(offset, &dirent->d_off))
436 goto efault;
437 }
438 dirent = buf->current_dir;
439 if (__put_user(d_ino, &dirent->d_ino))
440 goto efault;
441 if (__put_user(reclen, &dirent->d_reclen))
442 goto efault;
443 if (copy_to_user(dirent->d_name, name, namlen))
444 goto efault;
445 if (__put_user(0, dirent->d_name + namlen))
446 goto efault;
447 if (__put_user(d_type, (char __user *) dirent + reclen - 1))
448 goto efault;
449 buf->previous = dirent;
450 dirent = (void __user *)dirent + reclen;
451 buf->current_dir = dirent;
452 buf->count -= reclen;
453 return 0;
454efault:
455 buf->error = -EFAULT;
456 return -EFAULT;
457}
458
459COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
460 struct compat_linux_dirent __user *, dirent, unsigned int, count)
461{
462 struct fd f;
463 struct compat_linux_dirent __user * lastdirent;
464 struct compat_getdents_callback buf = {
465 .ctx.actor = compat_filldir,
466 .current_dir = dirent,
467 .count = count
468 };
469 int error;
470
471 if (!access_ok(VERIFY_WRITE, dirent, count))
472 return -EFAULT;
473
474 f = fdget_pos(fd);
475 if (!f.file)
476 return -EBADF;
477
478 error = iterate_dir(f.file, &buf.ctx);
479 if (error >= 0)
480 error = buf.error;
481 lastdirent = buf.previous;
482 if (lastdirent) {
483 if (put_user(buf.ctx.pos, &lastdirent->d_off))
484 error = -EFAULT;
485 else
486 error = count - buf.count;
487 }
488 fdput_pos(f);
489 return error;
490}
491#endif
diff --git a/fs/select.c b/fs/select.c
index e2112270d75a..dd70937ddb60 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -338,6 +338,53 @@ sticky:
338 return ret; 338 return ret;
339} 339}
340 340
341/*
342 * Scalable version of the fd_set.
343 */
344
345typedef struct {
346 unsigned long *in, *out, *ex;
347 unsigned long *res_in, *res_out, *res_ex;
348} fd_set_bits;
349
350/*
351 * How many longwords for "nr" bits?
352 */
353#define FDS_BITPERLONG (8*sizeof(long))
354#define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)
355#define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long))
356
357/*
358 * We do a VERIFY_WRITE here even though we are only reading this time:
359 * we'll write to it eventually..
360 *
361 * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
362 */
363static inline
364int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
365{
366 nr = FDS_BYTES(nr);
367 if (ufdset)
368 return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0;
369
370 memset(fdset, 0, nr);
371 return 0;
372}
373
374static inline unsigned long __must_check
375set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
376{
377 if (ufdset)
378 return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
379 return 0;
380}
381
382static inline
383void zero_fd_set(unsigned long nr, unsigned long *fdset)
384{
385 memset(fdset, 0, FDS_BYTES(nr));
386}
387
341#define FDS_IN(fds, n) (fds->in + n) 388#define FDS_IN(fds, n) (fds->in + n)
342#define FDS_OUT(fds, n) (fds->out + n) 389#define FDS_OUT(fds, n) (fds->out + n)
343#define FDS_EX(fds, n) (fds->ex + n) 390#define FDS_EX(fds, n) (fds->ex + n)
@@ -401,7 +448,7 @@ static inline void wait_key_set(poll_table *wait, unsigned long in,
401 wait->_key |= POLLOUT_SET; 448 wait->_key |= POLLOUT_SET;
402} 449}
403 450
404int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time) 451static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
405{ 452{
406 ktime_t expire, *to = NULL; 453 ktime_t expire, *to = NULL;
407 struct poll_wqueues table; 454 struct poll_wqueues table;
@@ -881,7 +928,7 @@ static int do_poll(struct poll_list *list, struct poll_wqueues *wait,
881#define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \ 928#define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \
882 sizeof(struct pollfd)) 929 sizeof(struct pollfd))
883 930
884int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, 931static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
885 struct timespec64 *end_time) 932 struct timespec64 *end_time)
886{ 933{
887 struct poll_wqueues table; 934 struct poll_wqueues table;
@@ -1053,3 +1100,373 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
1053 1100
1054 return ret; 1101 return ret;
1055} 1102}
1103
1104#ifdef CONFIG_COMPAT
1105#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
1106
1107static
1108int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1109 int timeval, int ret)
1110{
1111 struct timespec ts;
1112
1113 if (!p)
1114 return ret;
1115
1116 if (current->personality & STICKY_TIMEOUTS)
1117 goto sticky;
1118
1119 /* No update for zero timeout */
1120 if (!end_time->tv_sec && !end_time->tv_nsec)
1121 return ret;
1122
1123 ktime_get_ts(&ts);
1124 ts = timespec_sub(*end_time, ts);
1125 if (ts.tv_sec < 0)
1126 ts.tv_sec = ts.tv_nsec = 0;
1127
1128 if (timeval) {
1129 struct compat_timeval rtv;
1130
1131 rtv.tv_sec = ts.tv_sec;
1132 rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1133
1134 if (!copy_to_user(p, &rtv, sizeof(rtv)))
1135 return ret;
1136 } else {
1137 struct compat_timespec rts;
1138
1139 rts.tv_sec = ts.tv_sec;
1140 rts.tv_nsec = ts.tv_nsec;
1141
1142 if (!copy_to_user(p, &rts, sizeof(rts)))
1143 return ret;
1144 }
1145 /*
1146 * If an application puts its timeval in read-only memory, we
1147 * don't want the Linux-specific update to the timeval to
1148 * cause a fault after the select has completed
1149 * successfully. However, because we're not updating the
1150 * timeval, we can't restart the system call.
1151 */
1152
1153sticky:
1154 if (ret == -ERESTARTNOHAND)
1155 ret = -EINTR;
1156 return ret;
1157}
1158
1159/*
1160 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1161 * 64-bit unsigned longs.
1162 */
1163static
1164int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1165 unsigned long *fdset)
1166{
1167 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1168 if (ufdset) {
1169 unsigned long odd;
1170
1171 if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
1172 return -EFAULT;
1173
1174 odd = nr & 1UL;
1175 nr &= ~1UL;
1176 while (nr) {
1177 unsigned long h, l;
1178 if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
1179 return -EFAULT;
1180 ufdset += 2;
1181 *fdset++ = h << 32 | l;
1182 nr -= 2;
1183 }
1184 if (odd && __get_user(*fdset, ufdset))
1185 return -EFAULT;
1186 } else {
1187 /* Tricky, must clear full unsigned long in the
1188 * kernel fdset at the end, this makes sure that
1189 * actually happens.
1190 */
1191 memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
1192 }
1193 return 0;
1194}
1195
1196static
1197int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1198 unsigned long *fdset)
1199{
1200 unsigned long odd;
1201 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1202
1203 if (!ufdset)
1204 return 0;
1205
1206 odd = nr & 1UL;
1207 nr &= ~1UL;
1208 while (nr) {
1209 unsigned long h, l;
1210 l = *fdset++;
1211 h = l >> 32;
1212 if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
1213 return -EFAULT;
1214 ufdset += 2;
1215 nr -= 2;
1216 }
1217 if (odd && __put_user(*fdset, ufdset))
1218 return -EFAULT;
1219 return 0;
1220}
1221
1222
1223/*
1224 * This is a virtual copy of sys_select from fs/select.c and probably
1225 * should be compared to it from time to time
1226 */
1227
1228/*
1229 * We can actually return ERESTARTSYS instead of EINTR, but I'd
1230 * like to be certain this leads to no problems. So I return
1231 * EINTR just for safety.
1232 *
1233 * Update: ERESTARTSYS breaks at least the xview clock binary, so
1234 * I'm trying ERESTARTNOHAND which restart only when you want to.
1235 */
1236static int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1237 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1238 struct timespec *end_time)
1239{
1240 fd_set_bits fds;
1241 void *bits;
1242 int size, max_fds, ret = -EINVAL;
1243 struct fdtable *fdt;
1244 long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
1245
1246 if (n < 0)
1247 goto out_nofds;
1248
1249 /* max_fds can increase, so grab it once to avoid race */
1250 rcu_read_lock();
1251 fdt = files_fdtable(current->files);
1252 max_fds = fdt->max_fds;
1253 rcu_read_unlock();
1254 if (n > max_fds)
1255 n = max_fds;
1256
1257 /*
1258 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1259 * since we used fdset we need to allocate memory in units of
1260 * long-words.
1261 */
1262 size = FDS_BYTES(n);
1263 bits = stack_fds;
1264 if (size > sizeof(stack_fds) / 6) {
1265 bits = kmalloc(6 * size, GFP_KERNEL);
1266 ret = -ENOMEM;
1267 if (!bits)
1268 goto out_nofds;
1269 }
1270 fds.in = (unsigned long *) bits;
1271 fds.out = (unsigned long *) (bits + size);
1272 fds.ex = (unsigned long *) (bits + 2*size);
1273 fds.res_in = (unsigned long *) (bits + 3*size);
1274 fds.res_out = (unsigned long *) (bits + 4*size);
1275 fds.res_ex = (unsigned long *) (bits + 5*size);
1276
1277 if ((ret = compat_get_fd_set(n, inp, fds.in)) ||
1278 (ret = compat_get_fd_set(n, outp, fds.out)) ||
1279 (ret = compat_get_fd_set(n, exp, fds.ex)))
1280 goto out;
1281 zero_fd_set(n, fds.res_in);
1282 zero_fd_set(n, fds.res_out);
1283 zero_fd_set(n, fds.res_ex);
1284
1285 ret = do_select(n, &fds, end_time);
1286
1287 if (ret < 0)
1288 goto out;
1289 if (!ret) {
1290 ret = -ERESTARTNOHAND;
1291 if (signal_pending(current))
1292 goto out;
1293 ret = 0;
1294 }
1295
1296 if (compat_set_fd_set(n, inp, fds.res_in) ||
1297 compat_set_fd_set(n, outp, fds.res_out) ||
1298 compat_set_fd_set(n, exp, fds.res_ex))
1299 ret = -EFAULT;
1300out:
1301 if (bits != stack_fds)
1302 kfree(bits);
1303out_nofds:
1304 return ret;
1305}
1306
1307COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
1308 compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1309 struct compat_timeval __user *, tvp)
1310{
1311 struct timespec end_time, *to = NULL;
1312 struct compat_timeval tv;
1313 int ret;
1314
1315 if (tvp) {
1316 if (copy_from_user(&tv, tvp, sizeof(tv)))
1317 return -EFAULT;
1318
1319 to = &end_time;
1320 if (poll_select_set_timeout(to,
1321 tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
1322 (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
1323 return -EINVAL;
1324 }
1325
1326 ret = compat_core_sys_select(n, inp, outp, exp, to);
1327 ret = compat_poll_select_copy_remaining(&end_time, tvp, 1, ret);
1328
1329 return ret;
1330}
1331
1332struct compat_sel_arg_struct {
1333 compat_ulong_t n;
1334 compat_uptr_t inp;
1335 compat_uptr_t outp;
1336 compat_uptr_t exp;
1337 compat_uptr_t tvp;
1338};
1339
1340COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
1341{
1342 struct compat_sel_arg_struct a;
1343
1344 if (copy_from_user(&a, arg, sizeof(a)))
1345 return -EFAULT;
1346 return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
1347 compat_ptr(a.exp), compat_ptr(a.tvp));
1348}
1349
1350static long do_compat_pselect(int n, compat_ulong_t __user *inp,
1351 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1352 struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
1353 compat_size_t sigsetsize)
1354{
1355 compat_sigset_t ss32;
1356 sigset_t ksigmask, sigsaved;
1357 struct compat_timespec ts;
1358 struct timespec end_time, *to = NULL;
1359 int ret;
1360
1361 if (tsp) {
1362 if (copy_from_user(&ts, tsp, sizeof(ts)))
1363 return -EFAULT;
1364
1365 to = &end_time;
1366 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1367 return -EINVAL;
1368 }
1369
1370 if (sigmask) {
1371 if (sigsetsize != sizeof(compat_sigset_t))
1372 return -EINVAL;
1373 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1374 return -EFAULT;
1375 sigset_from_compat(&ksigmask, &ss32);
1376
1377 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1378 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1379 }
1380
1381 ret = compat_core_sys_select(n, inp, outp, exp, to);
1382 ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);
1383
1384 if (ret == -ERESTARTNOHAND) {
1385 /*
1386 * Don't restore the signal mask yet. Let do_signal() deliver
1387 * the signal on the way back to userspace, before the signal
1388 * mask is restored.
1389 */
1390 if (sigmask) {
1391 memcpy(&current->saved_sigmask, &sigsaved,
1392 sizeof(sigsaved));
1393 set_restore_sigmask();
1394 }
1395 } else if (sigmask)
1396 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1397
1398 return ret;
1399}
1400
1401COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
1402 compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1403 struct compat_timespec __user *, tsp, void __user *, sig)
1404{
1405 compat_size_t sigsetsize = 0;
1406 compat_uptr_t up = 0;
1407
1408 if (sig) {
1409 if (!access_ok(VERIFY_READ, sig,
1410 sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
1411 __get_user(up, (compat_uptr_t __user *)sig) ||
1412 __get_user(sigsetsize,
1413 (compat_size_t __user *)(sig+sizeof(up))))
1414 return -EFAULT;
1415 }
1416 return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
1417 sigsetsize);
1418}
1419
1420COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
1421 unsigned int, nfds, struct compat_timespec __user *, tsp,
1422 const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
1423{
1424 compat_sigset_t ss32;
1425 sigset_t ksigmask, sigsaved;
1426 struct compat_timespec ts;
1427 struct timespec end_time, *to = NULL;
1428 int ret;
1429
1430 if (tsp) {
1431 if (copy_from_user(&ts, tsp, sizeof(ts)))
1432 return -EFAULT;
1433
1434 to = &end_time;
1435 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1436 return -EINVAL;
1437 }
1438
1439 if (sigmask) {
1440 if (sigsetsize != sizeof(compat_sigset_t))
1441 return -EINVAL;
1442 if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1443 return -EFAULT;
1444 sigset_from_compat(&ksigmask, &ss32);
1445
1446 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1447 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1448 }
1449
1450 ret = do_sys_poll(ufds, nfds, to);
1451
1452 /* We can restart this syscall, usually */
1453 if (ret == -EINTR) {
1454 /*
1455 * Don't restore the signal mask yet. Let do_signal() deliver
1456 * the signal on the way back to userspace, before the signal
1457 * mask is restored.
1458 */
1459 if (sigmask) {
1460 memcpy(&current->saved_sigmask, &sigsaved,
1461 sizeof(sigsaved));
1462 set_restore_sigmask();
1463 }
1464 ret = -ERESTARTNOHAND;
1465 } else if (sigmask)
1466 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1467
1468 ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);
1469
1470 return ret;
1471}
1472#endif
diff --git a/fs/stat.c b/fs/stat.c
index a257b872a53d..f494b182c7c7 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -15,6 +15,7 @@
15#include <linux/cred.h> 15#include <linux/cred.h>
16#include <linux/syscalls.h> 16#include <linux/syscalls.h>
17#include <linux/pagemap.h> 17#include <linux/pagemap.h>
18#include <linux/compat.h>
18 19
19#include <linux/uaccess.h> 20#include <linux/uaccess.h>
20#include <asm/unistd.h> 21#include <asm/unistd.h>
@@ -575,6 +576,91 @@ SYSCALL_DEFINE5(statx,
575 return cp_statx(&stat, buffer); 576 return cp_statx(&stat, buffer);
576} 577}
577 578
579#ifdef CONFIG_COMPAT
580static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
581{
582 struct compat_stat tmp;
583
584 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
585 return -EOVERFLOW;
586
587 memset(&tmp, 0, sizeof(tmp));
588 tmp.st_dev = old_encode_dev(stat->dev);
589 tmp.st_ino = stat->ino;
590 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
591 return -EOVERFLOW;
592 tmp.st_mode = stat->mode;
593 tmp.st_nlink = stat->nlink;
594 if (tmp.st_nlink != stat->nlink)
595 return -EOVERFLOW;
596 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
597 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
598 tmp.st_rdev = old_encode_dev(stat->rdev);
599 if ((u64) stat->size > MAX_NON_LFS)
600 return -EOVERFLOW;
601 tmp.st_size = stat->size;
602 tmp.st_atime = stat->atime.tv_sec;
603 tmp.st_atime_nsec = stat->atime.tv_nsec;
604 tmp.st_mtime = stat->mtime.tv_sec;
605 tmp.st_mtime_nsec = stat->mtime.tv_nsec;
606 tmp.st_ctime = stat->ctime.tv_sec;
607 tmp.st_ctime_nsec = stat->ctime.tv_nsec;
608 tmp.st_blocks = stat->blocks;
609 tmp.st_blksize = stat->blksize;
610 return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
611}
612
613COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
614 struct compat_stat __user *, statbuf)
615{
616 struct kstat stat;
617 int error;
618
619 error = vfs_stat(filename, &stat);
620 if (error)
621 return error;
622 return cp_compat_stat(&stat, statbuf);
623}
624
625COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
626 struct compat_stat __user *, statbuf)
627{
628 struct kstat stat;
629 int error;
630
631 error = vfs_lstat(filename, &stat);
632 if (error)
633 return error;
634 return cp_compat_stat(&stat, statbuf);
635}
636
637#ifndef __ARCH_WANT_STAT64
638COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
639 const char __user *, filename,
640 struct compat_stat __user *, statbuf, int, flag)
641{
642 struct kstat stat;
643 int error;
644
645 error = vfs_fstatat(dfd, filename, &stat, flag);
646 if (error)
647 return error;
648 return cp_compat_stat(&stat, statbuf);
649}
650#endif
651
652COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
653 struct compat_stat __user *, statbuf)
654{
655 struct kstat stat;
656 int error = vfs_fstat(fd, &stat);
657
658 if (!error)
659 error = cp_compat_stat(&stat, statbuf);
660 return error;
661}
662#endif
663
578/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */ 664/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
579void __inode_add_bytes(struct inode *inode, loff_t bytes) 665void __inode_add_bytes(struct inode *inode, loff_t bytes)
580{ 666{
diff --git a/fs/statfs.c b/fs/statfs.c
index 13ae259d4879..4e4623c7a126 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -7,6 +7,7 @@
7#include <linux/statfs.h> 7#include <linux/statfs.h>
8#include <linux/security.h> 8#include <linux/security.h>
9#include <linux/uaccess.h> 9#include <linux/uaccess.h>
10#include <linux/compat.h>
10#include "internal.h" 11#include "internal.h"
11 12
12static int flags_by_mnt(int mnt_flags) 13static int flags_by_mnt(int mnt_flags)
@@ -239,3 +240,142 @@ SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
239 240
240 return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0; 241 return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
241} 242}
243
244#ifdef CONFIG_COMPAT
245static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
246{
247 if (sizeof ubuf->f_blocks == 4) {
248 if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
249 kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
250 return -EOVERFLOW;
251 /* f_files and f_ffree may be -1; it's okay
252 * to stuff that into 32 bits */
253 if (kbuf->f_files != 0xffffffffffffffffULL
254 && (kbuf->f_files & 0xffffffff00000000ULL))
255 return -EOVERFLOW;
256 if (kbuf->f_ffree != 0xffffffffffffffffULL
257 && (kbuf->f_ffree & 0xffffffff00000000ULL))
258 return -EOVERFLOW;
259 }
260 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
261 __put_user(kbuf->f_type, &ubuf->f_type) ||
262 __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
263 __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
264 __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
265 __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
266 __put_user(kbuf->f_files, &ubuf->f_files) ||
267 __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
268 __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
269 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
270 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
271 __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
272 __put_user(kbuf->f_flags, &ubuf->f_flags) ||
273 __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
274 return -EFAULT;
275 return 0;
276}
277
278/*
279 * The following statfs calls are copies of code from fs/statfs.c and
280 * should be checked against those from time to time
281 */
282COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
283{
284 struct kstatfs tmp;
285 int error = user_statfs(pathname, &tmp);
286 if (!error)
287 error = put_compat_statfs(buf, &tmp);
288 return error;
289}
290
291COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
292{
293 struct kstatfs tmp;
294 int error = fd_statfs(fd, &tmp);
295 if (!error)
296 error = put_compat_statfs(buf, &tmp);
297 return error;
298}
299
300static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
301{
302 if (sizeof(ubuf->f_bsize) == 4) {
303 if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen |
304 kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL)
305 return -EOVERFLOW;
306 /* f_files and f_ffree may be -1; it's okay
307 * to stuff that into 32 bits */
308 if (kbuf->f_files != 0xffffffffffffffffULL
309 && (kbuf->f_files & 0xffffffff00000000ULL))
310 return -EOVERFLOW;
311 if (kbuf->f_ffree != 0xffffffffffffffffULL
312 && (kbuf->f_ffree & 0xffffffff00000000ULL))
313 return -EOVERFLOW;
314 }
315 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
316 __put_user(kbuf->f_type, &ubuf->f_type) ||
317 __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
318 __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
319 __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
320 __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
321 __put_user(kbuf->f_files, &ubuf->f_files) ||
322 __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
323 __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
324 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
325 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
326 __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
327 __put_user(kbuf->f_flags, &ubuf->f_flags) ||
328 __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
329 return -EFAULT;
330 return 0;
331}
332
333COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
334{
335 struct kstatfs tmp;
336 int error;
337
338 if (sz != sizeof(*buf))
339 return -EINVAL;
340
341 error = user_statfs(pathname, &tmp);
342 if (!error)
343 error = put_compat_statfs64(buf, &tmp);
344 return error;
345}
346
347COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
348{
349 struct kstatfs tmp;
350 int error;
351
352 if (sz != sizeof(*buf))
353 return -EINVAL;
354
355 error = fd_statfs(fd, &tmp);
356 if (!error)
357 error = put_compat_statfs64(buf, &tmp);
358 return error;
359}
360
361/*
362 * This is a copy of sys_ustat, just dealing with a structure layout.
363 * Given how simple this syscall is that apporach is more maintainable
364 * than the various conversion hacks.
365 */
366COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
367{
368 struct compat_ustat tmp;
369 struct kstatfs sbuf;
370 int err = vfs_ustat(new_decode_dev(dev), &sbuf);
371 if (err)
372 return err;
373
374 memset(&tmp, 0, sizeof(struct compat_ustat));
375 tmp.f_tfree = sbuf.f_bfree;
376 tmp.f_tinode = sbuf.f_ffree;
377 if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
378 return -EFAULT;
379 return 0;
380}
381#endif
diff --git a/fs/utimes.c b/fs/utimes.c
index 32b15b3f6629..6571d8c848a0 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -1,14 +1,10 @@
1#include <linux/compiler.h>
2#include <linux/file.h> 1#include <linux/file.h>
3#include <linux/fs.h>
4#include <linux/linkage.h>
5#include <linux/mount.h> 2#include <linux/mount.h>
6#include <linux/namei.h> 3#include <linux/namei.h>
7#include <linux/sched.h>
8#include <linux/stat.h>
9#include <linux/utime.h> 4#include <linux/utime.h>
10#include <linux/syscalls.h> 5#include <linux/syscalls.h>
11#include <linux/uaccess.h> 6#include <linux/uaccess.h>
7#include <linux/compat.h>
12#include <asm/unistd.h> 8#include <asm/unistd.h>
13 9
14#ifdef __ARCH_WANT_SYS_UTIME 10#ifdef __ARCH_WANT_SYS_UTIME
@@ -219,3 +215,63 @@ SYSCALL_DEFINE2(utimes, char __user *, filename,
219{ 215{
220 return sys_futimesat(AT_FDCWD, filename, utimes); 216 return sys_futimesat(AT_FDCWD, filename, utimes);
221} 217}
218
219#ifdef CONFIG_COMPAT
220/*
221 * Not all architectures have sys_utime, so implement this in terms
222 * of sys_utimes.
223 */
224COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
225 struct compat_utimbuf __user *, t)
226{
227 struct timespec tv[2];
228
229 if (t) {
230 if (get_user(tv[0].tv_sec, &t->actime) ||
231 get_user(tv[1].tv_sec, &t->modtime))
232 return -EFAULT;
233 tv[0].tv_nsec = 0;
234 tv[1].tv_nsec = 0;
235 }
236 return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
237}
238
239COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
240{
241 struct timespec tv[2];
242
243 if (t) {
244 if (compat_get_timespec(&tv[0], &t[0]) ||
245 compat_get_timespec(&tv[1], &t[1]))
246 return -EFAULT;
247
248 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
249 return 0;
250 }
251 return do_utimes(dfd, filename, t ? tv : NULL, flags);
252}
253
254COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
255{
256 struct timespec tv[2];
257
258 if (t) {
259 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
260 get_user(tv[0].tv_nsec, &t[0].tv_usec) ||
261 get_user(tv[1].tv_sec, &t[1].tv_sec) ||
262 get_user(tv[1].tv_nsec, &t[1].tv_usec))
263 return -EFAULT;
264 if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 ||
265 tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0)
266 return -EINVAL;
267 tv[0].tv_nsec *= 1000;
268 tv[1].tv_nsec *= 1000;
269 }
270 return do_utimes(dfd, filename, t ? tv : NULL, 0);
271}
272
273COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t)
274{
275 return compat_sys_futimesat(AT_FDCWD, filename, t);
276}
277#endif
diff --git a/include/linux/compat.h b/include/linux/compat.h
index af9dbc44fd92..8172b03685f9 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -528,11 +528,6 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
528asmlinkage long compat_sys_getdents(unsigned int fd, 528asmlinkage long compat_sys_getdents(unsigned int fd,
529 struct compat_linux_dirent __user *dirent, 529 struct compat_linux_dirent __user *dirent,
530 unsigned int count); 530 unsigned int count);
531#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
532asmlinkage long compat_sys_getdents64(unsigned int fd,
533 struct linux_dirent64 __user *dirent,
534 unsigned int count);
535#endif
536asmlinkage long compat_sys_vmsplice(int fd, const struct compat_iovec __user *, 531asmlinkage long compat_sys_vmsplice(int fd, const struct compat_iovec __user *,
537 unsigned int nr_segs, unsigned int flags); 532 unsigned int nr_segs, unsigned int flags);
538asmlinkage long compat_sys_open(const char __user *filename, int flags, 533asmlinkage long compat_sys_open(const char __user *filename, int flags,
diff --git a/include/linux/poll.h b/include/linux/poll.h
index a46d6755035e..75ffc5729e4c 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -98,64 +98,8 @@ extern int poll_schedule_timeout(struct poll_wqueues *pwq, int state,
98 ktime_t *expires, unsigned long slack); 98 ktime_t *expires, unsigned long slack);
99extern u64 select_estimate_accuracy(struct timespec64 *tv); 99extern u64 select_estimate_accuracy(struct timespec64 *tv);
100 100
101
102static inline int poll_schedule(struct poll_wqueues *pwq, int state)
103{
104 return poll_schedule_timeout(pwq, state, NULL, 0);
105}
106
107/*
108 * Scalable version of the fd_set.
109 */
110
111typedef struct {
112 unsigned long *in, *out, *ex;
113 unsigned long *res_in, *res_out, *res_ex;
114} fd_set_bits;
115
116/*
117 * How many longwords for "nr" bits?
118 */
119#define FDS_BITPERLONG (8*sizeof(long))
120#define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)
121#define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long))
122
123/*
124 * We do a VERIFY_WRITE here even though we are only reading this time:
125 * we'll write to it eventually..
126 *
127 * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
128 */
129static inline
130int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
131{
132 nr = FDS_BYTES(nr);
133 if (ufdset)
134 return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0;
135
136 memset(fdset, 0, nr);
137 return 0;
138}
139
140static inline unsigned long __must_check
141set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
142{
143 if (ufdset)
144 return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
145 return 0;
146}
147
148static inline
149void zero_fd_set(unsigned long nr, unsigned long *fdset)
150{
151 memset(fdset, 0, FDS_BYTES(nr));
152}
153
154#define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1) 101#define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1)
155 102
156extern int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time);
157extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
158 struct timespec64 *end_time);
159extern int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, 103extern int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
160 fd_set __user *exp, struct timespec64 *end_time); 104 fd_set __user *exp, struct timespec64 *end_time);
161 105
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index a076cf1a3a23..061185a5eb51 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -194,8 +194,7 @@ __SYSCALL(__NR_quotactl, sys_quotactl)
194 194
195/* fs/readdir.c */ 195/* fs/readdir.c */
196#define __NR_getdents64 61 196#define __NR_getdents64 61
197#define __ARCH_WANT_COMPAT_SYS_GETDENTS64 197__SYSCALL(__NR_getdents64, sys_getdents64)
198__SC_COMP(__NR_getdents64, sys_getdents64, compat_sys_getdents64)
199 198
200/* fs/read_write.c */ 199/* fs/read_write.c */
201#define __NR3264_lseek 62 200#define __NR3264_lseek 62