at v2.6.26-rc7 2195 lines 54 kB view raw
1/* 2 * linux/fs/compat.c 3 * 4 * Kernel compatibililty routines for e.g. 32 bit syscall support 5 * on 64 bit kernels. 6 * 7 * Copyright (C) 2002 Stephen Rothwell, IBM Corporation 8 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) 9 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 10 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs 11 * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License version 2 as 15 * published by the Free Software Foundation. 16 */ 17 18#include <linux/kernel.h> 19#include <linux/linkage.h> 20#include <linux/compat.h> 21#include <linux/errno.h> 22#include <linux/time.h> 23#include <linux/fs.h> 24#include <linux/fcntl.h> 25#include <linux/namei.h> 26#include <linux/file.h> 27#include <linux/fdtable.h> 28#include <linux/vfs.h> 29#include <linux/ioctl.h> 30#include <linux/init.h> 31#include <linux/smb.h> 32#include <linux/smb_mount.h> 33#include <linux/ncp_mount.h> 34#include <linux/nfs4_mount.h> 35#include <linux/smp_lock.h> 36#include <linux/syscalls.h> 37#include <linux/ctype.h> 38#include <linux/module.h> 39#include <linux/dirent.h> 40#include <linux/fsnotify.h> 41#include <linux/highuid.h> 42#include <linux/sunrpc/svc.h> 43#include <linux/nfsd/nfsd.h> 44#include <linux/nfsd/syscall.h> 45#include <linux/personality.h> 46#include <linux/rwsem.h> 47#include <linux/tsacct_kern.h> 48#include <linux/security.h> 49#include <linux/highmem.h> 50#include <linux/signal.h> 51#include <linux/poll.h> 52#include <linux/mm.h> 53#include <linux/eventpoll.h> 54 55#include <asm/uaccess.h> 56#include <asm/mmu_context.h> 57#include <asm/ioctls.h> 58#include "internal.h" 59 60int compat_log = 1; 61 62int compat_printk(const char *fmt, ...) 63{ 64 va_list ap; 65 int ret; 66 if (!compat_log) 67 return 0; 68 va_start(ap, fmt); 69 ret = vprintk(fmt, ap); 70 va_end(ap); 71 return ret; 72} 73 74#include "read_write.h" 75 76/* 77 * Not all architectures have sys_utime, so implement this in terms 78 * of sys_utimes. 79 */ 80asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __user *t) 81{ 82 struct timespec tv[2]; 83 84 if (t) { 85 if (get_user(tv[0].tv_sec, &t->actime) || 86 get_user(tv[1].tv_sec, &t->modtime)) 87 return -EFAULT; 88 tv[0].tv_nsec = 0; 89 tv[1].tv_nsec = 0; 90 } 91 return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); 92} 93 94asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags) 95{ 96 struct timespec tv[2]; 97 98 if (t) { 99 if (get_compat_timespec(&tv[0], &t[0]) || 100 get_compat_timespec(&tv[1], &t[1])) 101 return -EFAULT; 102 103 if ((tv[0].tv_nsec == UTIME_OMIT || tv[0].tv_nsec == UTIME_NOW) 104 && tv[0].tv_sec != 0) 105 return -EINVAL; 106 if ((tv[1].tv_nsec == UTIME_OMIT || tv[1].tv_nsec == UTIME_NOW) 107 && tv[1].tv_sec != 0) 108 return -EINVAL; 109 110 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) 111 return 0; 112 } 113 return do_utimes(dfd, filename, t ? tv : NULL, flags); 114} 115 116asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t) 117{ 118 struct timespec tv[2]; 119 120 if (t) { 121 if (get_user(tv[0].tv_sec, &t[0].tv_sec) || 122 get_user(tv[0].tv_nsec, &t[0].tv_usec) || 123 get_user(tv[1].tv_sec, &t[1].tv_sec) || 124 get_user(tv[1].tv_nsec, &t[1].tv_usec)) 125 return -EFAULT; 126 if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 || 127 tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0) 128 return -EINVAL; 129 tv[0].tv_nsec *= 1000; 130 tv[1].tv_nsec *= 1000; 131 } 132 return do_utimes(dfd, filename, t ? tv : NULL, 0); 133} 134 135asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t) 136{ 137 return compat_sys_futimesat(AT_FDCWD, filename, t); 138} 139 140asmlinkage long compat_sys_newstat(char __user * filename, 141 struct compat_stat __user *statbuf) 142{ 143 struct kstat stat; 144 int error = vfs_stat_fd(AT_FDCWD, filename, &stat); 145 146 if (!error) 147 error = cp_compat_stat(&stat, statbuf); 148 return error; 149} 150 151asmlinkage long compat_sys_newlstat(char __user * filename, 152 struct compat_stat __user *statbuf) 153{ 154 struct kstat stat; 155 int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); 156 157 if (!error) 158 error = cp_compat_stat(&stat, statbuf); 159 return error; 160} 161 162#ifndef __ARCH_WANT_STAT64 163asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename, 164 struct compat_stat __user *statbuf, int flag) 165{ 166 struct kstat stat; 167 int error = -EINVAL; 168 169 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) 170 goto out; 171 172 if (flag & AT_SYMLINK_NOFOLLOW) 173 error = vfs_lstat_fd(dfd, filename, &stat); 174 else 175 error = vfs_stat_fd(dfd, filename, &stat); 176 177 if (!error) 178 error = cp_compat_stat(&stat, statbuf); 179 180out: 181 return error; 182} 183#endif 184 185asmlinkage long compat_sys_newfstat(unsigned int fd, 186 struct compat_stat __user * statbuf) 187{ 188 struct kstat stat; 189 int error = vfs_fstat(fd, &stat); 190 191 if (!error) 192 error = cp_compat_stat(&stat, statbuf); 193 return error; 194} 195 196static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) 197{ 198 199 if (sizeof ubuf->f_blocks == 4) { 200 if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) & 201 0xffffffff00000000ULL) 202 return -EOVERFLOW; 203 /* f_files and f_ffree may be -1; it's okay 204 * to stuff that into 32 bits */ 205 if (kbuf->f_files != 0xffffffffffffffffULL 206 && (kbuf->f_files & 0xffffffff00000000ULL)) 207 return -EOVERFLOW; 208 if (kbuf->f_ffree != 0xffffffffffffffffULL 209 && (kbuf->f_ffree & 0xffffffff00000000ULL)) 210 return -EOVERFLOW; 211 } 212 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || 213 __put_user(kbuf->f_type, &ubuf->f_type) || 214 __put_user(kbuf->f_bsize, &ubuf->f_bsize) || 215 __put_user(kbuf->f_blocks, &ubuf->f_blocks) || 216 __put_user(kbuf->f_bfree, &ubuf->f_bfree) || 217 __put_user(kbuf->f_bavail, &ubuf->f_bavail) || 218 __put_user(kbuf->f_files, &ubuf->f_files) || 219 __put_user(kbuf->f_ffree, &ubuf->f_ffree) || 220 __put_user(kbuf->f_namelen, &ubuf->f_namelen) || 221 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || 222 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || 223 __put_user(kbuf->f_frsize, &ubuf->f_frsize) || 224 __put_user(0, &ubuf->f_spare[0]) || 225 __put_user(0, &ubuf->f_spare[1]) || 226 __put_user(0, &ubuf->f_spare[2]) || 227 __put_user(0, &ubuf->f_spare[3]) || 228 __put_user(0, &ubuf->f_spare[4])) 229 return -EFAULT; 230 return 0; 231} 232 233/* 234 * The following statfs calls are copies of code from fs/open.c and 235 * should be checked against those from time to time 236 */ 237asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs __user *buf) 238{ 239 struct nameidata nd; 240 int error; 241 242 error = user_path_walk(path, &nd); 243 if (!error) { 244 struct kstatfs tmp; 245 error = vfs_statfs(nd.path.dentry, &tmp); 246 if (!error) 247 error = put_compat_statfs(buf, &tmp); 248 path_put(&nd.path); 249 } 250 return error; 251} 252 253asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf) 254{ 255 struct file * file; 256 struct kstatfs tmp; 257 int error; 258 259 error = -EBADF; 260 file = fget(fd); 261 if (!file) 262 goto out; 263 error = vfs_statfs(file->f_path.dentry, &tmp); 264 if (!error) 265 error = put_compat_statfs(buf, &tmp); 266 fput(file); 267out: 268 return error; 269} 270 271static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) 272{ 273 if (sizeof ubuf->f_blocks == 4) { 274 if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) & 275 0xffffffff00000000ULL) 276 return -EOVERFLOW; 277 /* f_files and f_ffree may be -1; it's okay 278 * to stuff that into 32 bits */ 279 if (kbuf->f_files != 0xffffffffffffffffULL 280 && (kbuf->f_files & 0xffffffff00000000ULL)) 281 return -EOVERFLOW; 282 if (kbuf->f_ffree != 0xffffffffffffffffULL 283 && (kbuf->f_ffree & 0xffffffff00000000ULL)) 284 return -EOVERFLOW; 285 } 286 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || 287 __put_user(kbuf->f_type, &ubuf->f_type) || 288 __put_user(kbuf->f_bsize, &ubuf->f_bsize) || 289 __put_user(kbuf->f_blocks, &ubuf->f_blocks) || 290 __put_user(kbuf->f_bfree, &ubuf->f_bfree) || 291 __put_user(kbuf->f_bavail, &ubuf->f_bavail) || 292 __put_user(kbuf->f_files, &ubuf->f_files) || 293 __put_user(kbuf->f_ffree, &ubuf->f_ffree) || 294 __put_user(kbuf->f_namelen, &ubuf->f_namelen) || 295 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || 296 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || 297 __put_user(kbuf->f_frsize, &ubuf->f_frsize)) 298 return -EFAULT; 299 return 0; 300} 301 302asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf) 303{ 304 struct nameidata nd; 305 int error; 306 307 if (sz != sizeof(*buf)) 308 return -EINVAL; 309 310 error = user_path_walk(path, &nd); 311 if (!error) { 312 struct kstatfs tmp; 313 error = vfs_statfs(nd.path.dentry, &tmp); 314 if (!error) 315 error = put_compat_statfs64(buf, &tmp); 316 path_put(&nd.path); 317 } 318 return error; 319} 320 321asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf) 322{ 323 struct file * file; 324 struct kstatfs tmp; 325 int error; 326 327 if (sz != sizeof(*buf)) 328 return -EINVAL; 329 330 error = -EBADF; 331 file = fget(fd); 332 if (!file) 333 goto out; 334 error = vfs_statfs(file->f_path.dentry, &tmp); 335 if (!error) 336 error = put_compat_statfs64(buf, &tmp); 337 fput(file); 338out: 339 return error; 340} 341 342static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 343{ 344 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || 345 __get_user(kfl->l_type, &ufl->l_type) || 346 __get_user(kfl->l_whence, &ufl->l_whence) || 347 __get_user(kfl->l_start, &ufl->l_start) || 348 __get_user(kfl->l_len, &ufl->l_len) || 349 __get_user(kfl->l_pid, &ufl->l_pid)) 350 return -EFAULT; 351 return 0; 352} 353 354static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) 355{ 356 if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) || 357 __put_user(kfl->l_type, &ufl->l_type) || 358 __put_user(kfl->l_whence, &ufl->l_whence) || 359 __put_user(kfl->l_start, &ufl->l_start) || 360 __put_user(kfl->l_len, &ufl->l_len) || 361 __put_user(kfl->l_pid, &ufl->l_pid)) 362 return -EFAULT; 363 return 0; 364} 365 366#ifndef HAVE_ARCH_GET_COMPAT_FLOCK64 367static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) 368{ 369 if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || 370 __get_user(kfl->l_type, &ufl->l_type) || 371 __get_user(kfl->l_whence, &ufl->l_whence) || 372 __get_user(kfl->l_start, &ufl->l_start) || 373 __get_user(kfl->l_len, &ufl->l_len) || 374 __get_user(kfl->l_pid, &ufl->l_pid)) 375 return -EFAULT; 376 return 0; 377} 378#endif 379 380#ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64 381static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) 382{ 383 if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) || 384 __put_user(kfl->l_type, &ufl->l_type) || 385 __put_user(kfl->l_whence, &ufl->l_whence) || 386 __put_user(kfl->l_start, &ufl->l_start) || 387 __put_user(kfl->l_len, &ufl->l_len) || 388 __put_user(kfl->l_pid, &ufl->l_pid)) 389 return -EFAULT; 390 return 0; 391} 392#endif 393 394asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, 395 unsigned long arg) 396{ 397 mm_segment_t old_fs; 398 struct flock f; 399 long ret; 400 401 switch (cmd) { 402 case F_GETLK: 403 case F_SETLK: 404 case F_SETLKW: 405 ret = get_compat_flock(&f, compat_ptr(arg)); 406 if (ret != 0) 407 break; 408 old_fs = get_fs(); 409 set_fs(KERNEL_DS); 410 ret = sys_fcntl(fd, cmd, (unsigned long)&f); 411 set_fs(old_fs); 412 if (cmd == F_GETLK && ret == 0) { 413 /* GETLK was successfule and we need to return the data... 414 * but it needs to fit in the compat structure. 415 * l_start shouldn't be too big, unless the original 416 * start + end is greater than COMPAT_OFF_T_MAX, in which 417 * case the app was asking for trouble, so we return 418 * -EOVERFLOW in that case. 419 * l_len could be too big, in which case we just truncate it, 420 * and only allow the app to see that part of the conflicting 421 * lock that might make sense to it anyway 422 */ 423 424 if (f.l_start > COMPAT_OFF_T_MAX) 425 ret = -EOVERFLOW; 426 if (f.l_len > COMPAT_OFF_T_MAX) 427 f.l_len = COMPAT_OFF_T_MAX; 428 if (ret == 0) 429 ret = put_compat_flock(&f, compat_ptr(arg)); 430 } 431 break; 432 433 case F_GETLK64: 434 case F_SETLK64: 435 case F_SETLKW64: 436 ret = get_compat_flock64(&f, compat_ptr(arg)); 437 if (ret != 0) 438 break; 439 old_fs = get_fs(); 440 set_fs(KERNEL_DS); 441 ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK : 442 ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW), 443 (unsigned long)&f); 444 set_fs(old_fs); 445 if (cmd == F_GETLK64 && ret == 0) { 446 /* need to return lock information - see above for commentary */ 447 if (f.l_start > COMPAT_LOFF_T_MAX) 448 ret = -EOVERFLOW; 449 if (f.l_len > COMPAT_LOFF_T_MAX) 450 f.l_len = COMPAT_LOFF_T_MAX; 451 if (ret == 0) 452 ret = put_compat_flock64(&f, compat_ptr(arg)); 453 } 454 break; 455 456 default: 457 ret = sys_fcntl(fd, cmd, arg); 458 break; 459 } 460 return ret; 461} 462 463asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd, 464 unsigned long arg) 465{ 466 if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64)) 467 return -EINVAL; 468 return compat_sys_fcntl64(fd, cmd, arg); 469} 470 471asmlinkage long 472compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p) 473{ 474 long ret; 475 aio_context_t ctx64; 476 477 mm_segment_t oldfs = get_fs(); 478 if (unlikely(get_user(ctx64, ctx32p))) 479 return -EFAULT; 480 481 set_fs(KERNEL_DS); 482 /* The __user pointer cast is valid because of the set_fs() */ 483 ret = sys_io_setup(nr_reqs, (aio_context_t __user *) &ctx64); 484 set_fs(oldfs); 485 /* truncating is ok because it's a user address */ 486 if (!ret) 487 ret = put_user((u32) ctx64, ctx32p); 488 return ret; 489} 490 491asmlinkage long 492compat_sys_io_getevents(aio_context_t ctx_id, 493 unsigned long min_nr, 494 unsigned long nr, 495 struct io_event __user *events, 496 struct compat_timespec __user *timeout) 497{ 498 long ret; 499 struct timespec t; 500 struct timespec __user *ut = NULL; 501 502 ret = -EFAULT; 503 if (unlikely(!access_ok(VERIFY_WRITE, events, 504 nr * sizeof(struct io_event)))) 505 goto out; 506 if (timeout) { 507 if (get_compat_timespec(&t, timeout)) 508 goto out; 509 510 ut = compat_alloc_user_space(sizeof(*ut)); 511 if (copy_to_user(ut, &t, sizeof(t)) ) 512 goto out; 513 } 514 ret = sys_io_getevents(ctx_id, min_nr, nr, events, ut); 515out: 516 return ret; 517} 518 519static inline long 520copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64) 521{ 522 compat_uptr_t uptr; 523 int i; 524 525 for (i = 0; i < nr; ++i) { 526 if (get_user(uptr, ptr32 + i)) 527 return -EFAULT; 528 if (put_user(compat_ptr(uptr), ptr64 + i)) 529 return -EFAULT; 530 } 531 return 0; 532} 533 534#define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) 535 536asmlinkage long 537compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb) 538{ 539 struct iocb __user * __user *iocb64; 540 long ret; 541 542 if (unlikely(nr < 0)) 543 return -EINVAL; 544 545 if (nr > MAX_AIO_SUBMITS) 546 nr = MAX_AIO_SUBMITS; 547 548 iocb64 = compat_alloc_user_space(nr * sizeof(*iocb64)); 549 ret = copy_iocb(nr, iocb, iocb64); 550 if (!ret) 551 ret = sys_io_submit(ctx_id, nr, iocb64); 552 return ret; 553} 554 555struct compat_ncp_mount_data { 556 compat_int_t version; 557 compat_uint_t ncp_fd; 558 __compat_uid_t mounted_uid; 559 compat_pid_t wdog_pid; 560 unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; 561 compat_uint_t time_out; 562 compat_uint_t retry_count; 563 compat_uint_t flags; 564 __compat_uid_t uid; 565 __compat_gid_t gid; 566 compat_mode_t file_mode; 567 compat_mode_t dir_mode; 568}; 569 570struct compat_ncp_mount_data_v4 { 571 compat_int_t version; 572 compat_ulong_t flags; 573 compat_ulong_t mounted_uid; 574 compat_long_t wdog_pid; 575 compat_uint_t ncp_fd; 576 compat_uint_t time_out; 577 compat_uint_t retry_count; 578 compat_ulong_t uid; 579 compat_ulong_t gid; 580 compat_ulong_t file_mode; 581 compat_ulong_t dir_mode; 582}; 583 584static void *do_ncp_super_data_conv(void *raw_data) 585{ 586 int version = *(unsigned int *)raw_data; 587 588 if (version == 3) { 589 struct compat_ncp_mount_data *c_n = raw_data; 590 struct ncp_mount_data *n = raw_data; 591 592 n->dir_mode = c_n->dir_mode; 593 n->file_mode = c_n->file_mode; 594 n->gid = c_n->gid; 595 n->uid = c_n->uid; 596 memmove (n->mounted_vol, c_n->mounted_vol, (sizeof (c_n->mounted_vol) + 3 * sizeof (unsigned int))); 597 n->wdog_pid = c_n->wdog_pid; 598 n->mounted_uid = c_n->mounted_uid; 599 } else if (version == 4) { 600 struct compat_ncp_mount_data_v4 *c_n = raw_data; 601 struct ncp_mount_data_v4 *n = raw_data; 602 603 n->dir_mode = c_n->dir_mode; 604 n->file_mode = c_n->file_mode; 605 n->gid = c_n->gid; 606 n->uid = c_n->uid; 607 n->retry_count = c_n->retry_count; 608 n->time_out = c_n->time_out; 609 n->ncp_fd = c_n->ncp_fd; 610 n->wdog_pid = c_n->wdog_pid; 611 n->mounted_uid = c_n->mounted_uid; 612 n->flags = c_n->flags; 613 } else if (version != 5) { 614 return NULL; 615 } 616 617 return raw_data; 618} 619 620struct compat_smb_mount_data { 621 compat_int_t version; 622 __compat_uid_t mounted_uid; 623 __compat_uid_t uid; 624 __compat_gid_t gid; 625 compat_mode_t file_mode; 626 compat_mode_t dir_mode; 627}; 628 629static void *do_smb_super_data_conv(void *raw_data) 630{ 631 struct smb_mount_data *s = raw_data; 632 struct compat_smb_mount_data *c_s = raw_data; 633 634 if (c_s->version != SMB_MOUNT_OLDVERSION) 635 goto out; 636 s->dir_mode = c_s->dir_mode; 637 s->file_mode = c_s->file_mode; 638 s->gid = c_s->gid; 639 s->uid = c_s->uid; 640 s->mounted_uid = c_s->mounted_uid; 641 out: 642 return raw_data; 643} 644 645struct compat_nfs_string { 646 compat_uint_t len; 647 compat_uptr_t data; 648}; 649 650static inline void compat_nfs_string(struct nfs_string *dst, 651 struct compat_nfs_string *src) 652{ 653 dst->data = compat_ptr(src->data); 654 dst->len = src->len; 655} 656 657struct compat_nfs4_mount_data_v1 { 658 compat_int_t version; 659 compat_int_t flags; 660 compat_int_t rsize; 661 compat_int_t wsize; 662 compat_int_t timeo; 663 compat_int_t retrans; 664 compat_int_t acregmin; 665 compat_int_t acregmax; 666 compat_int_t acdirmin; 667 compat_int_t acdirmax; 668 struct compat_nfs_string client_addr; 669 struct compat_nfs_string mnt_path; 670 struct compat_nfs_string hostname; 671 compat_uint_t host_addrlen; 672 compat_uptr_t host_addr; 673 compat_int_t proto; 674 compat_int_t auth_flavourlen; 675 compat_uptr_t auth_flavours; 676}; 677 678static int do_nfs4_super_data_conv(void *raw_data) 679{ 680 int version = *(compat_uint_t *) raw_data; 681 682 if (version == 1) { 683 struct compat_nfs4_mount_data_v1 *raw = raw_data; 684 struct nfs4_mount_data *real = raw_data; 685 686 /* copy the fields backwards */ 687 real->auth_flavours = compat_ptr(raw->auth_flavours); 688 real->auth_flavourlen = raw->auth_flavourlen; 689 real->proto = raw->proto; 690 real->host_addr = compat_ptr(raw->host_addr); 691 real->host_addrlen = raw->host_addrlen; 692 compat_nfs_string(&real->hostname, &raw->hostname); 693 compat_nfs_string(&real->mnt_path, &raw->mnt_path); 694 compat_nfs_string(&real->client_addr, &raw->client_addr); 695 real->acdirmax = raw->acdirmax; 696 real->acdirmin = raw->acdirmin; 697 real->acregmax = raw->acregmax; 698 real->acregmin = raw->acregmin; 699 real->retrans = raw->retrans; 700 real->timeo = raw->timeo; 701 real->wsize = raw->wsize; 702 real->rsize = raw->rsize; 703 real->flags = raw->flags; 704 real->version = raw->version; 705 } 706 707 return 0; 708} 709 710#define SMBFS_NAME "smbfs" 711#define NCPFS_NAME "ncpfs" 712#define NFS4_NAME "nfs4" 713 714asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name, 715 char __user * type, unsigned long flags, 716 void __user * data) 717{ 718 unsigned long type_page; 719 unsigned long data_page; 720 unsigned long dev_page; 721 char *dir_page; 722 int retval; 723 724 retval = copy_mount_options (type, &type_page); 725 if (retval < 0) 726 goto out; 727 728 dir_page = getname(dir_name); 729 retval = PTR_ERR(dir_page); 730 if (IS_ERR(dir_page)) 731 goto out1; 732 733 retval = copy_mount_options (dev_name, &dev_page); 734 if (retval < 0) 735 goto out2; 736 737 retval = copy_mount_options (data, &data_page); 738 if (retval < 0) 739 goto out3; 740 741 retval = -EINVAL; 742 743 if (type_page && data_page) { 744 if (!strcmp((char *)type_page, SMBFS_NAME)) { 745 do_smb_super_data_conv((void *)data_page); 746 } else if (!strcmp((char *)type_page, NCPFS_NAME)) { 747 do_ncp_super_data_conv((void *)data_page); 748 } else if (!strcmp((char *)type_page, NFS4_NAME)) { 749 if (do_nfs4_super_data_conv((void *) data_page)) 750 goto out4; 751 } 752 } 753 754 lock_kernel(); 755 retval = do_mount((char*)dev_page, dir_page, (char*)type_page, 756 flags, (void*)data_page); 757 unlock_kernel(); 758 759 out4: 760 free_page(data_page); 761 out3: 762 free_page(dev_page); 763 out2: 764 putname(dir_page); 765 out1: 766 free_page(type_page); 767 out: 768 return retval; 769} 770 771#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) 772 773struct compat_old_linux_dirent { 774 compat_ulong_t d_ino; 775 compat_ulong_t d_offset; 776 unsigned short d_namlen; 777 char d_name[1]; 778}; 779 780struct compat_readdir_callback { 781 struct compat_old_linux_dirent __user *dirent; 782 int result; 783}; 784 785static int compat_fillonedir(void *__buf, const char *name, int namlen, 786 loff_t offset, u64 ino, unsigned int d_type) 787{ 788 struct compat_readdir_callback *buf = __buf; 789 struct compat_old_linux_dirent __user *dirent; 790 compat_ulong_t d_ino; 791 792 if (buf->result) 793 return -EINVAL; 794 d_ino = ino; 795 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) 796 return -EOVERFLOW; 797 buf->result++; 798 dirent = buf->dirent; 799 if (!access_ok(VERIFY_WRITE, dirent, 800 (unsigned long)(dirent->d_name + namlen + 1) - 801 (unsigned long)dirent)) 802 goto efault; 803 if ( __put_user(d_ino, &dirent->d_ino) || 804 __put_user(offset, &dirent->d_offset) || 805 __put_user(namlen, &dirent->d_namlen) || 806 __copy_to_user(dirent->d_name, name, namlen) || 807 __put_user(0, dirent->d_name + namlen)) 808 goto efault; 809 return 0; 810efault: 811 buf->result = -EFAULT; 812 return -EFAULT; 813} 814 815asmlinkage long compat_sys_old_readdir(unsigned int fd, 816 struct compat_old_linux_dirent __user *dirent, unsigned int count) 817{ 818 int error; 819 struct file *file; 820 struct compat_readdir_callback buf; 821 822 error = -EBADF; 823 file = fget(fd); 824 if (!file) 825 goto out; 826 827 buf.result = 0; 828 buf.dirent = dirent; 829 830 error = vfs_readdir(file, compat_fillonedir, &buf); 831 if (error >= 0) 832 error = buf.result; 833 834 fput(file); 835out: 836 return error; 837} 838 839struct compat_linux_dirent { 840 compat_ulong_t d_ino; 841 compat_ulong_t d_off; 842 unsigned short d_reclen; 843 char d_name[1]; 844}; 845 846struct compat_getdents_callback { 847 struct compat_linux_dirent __user *current_dir; 848 struct compat_linux_dirent __user *previous; 849 int count; 850 int error; 851}; 852 853static int compat_filldir(void *__buf, const char *name, int namlen, 854 loff_t offset, u64 ino, unsigned int d_type) 855{ 856 struct compat_linux_dirent __user * dirent; 857 struct compat_getdents_callback *buf = __buf; 858 compat_ulong_t d_ino; 859 int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(compat_long_t)); 860 861 buf->error = -EINVAL; /* only used if we fail.. */ 862 if (reclen > buf->count) 863 return -EINVAL; 864 d_ino = ino; 865 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) 866 return -EOVERFLOW; 867 dirent = buf->previous; 868 if (dirent) { 869 if (__put_user(offset, &dirent->d_off)) 870 goto efault; 871 } 872 dirent = buf->current_dir; 873 if (__put_user(d_ino, &dirent->d_ino)) 874 goto efault; 875 if (__put_user(reclen, &dirent->d_reclen)) 876 goto efault; 877 if (copy_to_user(dirent->d_name, name, namlen)) 878 goto efault; 879 if (__put_user(0, dirent->d_name + namlen)) 880 goto efault; 881 if (__put_user(d_type, (char __user *) dirent + reclen - 1)) 882 goto efault; 883 buf->previous = dirent; 884 dirent = (void __user *)dirent + reclen; 885 buf->current_dir = dirent; 886 buf->count -= reclen; 887 return 0; 888efault: 889 buf->error = -EFAULT; 890 return -EFAULT; 891} 892 893asmlinkage long compat_sys_getdents(unsigned int fd, 894 struct compat_linux_dirent __user *dirent, unsigned int count) 895{ 896 struct file * file; 897 struct compat_linux_dirent __user * lastdirent; 898 struct compat_getdents_callback buf; 899 int error; 900 901 error = -EFAULT; 902 if (!access_ok(VERIFY_WRITE, dirent, count)) 903 goto out; 904 905 error = -EBADF; 906 file = fget(fd); 907 if (!file) 908 goto out; 909 910 buf.current_dir = dirent; 911 buf.previous = NULL; 912 buf.count = count; 913 buf.error = 0; 914 915 error = vfs_readdir(file, compat_filldir, &buf); 916 if (error < 0) 917 goto out_putf; 918 error = buf.error; 919 lastdirent = buf.previous; 920 if (lastdirent) { 921 if (put_user(file->f_pos, &lastdirent->d_off)) 922 error = -EFAULT; 923 else 924 error = count - buf.count; 925 } 926 927out_putf: 928 fput(file); 929out: 930 return error; 931} 932 933#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 934 935struct compat_getdents_callback64 { 936 struct linux_dirent64 __user *current_dir; 937 struct linux_dirent64 __user *previous; 938 int count; 939 int error; 940}; 941 942static int compat_filldir64(void * __buf, const char * name, int namlen, loff_t offset, 943 u64 ino, unsigned int d_type) 944{ 945 struct linux_dirent64 __user *dirent; 946 struct compat_getdents_callback64 *buf = __buf; 947 int jj = NAME_OFFSET(dirent); 948 int reclen = ALIGN(jj + namlen + 1, sizeof(u64)); 949 u64 off; 950 951 buf->error = -EINVAL; /* only used if we fail.. */ 952 if (reclen > buf->count) 953 return -EINVAL; 954 dirent = buf->previous; 955 956 if (dirent) { 957 if (__put_user_unaligned(offset, &dirent->d_off)) 958 goto efault; 959 } 960 dirent = buf->current_dir; 961 if (__put_user_unaligned(ino, &dirent->d_ino)) 962 goto efault; 963 off = 0; 964 if (__put_user_unaligned(off, &dirent->d_off)) 965 goto efault; 966 if (__put_user(reclen, &dirent->d_reclen)) 967 goto efault; 968 if (__put_user(d_type, &dirent->d_type)) 969 goto efault; 970 if (copy_to_user(dirent->d_name, name, namlen)) 971 goto efault; 972 if (__put_user(0, dirent->d_name + namlen)) 973 goto efault; 974 buf->previous = dirent; 975 dirent = (void __user *)dirent + reclen; 976 buf->current_dir = dirent; 977 buf->count -= reclen; 978 return 0; 979efault: 980 buf->error = -EFAULT; 981 return -EFAULT; 982} 983 984asmlinkage long compat_sys_getdents64(unsigned int fd, 985 struct linux_dirent64 __user * dirent, unsigned int count) 986{ 987 struct file * file; 988 struct linux_dirent64 __user * lastdirent; 989 struct compat_getdents_callback64 buf; 990 int error; 991 992 error = -EFAULT; 993 if (!access_ok(VERIFY_WRITE, dirent, count)) 994 goto out; 995 996 error = -EBADF; 997 file = fget(fd); 998 if (!file) 999 goto out; 1000 1001 buf.current_dir = dirent; 1002 buf.previous = NULL; 1003 buf.count = count; 1004 buf.error = 0; 1005 1006 error = vfs_readdir(file, compat_filldir64, &buf); 1007 if (error < 0) 1008 goto out_putf; 1009 error = buf.error; 1010 lastdirent = buf.previous; 1011 if (lastdirent) { 1012 typeof(lastdirent->d_off) d_off = file->f_pos; 1013 error = -EFAULT; 1014 if (__put_user_unaligned(d_off, &lastdirent->d_off)) 1015 goto out_putf; 1016 error = count - buf.count; 1017 } 1018 1019out_putf: 1020 fput(file); 1021out: 1022 return error; 1023} 1024#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */ 1025 1026static ssize_t compat_do_readv_writev(int type, struct file *file, 1027 const struct compat_iovec __user *uvector, 1028 unsigned long nr_segs, loff_t *pos) 1029{ 1030 compat_ssize_t tot_len; 1031 struct iovec iovstack[UIO_FASTIOV]; 1032 struct iovec *iov=iovstack, *vector; 1033 ssize_t ret; 1034 int seg; 1035 io_fn_t fn; 1036 iov_fn_t fnv; 1037 1038 /* 1039 * SuS says "The readv() function *may* fail if the iovcnt argument 1040 * was less than or equal to 0, or greater than {IOV_MAX}. Linux has 1041 * traditionally returned zero for zero segments, so... 1042 */ 1043 ret = 0; 1044 if (nr_segs == 0) 1045 goto out; 1046 1047 /* 1048 * First get the "struct iovec" from user memory and 1049 * verify all the pointers 1050 */ 1051 ret = -EINVAL; 1052 if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0)) 1053 goto out; 1054 if (!file->f_op) 1055 goto out; 1056 if (nr_segs > UIO_FASTIOV) { 1057 ret = -ENOMEM; 1058 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); 1059 if (!iov) 1060 goto out; 1061 } 1062 ret = -EFAULT; 1063 if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) 1064 goto out; 1065 1066 /* 1067 * Single unix specification: 1068 * We should -EINVAL if an element length is not >= 0 and fitting an 1069 * ssize_t. The total length is fitting an ssize_t 1070 * 1071 * Be careful here because iov_len is a size_t not an ssize_t 1072 */ 1073 tot_len = 0; 1074 vector = iov; 1075 ret = -EINVAL; 1076 for (seg = 0 ; seg < nr_segs; seg++) { 1077 compat_ssize_t tmp = tot_len; 1078 compat_ssize_t len; 1079 compat_uptr_t buf; 1080 1081 if (__get_user(len, &uvector->iov_len) || 1082 __get_user(buf, &uvector->iov_base)) { 1083 ret = -EFAULT; 1084 goto out; 1085 } 1086 if (len < 0) /* size_t not fitting an compat_ssize_t .. */ 1087 goto out; 1088 tot_len += len; 1089 if (tot_len < tmp) /* maths overflow on the compat_ssize_t */ 1090 goto out; 1091 vector->iov_base = compat_ptr(buf); 1092 vector->iov_len = (compat_size_t) len; 1093 uvector++; 1094 vector++; 1095 } 1096 if (tot_len == 0) { 1097 ret = 0; 1098 goto out; 1099 } 1100 1101 ret = rw_verify_area(type, file, pos, tot_len); 1102 if (ret < 0) 1103 goto out; 1104 1105 fnv = NULL; 1106 if (type == READ) { 1107 fn = file->f_op->read; 1108 fnv = file->f_op->aio_read; 1109 } else { 1110 fn = (io_fn_t)file->f_op->write; 1111 fnv = file->f_op->aio_write; 1112 } 1113 1114 if (fnv) 1115 ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, 1116 pos, fnv); 1117 else 1118 ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); 1119 1120out: 1121 if (iov != iovstack) 1122 kfree(iov); 1123 if ((ret + (type == READ)) > 0) { 1124 struct dentry *dentry = file->f_path.dentry; 1125 if (type == READ) 1126 fsnotify_access(dentry); 1127 else 1128 fsnotify_modify(dentry); 1129 } 1130 return ret; 1131} 1132 1133asmlinkage ssize_t 1134compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) 1135{ 1136 struct file *file; 1137 ssize_t ret = -EBADF; 1138 1139 file = fget(fd); 1140 if (!file) 1141 return -EBADF; 1142 1143 if (!(file->f_mode & FMODE_READ)) 1144 goto out; 1145 1146 ret = -EINVAL; 1147 if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) 1148 goto out; 1149 1150 ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); 1151 1152out: 1153 fput(file); 1154 return ret; 1155} 1156 1157asmlinkage ssize_t 1158compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) 1159{ 1160 struct file *file; 1161 ssize_t ret = -EBADF; 1162 1163 file = fget(fd); 1164 if (!file) 1165 return -EBADF; 1166 if (!(file->f_mode & FMODE_WRITE)) 1167 goto out; 1168 1169 ret = -EINVAL; 1170 if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) 1171 goto out; 1172 1173 ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); 1174 1175out: 1176 fput(file); 1177 return ret; 1178} 1179 1180asmlinkage long 1181compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32, 1182 unsigned int nr_segs, unsigned int flags) 1183{ 1184 unsigned i; 1185 struct iovec __user *iov; 1186 if (nr_segs > UIO_MAXIOV) 1187 return -EINVAL; 1188 iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec)); 1189 for (i = 0; i < nr_segs; i++) { 1190 struct compat_iovec v; 1191 if (get_user(v.iov_base, &iov32[i].iov_base) || 1192 get_user(v.iov_len, &iov32[i].iov_len) || 1193 put_user(compat_ptr(v.iov_base), &iov[i].iov_base) || 1194 put_user(v.iov_len, &iov[i].iov_len)) 1195 return -EFAULT; 1196 } 1197 return sys_vmsplice(fd, iov, nr_segs, flags); 1198} 1199 1200/* 1201 * Exactly like fs/open.c:sys_open(), except that it doesn't set the 1202 * O_LARGEFILE flag. 1203 */ 1204asmlinkage long 1205compat_sys_open(const char __user *filename, int flags, int mode) 1206{ 1207 return do_sys_open(AT_FDCWD, filename, flags, mode); 1208} 1209 1210/* 1211 * Exactly like fs/open.c:sys_openat(), except that it doesn't set the 1212 * O_LARGEFILE flag. 1213 */ 1214asmlinkage long 1215compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode) 1216{ 1217 return do_sys_open(dfd, filename, flags, mode); 1218} 1219 1220/* 1221 * compat_count() counts the number of arguments/envelopes. It is basically 1222 * a copy of count() from fs/exec.c, except that it works with 32 bit argv 1223 * and envp pointers. 1224 */ 1225static int compat_count(compat_uptr_t __user *argv, int max) 1226{ 1227 int i = 0; 1228 1229 if (argv != NULL) { 1230 for (;;) { 1231 compat_uptr_t p; 1232 1233 if (get_user(p, argv)) 1234 return -EFAULT; 1235 if (!p) 1236 break; 1237 argv++; 1238 if(++i > max) 1239 return -E2BIG; 1240 } 1241 } 1242 return i; 1243} 1244 1245/* 1246 * compat_copy_strings() is basically a copy of copy_strings() from fs/exec.c 1247 * except that it works with 32 bit argv and envp pointers. 1248 */ 1249static int compat_copy_strings(int argc, compat_uptr_t __user *argv, 1250 struct linux_binprm *bprm) 1251{ 1252 struct page *kmapped_page = NULL; 1253 char *kaddr = NULL; 1254 unsigned long kpos = 0; 1255 int ret; 1256 1257 while (argc-- > 0) { 1258 compat_uptr_t str; 1259 int len; 1260 unsigned long pos; 1261 1262 if (get_user(str, argv+argc) || 1263 !(len = strnlen_user(compat_ptr(str), MAX_ARG_STRLEN))) { 1264 ret = -EFAULT; 1265 goto out; 1266 } 1267 1268 if (len > MAX_ARG_STRLEN) { 1269 ret = -E2BIG; 1270 goto out; 1271 } 1272 1273 /* We're going to work our way backwords. */ 1274 pos = bprm->p; 1275 str += len; 1276 bprm->p -= len; 1277 1278 while (len > 0) { 1279 int offset, bytes_to_copy; 1280 1281 offset = pos % PAGE_SIZE; 1282 if (offset == 0) 1283 offset = PAGE_SIZE; 1284 1285 bytes_to_copy = offset; 1286 if (bytes_to_copy > len) 1287 bytes_to_copy = len; 1288 1289 offset -= bytes_to_copy; 1290 pos -= bytes_to_copy; 1291 str -= bytes_to_copy; 1292 len -= bytes_to_copy; 1293 1294 if (!kmapped_page || kpos != (pos & PAGE_MASK)) { 1295 struct page *page; 1296 1297#ifdef CONFIG_STACK_GROWSUP 1298 ret = expand_stack_downwards(bprm->vma, pos); 1299 if (ret < 0) { 1300 /* We've exceed the stack rlimit. */ 1301 ret = -E2BIG; 1302 goto out; 1303 } 1304#endif 1305 ret = get_user_pages(current, bprm->mm, pos, 1306 1, 1, 1, &page, NULL); 1307 if (ret <= 0) { 1308 /* We've exceed the stack rlimit. */ 1309 ret = -E2BIG; 1310 goto out; 1311 } 1312 1313 if (kmapped_page) { 1314 flush_kernel_dcache_page(kmapped_page); 1315 kunmap(kmapped_page); 1316 put_page(kmapped_page); 1317 } 1318 kmapped_page = page; 1319 kaddr = kmap(kmapped_page); 1320 kpos = pos & PAGE_MASK; 1321 flush_cache_page(bprm->vma, kpos, 1322 page_to_pfn(kmapped_page)); 1323 } 1324 if (copy_from_user(kaddr+offset, compat_ptr(str), 1325 bytes_to_copy)) { 1326 ret = -EFAULT; 1327 goto out; 1328 } 1329 } 1330 } 1331 ret = 0; 1332out: 1333 if (kmapped_page) { 1334 flush_kernel_dcache_page(kmapped_page); 1335 kunmap(kmapped_page); 1336 put_page(kmapped_page); 1337 } 1338 return ret; 1339} 1340 1341/* 1342 * compat_do_execve() is mostly a copy of do_execve(), with the exception 1343 * that it processes 32 bit argv and envp pointers. 1344 */ 1345int compat_do_execve(char * filename, 1346 compat_uptr_t __user *argv, 1347 compat_uptr_t __user *envp, 1348 struct pt_regs * regs) 1349{ 1350 struct linux_binprm *bprm; 1351 struct file *file; 1352 int retval; 1353 1354 retval = -ENOMEM; 1355 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); 1356 if (!bprm) 1357 goto out_ret; 1358 1359 file = open_exec(filename); 1360 retval = PTR_ERR(file); 1361 if (IS_ERR(file)) 1362 goto out_kfree; 1363 1364 sched_exec(); 1365 1366 bprm->file = file; 1367 bprm->filename = filename; 1368 bprm->interp = filename; 1369 1370 retval = bprm_mm_init(bprm); 1371 if (retval) 1372 goto out_file; 1373 1374 bprm->argc = compat_count(argv, MAX_ARG_STRINGS); 1375 if ((retval = bprm->argc) < 0) 1376 goto out_mm; 1377 1378 bprm->envc = compat_count(envp, MAX_ARG_STRINGS); 1379 if ((retval = bprm->envc) < 0) 1380 goto out_mm; 1381 1382 retval = security_bprm_alloc(bprm); 1383 if (retval) 1384 goto out; 1385 1386 retval = prepare_binprm(bprm); 1387 if (retval < 0) 1388 goto out; 1389 1390 retval = copy_strings_kernel(1, &bprm->filename, bprm); 1391 if (retval < 0) 1392 goto out; 1393 1394 bprm->exec = bprm->p; 1395 retval = compat_copy_strings(bprm->envc, envp, bprm); 1396 if (retval < 0) 1397 goto out; 1398 1399 retval = compat_copy_strings(bprm->argc, argv, bprm); 1400 if (retval < 0) 1401 goto out; 1402 1403 retval = search_binary_handler(bprm, regs); 1404 if (retval >= 0) { 1405 /* execve success */ 1406 security_bprm_free(bprm); 1407 acct_update_integrals(current); 1408 free_bprm(bprm); 1409 return retval; 1410 } 1411 1412out: 1413 if (bprm->security) 1414 security_bprm_free(bprm); 1415 1416out_mm: 1417 if (bprm->mm) 1418 mmput(bprm->mm); 1419 1420out_file: 1421 if (bprm->file) { 1422 allow_write_access(bprm->file); 1423 fput(bprm->file); 1424 } 1425 1426out_kfree: 1427 free_bprm(bprm); 1428 1429out_ret: 1430 return retval; 1431} 1432 1433#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) 1434 1435/* 1436 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1437 * 64-bit unsigned longs. 1438 */ 1439static 1440int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1441 unsigned long *fdset) 1442{ 1443 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS); 1444 if (ufdset) { 1445 unsigned long odd; 1446 1447 if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t))) 1448 return -EFAULT; 1449 1450 odd = nr & 1UL; 1451 nr &= ~1UL; 1452 while (nr) { 1453 unsigned long h, l; 1454 if (__get_user(l, ufdset) || __get_user(h, ufdset+1)) 1455 return -EFAULT; 1456 ufdset += 2; 1457 *fdset++ = h << 32 | l; 1458 nr -= 2; 1459 } 1460 if (odd && __get_user(*fdset, ufdset)) 1461 return -EFAULT; 1462 } else { 1463 /* Tricky, must clear full unsigned long in the 1464 * kernel fdset at the end, this makes sure that 1465 * actually happens. 1466 */ 1467 memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t)); 1468 } 1469 return 0; 1470} 1471 1472static 1473int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1474 unsigned long *fdset) 1475{ 1476 unsigned long odd; 1477 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS); 1478 1479 if (!ufdset) 1480 return 0; 1481 1482 odd = nr & 1UL; 1483 nr &= ~1UL; 1484 while (nr) { 1485 unsigned long h, l; 1486 l = *fdset++; 1487 h = l >> 32; 1488 if (__put_user(l, ufdset) || __put_user(h, ufdset+1)) 1489 return -EFAULT; 1490 ufdset += 2; 1491 nr -= 2; 1492 } 1493 if (odd && __put_user(*fdset, ufdset)) 1494 return -EFAULT; 1495 return 0; 1496} 1497 1498 1499/* 1500 * This is a virtual copy of sys_select from fs/select.c and probably 1501 * should be compared to it from time to time 1502 */ 1503 1504/* 1505 * We can actually return ERESTARTSYS instead of EINTR, but I'd 1506 * like to be certain this leads to no problems. So I return 1507 * EINTR just for safety. 1508 * 1509 * Update: ERESTARTSYS breaks at least the xview clock binary, so 1510 * I'm trying ERESTARTNOHAND which restart only when you want to. 1511 */ 1512#define MAX_SELECT_SECONDS \ 1513 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) 1514 1515int compat_core_sys_select(int n, compat_ulong_t __user *inp, 1516 compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) 1517{ 1518 fd_set_bits fds; 1519 void *bits; 1520 int size, max_fds, ret = -EINVAL; 1521 struct fdtable *fdt; 1522 long stack_fds[SELECT_STACK_ALLOC/sizeof(long)]; 1523 1524 if (n < 0) 1525 goto out_nofds; 1526 1527 /* max_fds can increase, so grab it once to avoid race */ 1528 rcu_read_lock(); 1529 fdt = files_fdtable(current->files); 1530 max_fds = fdt->max_fds; 1531 rcu_read_unlock(); 1532 if (n > max_fds) 1533 n = max_fds; 1534 1535 /* 1536 * We need 6 bitmaps (in/out/ex for both incoming and outgoing), 1537 * since we used fdset we need to allocate memory in units of 1538 * long-words. 1539 */ 1540 size = FDS_BYTES(n); 1541 bits = stack_fds; 1542 if (size > sizeof(stack_fds) / 6) { 1543 bits = kmalloc(6 * size, GFP_KERNEL); 1544 ret = -ENOMEM; 1545 if (!bits) 1546 goto out_nofds; 1547 } 1548 fds.in = (unsigned long *) bits; 1549 fds.out = (unsigned long *) (bits + size); 1550 fds.ex = (unsigned long *) (bits + 2*size); 1551 fds.res_in = (unsigned long *) (bits + 3*size); 1552 fds.res_out = (unsigned long *) (bits + 4*size); 1553 fds.res_ex = (unsigned long *) (bits + 5*size); 1554 1555 if ((ret = compat_get_fd_set(n, inp, fds.in)) || 1556 (ret = compat_get_fd_set(n, outp, fds.out)) || 1557 (ret = compat_get_fd_set(n, exp, fds.ex))) 1558 goto out; 1559 zero_fd_set(n, fds.res_in); 1560 zero_fd_set(n, fds.res_out); 1561 zero_fd_set(n, fds.res_ex); 1562 1563 ret = do_select(n, &fds, timeout); 1564 1565 if (ret < 0) 1566 goto out; 1567 if (!ret) { 1568 ret = -ERESTARTNOHAND; 1569 if (signal_pending(current)) 1570 goto out; 1571 ret = 0; 1572 } 1573 1574 if (compat_set_fd_set(n, inp, fds.res_in) || 1575 compat_set_fd_set(n, outp, fds.res_out) || 1576 compat_set_fd_set(n, exp, fds.res_ex)) 1577 ret = -EFAULT; 1578out: 1579 if (bits != stack_fds) 1580 kfree(bits); 1581out_nofds: 1582 return ret; 1583} 1584 1585asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, 1586 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1587 struct compat_timeval __user *tvp) 1588{ 1589 s64 timeout = -1; 1590 struct compat_timeval tv; 1591 int ret; 1592 1593 if (tvp) { 1594 if (copy_from_user(&tv, tvp, sizeof(tv))) 1595 return -EFAULT; 1596 1597 if (tv.tv_sec < 0 || tv.tv_usec < 0) 1598 return -EINVAL; 1599 1600 /* Cast to u64 to make GCC stop complaining */ 1601 if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS) 1602 timeout = -1; /* infinite */ 1603 else { 1604 timeout = DIV_ROUND_UP(tv.tv_usec, 1000000/HZ); 1605 timeout += tv.tv_sec * HZ; 1606 } 1607 } 1608 1609 ret = compat_core_sys_select(n, inp, outp, exp, &timeout); 1610 1611 if (tvp) { 1612 struct compat_timeval rtv; 1613 1614 if (current->personality & STICKY_TIMEOUTS) 1615 goto sticky; 1616 rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)); 1617 rtv.tv_sec = timeout; 1618 if (compat_timeval_compare(&rtv, &tv) >= 0) 1619 rtv = tv; 1620 if (copy_to_user(tvp, &rtv, sizeof(rtv))) { 1621sticky: 1622 /* 1623 * If an application puts its timeval in read-only 1624 * memory, we don't want the Linux-specific update to 1625 * the timeval to cause a fault after the select has 1626 * completed successfully. However, because we're not 1627 * updating the timeval, we can't restart the system 1628 * call. 1629 */ 1630 if (ret == -ERESTARTNOHAND) 1631 ret = -EINTR; 1632 } 1633 } 1634 1635 return ret; 1636} 1637 1638#ifdef HAVE_SET_RESTORE_SIGMASK 1639asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, 1640 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1641 struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, 1642 compat_size_t sigsetsize) 1643{ 1644 compat_sigset_t ss32; 1645 sigset_t ksigmask, sigsaved; 1646 s64 timeout = MAX_SCHEDULE_TIMEOUT; 1647 struct compat_timespec ts; 1648 int ret; 1649 1650 if (tsp) { 1651 if (copy_from_user(&ts, tsp, sizeof(ts))) 1652 return -EFAULT; 1653 1654 if (ts.tv_sec < 0 || ts.tv_nsec < 0) 1655 return -EINVAL; 1656 } 1657 1658 if (sigmask) { 1659 if (sigsetsize != sizeof(compat_sigset_t)) 1660 return -EINVAL; 1661 if (copy_from_user(&ss32, sigmask, sizeof(ss32))) 1662 return -EFAULT; 1663 sigset_from_compat(&ksigmask, &ss32); 1664 1665 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); 1666 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1667 } 1668 1669 do { 1670 if (tsp) { 1671 if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) { 1672 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ); 1673 timeout += ts.tv_sec * (unsigned long)HZ; 1674 ts.tv_sec = 0; 1675 ts.tv_nsec = 0; 1676 } else { 1677 ts.tv_sec -= MAX_SELECT_SECONDS; 1678 timeout = MAX_SELECT_SECONDS * HZ; 1679 } 1680 } 1681 1682 ret = compat_core_sys_select(n, inp, outp, exp, &timeout); 1683 1684 } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec)); 1685 1686 if (tsp) { 1687 struct compat_timespec rts; 1688 1689 if (current->personality & STICKY_TIMEOUTS) 1690 goto sticky; 1691 1692 rts.tv_sec = timeout / HZ; 1693 rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ); 1694 if (rts.tv_nsec >= NSEC_PER_SEC) { 1695 rts.tv_sec++; 1696 rts.tv_nsec -= NSEC_PER_SEC; 1697 } 1698 if (compat_timespec_compare(&rts, &ts) >= 0) 1699 rts = ts; 1700 if (copy_to_user(tsp, &rts, sizeof(rts))) { 1701sticky: 1702 /* 1703 * If an application puts its timeval in read-only 1704 * memory, we don't want the Linux-specific update to 1705 * the timeval to cause a fault after the select has 1706 * completed successfully. However, because we're not 1707 * updating the timeval, we can't restart the system 1708 * call. 1709 */ 1710 if (ret == -ERESTARTNOHAND) 1711 ret = -EINTR; 1712 } 1713 } 1714 1715 if (ret == -ERESTARTNOHAND) { 1716 /* 1717 * Don't restore the signal mask yet. Let do_signal() deliver 1718 * the signal on the way back to userspace, before the signal 1719 * mask is restored. 1720 */ 1721 if (sigmask) { 1722 memcpy(&current->saved_sigmask, &sigsaved, 1723 sizeof(sigsaved)); 1724 set_restore_sigmask(); 1725 } 1726 } else if (sigmask) 1727 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1728 1729 return ret; 1730} 1731 1732asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, 1733 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1734 struct compat_timespec __user *tsp, void __user *sig) 1735{ 1736 compat_size_t sigsetsize = 0; 1737 compat_uptr_t up = 0; 1738 1739 if (sig) { 1740 if (!access_ok(VERIFY_READ, sig, 1741 sizeof(compat_uptr_t)+sizeof(compat_size_t)) || 1742 __get_user(up, (compat_uptr_t __user *)sig) || 1743 __get_user(sigsetsize, 1744 (compat_size_t __user *)(sig+sizeof(up)))) 1745 return -EFAULT; 1746 } 1747 return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up), 1748 sigsetsize); 1749} 1750 1751asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, 1752 unsigned int nfds, struct compat_timespec __user *tsp, 1753 const compat_sigset_t __user *sigmask, compat_size_t sigsetsize) 1754{ 1755 compat_sigset_t ss32; 1756 sigset_t ksigmask, sigsaved; 1757 struct compat_timespec ts; 1758 s64 timeout = -1; 1759 int ret; 1760 1761 if (tsp) { 1762 if (copy_from_user(&ts, tsp, sizeof(ts))) 1763 return -EFAULT; 1764 1765 /* We assume that ts.tv_sec is always lower than 1766 the number of seconds that can be expressed in 1767 an s64. Otherwise the compiler bitches at us */ 1768 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ); 1769 timeout += ts.tv_sec * HZ; 1770 } 1771 1772 if (sigmask) { 1773 if (sigsetsize != sizeof(compat_sigset_t)) 1774 return -EINVAL; 1775 if (copy_from_user(&ss32, sigmask, sizeof(ss32))) 1776 return -EFAULT; 1777 sigset_from_compat(&ksigmask, &ss32); 1778 1779 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); 1780 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1781 } 1782 1783 ret = do_sys_poll(ufds, nfds, &timeout); 1784 1785 /* We can restart this syscall, usually */ 1786 if (ret == -EINTR) { 1787 /* 1788 * Don't restore the signal mask yet. Let do_signal() deliver 1789 * the signal on the way back to userspace, before the signal 1790 * mask is restored. 1791 */ 1792 if (sigmask) { 1793 memcpy(&current->saved_sigmask, &sigsaved, 1794 sizeof(sigsaved)); 1795 set_restore_sigmask(); 1796 } 1797 ret = -ERESTARTNOHAND; 1798 } else if (sigmask) 1799 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1800 1801 if (tsp && timeout >= 0) { 1802 struct compat_timespec rts; 1803 1804 if (current->personality & STICKY_TIMEOUTS) 1805 goto sticky; 1806 /* Yes, we know it's actually an s64, but it's also positive. */ 1807 rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1808 1000; 1809 rts.tv_sec = timeout; 1810 if (compat_timespec_compare(&rts, &ts) >= 0) 1811 rts = ts; 1812 if (copy_to_user(tsp, &rts, sizeof(rts))) { 1813sticky: 1814 /* 1815 * If an application puts its timeval in read-only 1816 * memory, we don't want the Linux-specific update to 1817 * the timeval to cause a fault after the select has 1818 * completed successfully. However, because we're not 1819 * updating the timeval, we can't restart the system 1820 * call. 1821 */ 1822 if (ret == -ERESTARTNOHAND && timeout >= 0) 1823 ret = -EINTR; 1824 } 1825 } 1826 1827 return ret; 1828} 1829#endif /* HAVE_SET_RESTORE_SIGMASK */ 1830 1831#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) 1832/* Stuff for NFS server syscalls... */ 1833struct compat_nfsctl_svc { 1834 u16 svc32_port; 1835 s32 svc32_nthreads; 1836}; 1837 1838struct compat_nfsctl_client { 1839 s8 cl32_ident[NFSCLNT_IDMAX+1]; 1840 s32 cl32_naddr; 1841 struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; 1842 s32 cl32_fhkeytype; 1843 s32 cl32_fhkeylen; 1844 u8 cl32_fhkey[NFSCLNT_KEYMAX]; 1845}; 1846 1847struct compat_nfsctl_export { 1848 char ex32_client[NFSCLNT_IDMAX+1]; 1849 char ex32_path[NFS_MAXPATHLEN+1]; 1850 compat_dev_t ex32_dev; 1851 compat_ino_t ex32_ino; 1852 compat_int_t ex32_flags; 1853 __compat_uid_t ex32_anon_uid; 1854 __compat_gid_t ex32_anon_gid; 1855}; 1856 1857struct compat_nfsctl_fdparm { 1858 struct sockaddr gd32_addr; 1859 s8 gd32_path[NFS_MAXPATHLEN+1]; 1860 compat_int_t gd32_version; 1861}; 1862 1863struct compat_nfsctl_fsparm { 1864 struct sockaddr gd32_addr; 1865 s8 gd32_path[NFS_MAXPATHLEN+1]; 1866 compat_int_t gd32_maxlen; 1867}; 1868 1869struct compat_nfsctl_arg { 1870 compat_int_t ca32_version; /* safeguard */ 1871 union { 1872 struct compat_nfsctl_svc u32_svc; 1873 struct compat_nfsctl_client u32_client; 1874 struct compat_nfsctl_export u32_export; 1875 struct compat_nfsctl_fdparm u32_getfd; 1876 struct compat_nfsctl_fsparm u32_getfs; 1877 } u; 1878#define ca32_svc u.u32_svc 1879#define ca32_client u.u32_client 1880#define ca32_export u.u32_export 1881#define ca32_getfd u.u32_getfd 1882#define ca32_getfs u.u32_getfs 1883}; 1884 1885union compat_nfsctl_res { 1886 __u8 cr32_getfh[NFS_FHSIZE]; 1887 struct knfsd_fh cr32_getfs; 1888}; 1889 1890static int compat_nfs_svc_trans(struct nfsctl_arg *karg, 1891 struct compat_nfsctl_arg __user *arg) 1892{ 1893 if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) || 1894 get_user(karg->ca_version, &arg->ca32_version) || 1895 __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) || 1896 __get_user(karg->ca_svc.svc_nthreads, 1897 &arg->ca32_svc.svc32_nthreads)) 1898 return -EFAULT; 1899 return 0; 1900} 1901 1902static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, 1903 struct compat_nfsctl_arg __user *arg) 1904{ 1905 if (!access_ok(VERIFY_READ, &arg->ca32_client, 1906 sizeof(arg->ca32_client)) || 1907 get_user(karg->ca_version, &arg->ca32_version) || 1908 __copy_from_user(&karg->ca_client.cl_ident[0], 1909 &arg->ca32_client.cl32_ident[0], 1910 NFSCLNT_IDMAX) || 1911 __get_user(karg->ca_client.cl_naddr, 1912 &arg->ca32_client.cl32_naddr) || 1913 __copy_from_user(&karg->ca_client.cl_addrlist[0], 1914 &arg->ca32_client.cl32_addrlist[0], 1915 (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) || 1916 __get_user(karg->ca_client.cl_fhkeytype, 1917 &arg->ca32_client.cl32_fhkeytype) || 1918 __get_user(karg->ca_client.cl_fhkeylen, 1919 &arg->ca32_client.cl32_fhkeylen) || 1920 __copy_from_user(&karg->ca_client.cl_fhkey[0], 1921 &arg->ca32_client.cl32_fhkey[0], 1922 NFSCLNT_KEYMAX)) 1923 return -EFAULT; 1924 1925 return 0; 1926} 1927 1928static int compat_nfs_exp_trans(struct nfsctl_arg *karg, 1929 struct compat_nfsctl_arg __user *arg) 1930{ 1931 if (!access_ok(VERIFY_READ, &arg->ca32_export, 1932 sizeof(arg->ca32_export)) || 1933 get_user(karg->ca_version, &arg->ca32_version) || 1934 __copy_from_user(&karg->ca_export.ex_client[0], 1935 &arg->ca32_export.ex32_client[0], 1936 NFSCLNT_IDMAX) || 1937 __copy_from_user(&karg->ca_export.ex_path[0], 1938 &arg->ca32_export.ex32_path[0], 1939 NFS_MAXPATHLEN) || 1940 __get_user(karg->ca_export.ex_dev, 1941 &arg->ca32_export.ex32_dev) || 1942 __get_user(karg->ca_export.ex_ino, 1943 &arg->ca32_export.ex32_ino) || 1944 __get_user(karg->ca_export.ex_flags, 1945 &arg->ca32_export.ex32_flags) || 1946 __get_user(karg->ca_export.ex_anon_uid, 1947 &arg->ca32_export.ex32_anon_uid) || 1948 __get_user(karg->ca_export.ex_anon_gid, 1949 &arg->ca32_export.ex32_anon_gid)) 1950 return -EFAULT; 1951 SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid); 1952 SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid); 1953 1954 return 0; 1955} 1956 1957static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, 1958 struct compat_nfsctl_arg __user *arg) 1959{ 1960 if (!access_ok(VERIFY_READ, &arg->ca32_getfd, 1961 sizeof(arg->ca32_getfd)) || 1962 get_user(karg->ca_version, &arg->ca32_version) || 1963 __copy_from_user(&karg->ca_getfd.gd_addr, 1964 &arg->ca32_getfd.gd32_addr, 1965 (sizeof(struct sockaddr))) || 1966 __copy_from_user(&karg->ca_getfd.gd_path, 1967 &arg->ca32_getfd.gd32_path, 1968 (NFS_MAXPATHLEN+1)) || 1969 __get_user(karg->ca_getfd.gd_version, 1970 &arg->ca32_getfd.gd32_version)) 1971 return -EFAULT; 1972 1973 return 0; 1974} 1975 1976static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, 1977 struct compat_nfsctl_arg __user *arg) 1978{ 1979 if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) || 1980 get_user(karg->ca_version, &arg->ca32_version) || 1981 __copy_from_user(&karg->ca_getfs.gd_addr, 1982 &arg->ca32_getfs.gd32_addr, 1983 (sizeof(struct sockaddr))) || 1984 __copy_from_user(&karg->ca_getfs.gd_path, 1985 &arg->ca32_getfs.gd32_path, 1986 (NFS_MAXPATHLEN+1)) || 1987 __get_user(karg->ca_getfs.gd_maxlen, 1988 &arg->ca32_getfs.gd32_maxlen)) 1989 return -EFAULT; 1990 1991 return 0; 1992} 1993 1994/* This really doesn't need translations, we are only passing 1995 * back a union which contains opaque nfs file handle data. 1996 */ 1997static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, 1998 union compat_nfsctl_res __user *res) 1999{ 2000 int err; 2001 2002 err = copy_to_user(res, kres, sizeof(*res)); 2003 2004 return (err) ? -EFAULT : 0; 2005} 2006 2007asmlinkage long compat_sys_nfsservctl(int cmd, 2008 struct compat_nfsctl_arg __user *arg, 2009 union compat_nfsctl_res __user *res) 2010{ 2011 struct nfsctl_arg *karg; 2012 union nfsctl_res *kres; 2013 mm_segment_t oldfs; 2014 int err; 2015 2016 karg = kmalloc(sizeof(*karg), GFP_USER); 2017 kres = kmalloc(sizeof(*kres), GFP_USER); 2018 if(!karg || !kres) { 2019 err = -ENOMEM; 2020 goto done; 2021 } 2022 2023 switch(cmd) { 2024 case NFSCTL_SVC: 2025 err = compat_nfs_svc_trans(karg, arg); 2026 break; 2027 2028 case NFSCTL_ADDCLIENT: 2029 err = compat_nfs_clnt_trans(karg, arg); 2030 break; 2031 2032 case NFSCTL_DELCLIENT: 2033 err = compat_nfs_clnt_trans(karg, arg); 2034 break; 2035 2036 case NFSCTL_EXPORT: 2037 case NFSCTL_UNEXPORT: 2038 err = compat_nfs_exp_trans(karg, arg); 2039 break; 2040 2041 case NFSCTL_GETFD: 2042 err = compat_nfs_getfd_trans(karg, arg); 2043 break; 2044 2045 case NFSCTL_GETFS: 2046 err = compat_nfs_getfs_trans(karg, arg); 2047 break; 2048 2049 default: 2050 err = -EINVAL; 2051 break; 2052 } 2053 2054 if (err) 2055 goto done; 2056 2057 oldfs = get_fs(); 2058 set_fs(KERNEL_DS); 2059 /* The __user pointer casts are valid because of the set_fs() */ 2060 err = sys_nfsservctl(cmd, (void __user *) karg, (void __user *) kres); 2061 set_fs(oldfs); 2062 2063 if (err) 2064 goto done; 2065 2066 if((cmd == NFSCTL_GETFD) || 2067 (cmd == NFSCTL_GETFS)) 2068 err = compat_nfs_getfh_res_trans(kres, res); 2069 2070done: 2071 kfree(karg); 2072 kfree(kres); 2073 return err; 2074} 2075#else /* !NFSD */ 2076long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2) 2077{ 2078 return sys_ni_syscall(); 2079} 2080#endif 2081 2082#ifdef CONFIG_EPOLL 2083 2084#ifdef HAVE_SET_RESTORE_SIGMASK 2085asmlinkage long compat_sys_epoll_pwait(int epfd, 2086 struct compat_epoll_event __user *events, 2087 int maxevents, int timeout, 2088 const compat_sigset_t __user *sigmask, 2089 compat_size_t sigsetsize) 2090{ 2091 long err; 2092 compat_sigset_t csigmask; 2093 sigset_t ksigmask, sigsaved; 2094 2095 /* 2096 * If the caller wants a certain signal mask to be set during the wait, 2097 * we apply it here. 2098 */ 2099 if (sigmask) { 2100 if (sigsetsize != sizeof(compat_sigset_t)) 2101 return -EINVAL; 2102 if (copy_from_user(&csigmask, sigmask, sizeof(csigmask))) 2103 return -EFAULT; 2104 sigset_from_compat(&ksigmask, &csigmask); 2105 sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); 2106 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 2107 } 2108 2109 err = sys_epoll_wait(epfd, events, maxevents, timeout); 2110 2111 /* 2112 * If we changed the signal mask, we need to restore the original one. 2113 * In case we've got a signal while waiting, we do not restore the 2114 * signal mask yet, and we allow do_signal() to deliver the signal on 2115 * the way back to userspace, before the signal mask is restored. 2116 */ 2117 if (sigmask) { 2118 if (err == -EINTR) { 2119 memcpy(&current->saved_sigmask, &sigsaved, 2120 sizeof(sigsaved)); 2121 set_restore_sigmask(); 2122 } else 2123 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 2124 } 2125 2126 return err; 2127} 2128#endif /* HAVE_SET_RESTORE_SIGMASK */ 2129 2130#endif /* CONFIG_EPOLL */ 2131 2132#ifdef CONFIG_SIGNALFD 2133 2134asmlinkage long compat_sys_signalfd(int ufd, 2135 const compat_sigset_t __user *sigmask, 2136 compat_size_t sigsetsize) 2137{ 2138 compat_sigset_t ss32; 2139 sigset_t tmp; 2140 sigset_t __user *ksigmask; 2141 2142 if (sigsetsize != sizeof(compat_sigset_t)) 2143 return -EINVAL; 2144 if (copy_from_user(&ss32, sigmask, sizeof(ss32))) 2145 return -EFAULT; 2146 sigset_from_compat(&tmp, &ss32); 2147 ksigmask = compat_alloc_user_space(sizeof(sigset_t)); 2148 if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t))) 2149 return -EFAULT; 2150 2151 return sys_signalfd(ufd, ksigmask, sizeof(sigset_t)); 2152} 2153 2154#endif /* CONFIG_SIGNALFD */ 2155 2156#ifdef CONFIG_TIMERFD 2157 2158asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, 2159 const struct compat_itimerspec __user *utmr, 2160 struct compat_itimerspec __user *otmr) 2161{ 2162 int error; 2163 struct itimerspec t; 2164 struct itimerspec __user *ut; 2165 2166 if (get_compat_itimerspec(&t, utmr)) 2167 return -EFAULT; 2168 ut = compat_alloc_user_space(2 * sizeof(struct itimerspec)); 2169 if (copy_to_user(&ut[0], &t, sizeof(t))) 2170 return -EFAULT; 2171 error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]); 2172 if (!error && otmr) 2173 error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) || 2174 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; 2175 2176 return error; 2177} 2178 2179asmlinkage long compat_sys_timerfd_gettime(int ufd, 2180 struct compat_itimerspec __user *otmr) 2181{ 2182 int error; 2183 struct itimerspec t; 2184 struct itimerspec __user *ut; 2185 2186 ut = compat_alloc_user_space(sizeof(struct itimerspec)); 2187 error = sys_timerfd_gettime(ufd, ut); 2188 if (!error) 2189 error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) || 2190 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; 2191 2192 return error; 2193} 2194 2195#endif /* CONFIG_TIMERFD */