aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c162
1 files changed, 89 insertions, 73 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 6af20de2c1a3..ca926ad0430c 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -72,8 +72,8 @@ int compat_printk(const char *fmt, ...)
72 * Not all architectures have sys_utime, so implement this in terms 72 * Not all architectures have sys_utime, so implement this in terms
73 * of sys_utimes. 73 * of sys_utimes.
74 */ 74 */
75asmlinkage long compat_sys_utime(const char __user *filename, 75COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
76 struct compat_utimbuf __user *t) 76 struct compat_utimbuf __user *, t)
77{ 77{
78 struct timespec tv[2]; 78 struct timespec tv[2];
79 79
@@ -87,13 +87,13 @@ asmlinkage long compat_sys_utime(const char __user *filename,
87 return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); 87 return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
88} 88}
89 89
90asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, struct compat_timespec __user *t, int flags) 90COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
91{ 91{
92 struct timespec tv[2]; 92 struct timespec tv[2];
93 93
94 if (t) { 94 if (t) {
95 if (get_compat_timespec(&tv[0], &t[0]) || 95 if (compat_get_timespec(&tv[0], &t[0]) ||
96 get_compat_timespec(&tv[1], &t[1])) 96 compat_get_timespec(&tv[1], &t[1]))
97 return -EFAULT; 97 return -EFAULT;
98 98
99 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) 99 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
@@ -102,7 +102,7 @@ asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filena
102 return do_utimes(dfd, filename, t ? tv : NULL, flags); 102 return do_utimes(dfd, filename, t ? tv : NULL, flags);
103} 103}
104 104
105asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, struct compat_timeval __user *t) 105COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
106{ 106{
107 struct timespec tv[2]; 107 struct timespec tv[2];
108 108
@@ -121,7 +121,7 @@ asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filena
121 return do_utimes(dfd, filename, t ? tv : NULL, 0); 121 return do_utimes(dfd, filename, t ? tv : NULL, 0);
122} 122}
123 123
124asmlinkage long compat_sys_utimes(const char __user *filename, struct compat_timeval __user *t) 124COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t)
125{ 125{
126 return compat_sys_futimesat(AT_FDCWD, filename, t); 126 return compat_sys_futimesat(AT_FDCWD, filename, t);
127} 127}
@@ -159,8 +159,8 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
159 return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0; 159 return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
160} 160}
161 161
162asmlinkage long compat_sys_newstat(const char __user * filename, 162COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
163 struct compat_stat __user *statbuf) 163 struct compat_stat __user *, statbuf)
164{ 164{
165 struct kstat stat; 165 struct kstat stat;
166 int error; 166 int error;
@@ -171,8 +171,8 @@ asmlinkage long compat_sys_newstat(const char __user * filename,
171 return cp_compat_stat(&stat, statbuf); 171 return cp_compat_stat(&stat, statbuf);
172} 172}
173 173
174asmlinkage long compat_sys_newlstat(const char __user * filename, 174COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
175 struct compat_stat __user *statbuf) 175 struct compat_stat __user *, statbuf)
176{ 176{
177 struct kstat stat; 177 struct kstat stat;
178 int error; 178 int error;
@@ -184,9 +184,9 @@ asmlinkage long compat_sys_newlstat(const char __user * filename,
184} 184}
185 185
186#ifndef __ARCH_WANT_STAT64 186#ifndef __ARCH_WANT_STAT64
187asmlinkage long compat_sys_newfstatat(unsigned int dfd, 187COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
188 const char __user *filename, 188 const char __user *, filename,
189 struct compat_stat __user *statbuf, int flag) 189 struct compat_stat __user *, statbuf, int, flag)
190{ 190{
191 struct kstat stat; 191 struct kstat stat;
192 int error; 192 int error;
@@ -198,8 +198,8 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd,
198} 198}
199#endif 199#endif
200 200
201asmlinkage long compat_sys_newfstat(unsigned int fd, 201COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
202 struct compat_stat __user * statbuf) 202 struct compat_stat __user *, statbuf)
203{ 203{
204 struct kstat stat; 204 struct kstat stat;
205 int error = vfs_fstat(fd, &stat); 205 int error = vfs_fstat(fd, &stat);
@@ -247,7 +247,7 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
247 * The following statfs calls are copies of code from fs/statfs.c and 247 * The following statfs calls are copies of code from fs/statfs.c and
248 * should be checked against those from time to time 248 * should be checked against those from time to time
249 */ 249 */
250asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf) 250COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
251{ 251{
252 struct kstatfs tmp; 252 struct kstatfs tmp;
253 int error = user_statfs(pathname, &tmp); 253 int error = user_statfs(pathname, &tmp);
@@ -256,7 +256,7 @@ asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_sta
256 return error; 256 return error;
257} 257}
258 258
259asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf) 259COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
260{ 260{
261 struct kstatfs tmp; 261 struct kstatfs tmp;
262 int error = fd_statfs(fd, &tmp); 262 int error = fd_statfs(fd, &tmp);
@@ -298,7 +298,7 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
298 return 0; 298 return 0;
299} 299}
300 300
301asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf) 301COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
302{ 302{
303 struct kstatfs tmp; 303 struct kstatfs tmp;
304 int error; 304 int error;
@@ -312,7 +312,7 @@ asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t s
312 return error; 312 return error;
313} 313}
314 314
315asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) 315COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
316{ 316{
317 struct kstatfs tmp; 317 struct kstatfs tmp;
318 int error; 318 int error;
@@ -331,7 +331,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
331 * Given how simple this syscall is that apporach is more maintainable 331 * Given how simple this syscall is that apporach is more maintainable
332 * than the various conversion hacks. 332 * than the various conversion hacks.
333 */ 333 */
334asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u) 334COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
335{ 335{
336 struct compat_ustat tmp; 336 struct compat_ustat tmp;
337 struct kstatfs sbuf; 337 struct kstatfs sbuf;
@@ -399,12 +399,28 @@ static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *u
399} 399}
400#endif 400#endif
401 401
402asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, 402static unsigned int
403 unsigned long arg) 403convert_fcntl_cmd(unsigned int cmd)
404{
405 switch (cmd) {
406 case F_GETLK64:
407 return F_GETLK;
408 case F_SETLK64:
409 return F_SETLK;
410 case F_SETLKW64:
411 return F_SETLKW;
412 }
413
414 return cmd;
415}
416
417COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
418 compat_ulong_t, arg)
404{ 419{
405 mm_segment_t old_fs; 420 mm_segment_t old_fs;
406 struct flock f; 421 struct flock f;
407 long ret; 422 long ret;
423 unsigned int conv_cmd;
408 424
409 switch (cmd) { 425 switch (cmd) {
410 case F_GETLK: 426 case F_GETLK:
@@ -441,16 +457,18 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
441 case F_GETLK64: 457 case F_GETLK64:
442 case F_SETLK64: 458 case F_SETLK64:
443 case F_SETLKW64: 459 case F_SETLKW64:
460 case F_GETLKP:
461 case F_SETLKP:
462 case F_SETLKPW:
444 ret = get_compat_flock64(&f, compat_ptr(arg)); 463 ret = get_compat_flock64(&f, compat_ptr(arg));
445 if (ret != 0) 464 if (ret != 0)
446 break; 465 break;
447 old_fs = get_fs(); 466 old_fs = get_fs();
448 set_fs(KERNEL_DS); 467 set_fs(KERNEL_DS);
449 ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK : 468 conv_cmd = convert_fcntl_cmd(cmd);
450 ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW), 469 ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
451 (unsigned long)&f);
452 set_fs(old_fs); 470 set_fs(old_fs);
453 if (cmd == F_GETLK64 && ret == 0) { 471 if ((conv_cmd == F_GETLK || conv_cmd == F_GETLKP) && ret == 0) {
454 /* need to return lock information - see above for commentary */ 472 /* need to return lock information - see above for commentary */
455 if (f.l_start > COMPAT_LOFF_T_MAX) 473 if (f.l_start > COMPAT_LOFF_T_MAX)
456 ret = -EOVERFLOW; 474 ret = -EOVERFLOW;
@@ -468,16 +486,22 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
468 return ret; 486 return ret;
469} 487}
470 488
471asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd, 489COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
472 unsigned long arg) 490 compat_ulong_t, arg)
473{ 491{
474 if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64)) 492 switch (cmd) {
493 case F_GETLK64:
494 case F_SETLK64:
495 case F_SETLKW64:
496 case F_GETLKP:
497 case F_SETLKP:
498 case F_SETLKPW:
475 return -EINVAL; 499 return -EINVAL;
500 }
476 return compat_sys_fcntl64(fd, cmd, arg); 501 return compat_sys_fcntl64(fd, cmd, arg);
477} 502}
478 503
479asmlinkage long 504COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_reqs, u32 __user *, ctx32p)
480compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p)
481{ 505{
482 long ret; 506 long ret;
483 aio_context_t ctx64; 507 aio_context_t ctx64;
@@ -496,32 +520,24 @@ compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p)
496 return ret; 520 return ret;
497} 521}
498 522
499asmlinkage long 523COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
500compat_sys_io_getevents(aio_context_t ctx_id, 524 compat_long_t, min_nr,
501 unsigned long min_nr, 525 compat_long_t, nr,
502 unsigned long nr, 526 struct io_event __user *, events,
503 struct io_event __user *events, 527 struct compat_timespec __user *, timeout)
504 struct compat_timespec __user *timeout)
505{ 528{
506 long ret;
507 struct timespec t; 529 struct timespec t;
508 struct timespec __user *ut = NULL; 530 struct timespec __user *ut = NULL;
509 531
510 ret = -EFAULT;
511 if (unlikely(!access_ok(VERIFY_WRITE, events,
512 nr * sizeof(struct io_event))))
513 goto out;
514 if (timeout) { 532 if (timeout) {
515 if (get_compat_timespec(&t, timeout)) 533 if (compat_get_timespec(&t, timeout))
516 goto out; 534 return -EFAULT;
517 535
518 ut = compat_alloc_user_space(sizeof(*ut)); 536 ut = compat_alloc_user_space(sizeof(*ut));
519 if (copy_to_user(ut, &t, sizeof(t)) ) 537 if (copy_to_user(ut, &t, sizeof(t)) )
520 goto out; 538 return -EFAULT;
521 } 539 }
522 ret = sys_io_getevents(ctx_id, min_nr, nr, events, ut); 540 return sys_io_getevents(ctx_id, min_nr, nr, events, ut);
523out:
524 return ret;
525} 541}
526 542
527/* A write operation does a read from user space and vice versa */ 543/* A write operation does a read from user space and vice versa */
@@ -617,8 +633,8 @@ copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64)
617 633
618#define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) 634#define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *))
619 635
620asmlinkage long 636COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
621compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb) 637 int, nr, u32 __user *, iocb)
622{ 638{
623 struct iocb __user * __user *iocb64; 639 struct iocb __user * __user *iocb64;
624 long ret; 640 long ret;
@@ -770,10 +786,10 @@ static int do_nfs4_super_data_conv(void *raw_data)
770#define NCPFS_NAME "ncpfs" 786#define NCPFS_NAME "ncpfs"
771#define NFS4_NAME "nfs4" 787#define NFS4_NAME "nfs4"
772 788
773asmlinkage long compat_sys_mount(const char __user * dev_name, 789COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
774 const char __user * dir_name, 790 const char __user *, dir_name,
775 const char __user * type, unsigned long flags, 791 const char __user *, type, compat_ulong_t, flags,
776 const void __user * data) 792 const void __user *, data)
777{ 793{
778 char *kernel_type; 794 char *kernel_type;
779 unsigned long data_page; 795 unsigned long data_page;
@@ -869,8 +885,8 @@ efault:
869 return -EFAULT; 885 return -EFAULT;
870} 886}
871 887
872asmlinkage long compat_sys_old_readdir(unsigned int fd, 888COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
873 struct compat_old_linux_dirent __user *dirent, unsigned int count) 889 struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
874{ 890{
875 int error; 891 int error;
876 struct fd f = fdget(fd); 892 struct fd f = fdget(fd);
@@ -948,8 +964,8 @@ efault:
948 return -EFAULT; 964 return -EFAULT;
949} 965}
950 966
951asmlinkage long compat_sys_getdents(unsigned int fd, 967COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
952 struct compat_linux_dirent __user *dirent, unsigned int count) 968 struct compat_linux_dirent __user *, dirent, unsigned int, count)
953{ 969{
954 struct fd f; 970 struct fd f;
955 struct compat_linux_dirent __user * lastdirent; 971 struct compat_linux_dirent __user * lastdirent;
@@ -981,7 +997,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
981 return error; 997 return error;
982} 998}
983 999
984#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 1000#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
985 1001
986struct compat_getdents_callback64 { 1002struct compat_getdents_callback64 {
987 struct dir_context ctx; 1003 struct dir_context ctx;
@@ -1033,8 +1049,8 @@ efault:
1033 return -EFAULT; 1049 return -EFAULT;
1034} 1050}
1035 1051
1036asmlinkage long compat_sys_getdents64(unsigned int fd, 1052COMPAT_SYSCALL_DEFINE3(getdents64, unsigned int, fd,
1037 struct linux_dirent64 __user * dirent, unsigned int count) 1053 struct linux_dirent64 __user *, dirent, unsigned int, count)
1038{ 1054{
1039 struct fd f; 1055 struct fd f;
1040 struct linux_dirent64 __user * lastdirent; 1056 struct linux_dirent64 __user * lastdirent;
@@ -1066,7 +1082,7 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
1066 fdput(f); 1082 fdput(f);
1067 return error; 1083 return error;
1068} 1084}
1069#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */ 1085#endif /* __ARCH_WANT_COMPAT_SYS_GETDENTS64 */
1070 1086
1071/* 1087/*
1072 * Exactly like fs/open.c:sys_open(), except that it doesn't set the 1088 * Exactly like fs/open.c:sys_open(), except that it doesn't set the
@@ -1287,9 +1303,9 @@ out_nofds:
1287 return ret; 1303 return ret;
1288} 1304}
1289 1305
1290asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, 1306COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
1291 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1307 compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1292 struct compat_timeval __user *tvp) 1308 struct compat_timeval __user *, tvp)
1293{ 1309{
1294 struct timespec end_time, *to = NULL; 1310 struct timespec end_time, *to = NULL;
1295 struct compat_timeval tv; 1311 struct compat_timeval tv;
@@ -1320,7 +1336,7 @@ struct compat_sel_arg_struct {
1320 compat_uptr_t tvp; 1336 compat_uptr_t tvp;
1321}; 1337};
1322 1338
1323asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg) 1339COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
1324{ 1340{
1325 struct compat_sel_arg_struct a; 1341 struct compat_sel_arg_struct a;
1326 1342
@@ -1381,9 +1397,9 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
1381 return ret; 1397 return ret;
1382} 1398}
1383 1399
1384asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, 1400COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
1385 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1401 compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1386 struct compat_timespec __user *tsp, void __user *sig) 1402 struct compat_timespec __user *, tsp, void __user *, sig)
1387{ 1403{
1388 compat_size_t sigsetsize = 0; 1404 compat_size_t sigsetsize = 0;
1389 compat_uptr_t up = 0; 1405 compat_uptr_t up = 0;
@@ -1400,9 +1416,9 @@ asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
1400 sigsetsize); 1416 sigsetsize);
1401} 1417}
1402 1418
1403asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, 1419COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
1404 unsigned int nfds, struct compat_timespec __user *tsp, 1420 unsigned int, nfds, struct compat_timespec __user *, tsp,
1405 const compat_sigset_t __user *sigmask, compat_size_t sigsetsize) 1421 const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
1406{ 1422{
1407 compat_sigset_t ss32; 1423 compat_sigset_t ss32;
1408 sigset_t ksigmask, sigsaved; 1424 sigset_t ksigmask, sigsaved;