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