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