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