at v3.0 2061 lines 52 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#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) 1310 1311static int poll_select_copy_remaining(struct timespec *end_time, void __user *p, 1312 int timeval, int ret) 1313{ 1314 struct timespec ts; 1315 1316 if (!p) 1317 return ret; 1318 1319 if (current->personality & STICKY_TIMEOUTS) 1320 goto sticky; 1321 1322 /* No update for zero timeout */ 1323 if (!end_time->tv_sec && !end_time->tv_nsec) 1324 return ret; 1325 1326 ktime_get_ts(&ts); 1327 ts = timespec_sub(*end_time, ts); 1328 if (ts.tv_sec < 0) 1329 ts.tv_sec = ts.tv_nsec = 0; 1330 1331 if (timeval) { 1332 struct compat_timeval rtv; 1333 1334 rtv.tv_sec = ts.tv_sec; 1335 rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC; 1336 1337 if (!copy_to_user(p, &rtv, sizeof(rtv))) 1338 return ret; 1339 } else { 1340 struct compat_timespec rts; 1341 1342 rts.tv_sec = ts.tv_sec; 1343 rts.tv_nsec = ts.tv_nsec; 1344 1345 if (!copy_to_user(p, &rts, sizeof(rts))) 1346 return ret; 1347 } 1348 /* 1349 * If an application puts its timeval in read-only memory, we 1350 * don't want the Linux-specific update to the timeval to 1351 * cause a fault after the select has completed 1352 * successfully. However, because we're not updating the 1353 * timeval, we can't restart the system call. 1354 */ 1355 1356sticky: 1357 if (ret == -ERESTARTNOHAND) 1358 ret = -EINTR; 1359 return ret; 1360} 1361 1362/* 1363 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1364 * 64-bit unsigned longs. 1365 */ 1366static 1367int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1368 unsigned long *fdset) 1369{ 1370 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS); 1371 if (ufdset) { 1372 unsigned long odd; 1373 1374 if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t))) 1375 return -EFAULT; 1376 1377 odd = nr & 1UL; 1378 nr &= ~1UL; 1379 while (nr) { 1380 unsigned long h, l; 1381 if (__get_user(l, ufdset) || __get_user(h, ufdset+1)) 1382 return -EFAULT; 1383 ufdset += 2; 1384 *fdset++ = h << 32 | l; 1385 nr -= 2; 1386 } 1387 if (odd && __get_user(*fdset, ufdset)) 1388 return -EFAULT; 1389 } else { 1390 /* Tricky, must clear full unsigned long in the 1391 * kernel fdset at the end, this makes sure that 1392 * actually happens. 1393 */ 1394 memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t)); 1395 } 1396 return 0; 1397} 1398 1399static 1400int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, 1401 unsigned long *fdset) 1402{ 1403 unsigned long odd; 1404 nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS); 1405 1406 if (!ufdset) 1407 return 0; 1408 1409 odd = nr & 1UL; 1410 nr &= ~1UL; 1411 while (nr) { 1412 unsigned long h, l; 1413 l = *fdset++; 1414 h = l >> 32; 1415 if (__put_user(l, ufdset) || __put_user(h, ufdset+1)) 1416 return -EFAULT; 1417 ufdset += 2; 1418 nr -= 2; 1419 } 1420 if (odd && __put_user(*fdset, ufdset)) 1421 return -EFAULT; 1422 return 0; 1423} 1424 1425 1426/* 1427 * This is a virtual copy of sys_select from fs/select.c and probably 1428 * should be compared to it from time to time 1429 */ 1430 1431/* 1432 * We can actually return ERESTARTSYS instead of EINTR, but I'd 1433 * like to be certain this leads to no problems. So I return 1434 * EINTR just for safety. 1435 * 1436 * Update: ERESTARTSYS breaks at least the xview clock binary, so 1437 * I'm trying ERESTARTNOHAND which restart only when you want to. 1438 */ 1439int compat_core_sys_select(int n, compat_ulong_t __user *inp, 1440 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1441 struct timespec *end_time) 1442{ 1443 fd_set_bits fds; 1444 void *bits; 1445 int size, max_fds, ret = -EINVAL; 1446 struct fdtable *fdt; 1447 long stack_fds[SELECT_STACK_ALLOC/sizeof(long)]; 1448 1449 if (n < 0) 1450 goto out_nofds; 1451 1452 /* max_fds can increase, so grab it once to avoid race */ 1453 rcu_read_lock(); 1454 fdt = files_fdtable(current->files); 1455 max_fds = fdt->max_fds; 1456 rcu_read_unlock(); 1457 if (n > max_fds) 1458 n = max_fds; 1459 1460 /* 1461 * We need 6 bitmaps (in/out/ex for both incoming and outgoing), 1462 * since we used fdset we need to allocate memory in units of 1463 * long-words. 1464 */ 1465 size = FDS_BYTES(n); 1466 bits = stack_fds; 1467 if (size > sizeof(stack_fds) / 6) { 1468 bits = kmalloc(6 * size, GFP_KERNEL); 1469 ret = -ENOMEM; 1470 if (!bits) 1471 goto out_nofds; 1472 } 1473 fds.in = (unsigned long *) bits; 1474 fds.out = (unsigned long *) (bits + size); 1475 fds.ex = (unsigned long *) (bits + 2*size); 1476 fds.res_in = (unsigned long *) (bits + 3*size); 1477 fds.res_out = (unsigned long *) (bits + 4*size); 1478 fds.res_ex = (unsigned long *) (bits + 5*size); 1479 1480 if ((ret = compat_get_fd_set(n, inp, fds.in)) || 1481 (ret = compat_get_fd_set(n, outp, fds.out)) || 1482 (ret = compat_get_fd_set(n, exp, fds.ex))) 1483 goto out; 1484 zero_fd_set(n, fds.res_in); 1485 zero_fd_set(n, fds.res_out); 1486 zero_fd_set(n, fds.res_ex); 1487 1488 ret = do_select(n, &fds, end_time); 1489 1490 if (ret < 0) 1491 goto out; 1492 if (!ret) { 1493 ret = -ERESTARTNOHAND; 1494 if (signal_pending(current)) 1495 goto out; 1496 ret = 0; 1497 } 1498 1499 if (compat_set_fd_set(n, inp, fds.res_in) || 1500 compat_set_fd_set(n, outp, fds.res_out) || 1501 compat_set_fd_set(n, exp, fds.res_ex)) 1502 ret = -EFAULT; 1503out: 1504 if (bits != stack_fds) 1505 kfree(bits); 1506out_nofds: 1507 return ret; 1508} 1509 1510asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, 1511 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1512 struct compat_timeval __user *tvp) 1513{ 1514 struct timespec end_time, *to = NULL; 1515 struct compat_timeval tv; 1516 int ret; 1517 1518 if (tvp) { 1519 if (copy_from_user(&tv, tvp, sizeof(tv))) 1520 return -EFAULT; 1521 1522 to = &end_time; 1523 if (poll_select_set_timeout(to, 1524 tv.tv_sec + (tv.tv_usec / USEC_PER_SEC), 1525 (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC)) 1526 return -EINVAL; 1527 } 1528 1529 ret = compat_core_sys_select(n, inp, outp, exp, to); 1530 ret = poll_select_copy_remaining(&end_time, tvp, 1, ret); 1531 1532 return ret; 1533} 1534 1535struct compat_sel_arg_struct { 1536 compat_ulong_t n; 1537 compat_uptr_t inp; 1538 compat_uptr_t outp; 1539 compat_uptr_t exp; 1540 compat_uptr_t tvp; 1541}; 1542 1543asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg) 1544{ 1545 struct compat_sel_arg_struct a; 1546 1547 if (copy_from_user(&a, arg, sizeof(a))) 1548 return -EFAULT; 1549 return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp), 1550 compat_ptr(a.exp), compat_ptr(a.tvp)); 1551} 1552 1553#ifdef HAVE_SET_RESTORE_SIGMASK 1554static long do_compat_pselect(int n, compat_ulong_t __user *inp, 1555 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1556 struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, 1557 compat_size_t sigsetsize) 1558{ 1559 compat_sigset_t ss32; 1560 sigset_t ksigmask, sigsaved; 1561 struct compat_timespec ts; 1562 struct timespec end_time, *to = NULL; 1563 int ret; 1564 1565 if (tsp) { 1566 if (copy_from_user(&ts, tsp, sizeof(ts))) 1567 return -EFAULT; 1568 1569 to = &end_time; 1570 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) 1571 return -EINVAL; 1572 } 1573 1574 if (sigmask) { 1575 if (sigsetsize != sizeof(compat_sigset_t)) 1576 return -EINVAL; 1577 if (copy_from_user(&ss32, sigmask, sizeof(ss32))) 1578 return -EFAULT; 1579 sigset_from_compat(&ksigmask, &ss32); 1580 1581 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); 1582 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1583 } 1584 1585 ret = compat_core_sys_select(n, inp, outp, exp, to); 1586 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret); 1587 1588 if (ret == -ERESTARTNOHAND) { 1589 /* 1590 * Don't restore the signal mask yet. Let do_signal() deliver 1591 * the signal on the way back to userspace, before the signal 1592 * mask is restored. 1593 */ 1594 if (sigmask) { 1595 memcpy(&current->saved_sigmask, &sigsaved, 1596 sizeof(sigsaved)); 1597 set_restore_sigmask(); 1598 } 1599 } else if (sigmask) 1600 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1601 1602 return ret; 1603} 1604 1605asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp, 1606 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1607 struct compat_timespec __user *tsp, void __user *sig) 1608{ 1609 compat_size_t sigsetsize = 0; 1610 compat_uptr_t up = 0; 1611 1612 if (sig) { 1613 if (!access_ok(VERIFY_READ, sig, 1614 sizeof(compat_uptr_t)+sizeof(compat_size_t)) || 1615 __get_user(up, (compat_uptr_t __user *)sig) || 1616 __get_user(sigsetsize, 1617 (compat_size_t __user *)(sig+sizeof(up)))) 1618 return -EFAULT; 1619 } 1620 return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up), 1621 sigsetsize); 1622} 1623 1624asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, 1625 unsigned int nfds, struct compat_timespec __user *tsp, 1626 const compat_sigset_t __user *sigmask, compat_size_t sigsetsize) 1627{ 1628 compat_sigset_t ss32; 1629 sigset_t ksigmask, sigsaved; 1630 struct compat_timespec ts; 1631 struct timespec end_time, *to = NULL; 1632 int ret; 1633 1634 if (tsp) { 1635 if (copy_from_user(&ts, tsp, sizeof(ts))) 1636 return -EFAULT; 1637 1638 to = &end_time; 1639 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) 1640 return -EINVAL; 1641 } 1642 1643 if (sigmask) { 1644 if (sigsetsize != sizeof(compat_sigset_t)) 1645 return -EINVAL; 1646 if (copy_from_user(&ss32, sigmask, sizeof(ss32))) 1647 return -EFAULT; 1648 sigset_from_compat(&ksigmask, &ss32); 1649 1650 sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); 1651 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1652 } 1653 1654 ret = do_sys_poll(ufds, nfds, to); 1655 1656 /* We can restart this syscall, usually */ 1657 if (ret == -EINTR) { 1658 /* 1659 * Don't restore the signal mask yet. Let do_signal() deliver 1660 * the signal on the way back to userspace, before the signal 1661 * mask is restored. 1662 */ 1663 if (sigmask) { 1664 memcpy(&current->saved_sigmask, &sigsaved, 1665 sizeof(sigsaved)); 1666 set_restore_sigmask(); 1667 } 1668 ret = -ERESTARTNOHAND; 1669 } else if (sigmask) 1670 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1671 1672 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret); 1673 1674 return ret; 1675} 1676#endif /* HAVE_SET_RESTORE_SIGMASK */ 1677 1678#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED) 1679/* Stuff for NFS server syscalls... */ 1680struct compat_nfsctl_svc { 1681 u16 svc32_port; 1682 s32 svc32_nthreads; 1683}; 1684 1685struct compat_nfsctl_client { 1686 s8 cl32_ident[NFSCLNT_IDMAX+1]; 1687 s32 cl32_naddr; 1688 struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; 1689 s32 cl32_fhkeytype; 1690 s32 cl32_fhkeylen; 1691 u8 cl32_fhkey[NFSCLNT_KEYMAX]; 1692}; 1693 1694struct compat_nfsctl_export { 1695 char ex32_client[NFSCLNT_IDMAX+1]; 1696 char ex32_path[NFS_MAXPATHLEN+1]; 1697 compat_dev_t ex32_dev; 1698 compat_ino_t ex32_ino; 1699 compat_int_t ex32_flags; 1700 __compat_uid_t ex32_anon_uid; 1701 __compat_gid_t ex32_anon_gid; 1702}; 1703 1704struct compat_nfsctl_fdparm { 1705 struct sockaddr gd32_addr; 1706 s8 gd32_path[NFS_MAXPATHLEN+1]; 1707 compat_int_t gd32_version; 1708}; 1709 1710struct compat_nfsctl_fsparm { 1711 struct sockaddr gd32_addr; 1712 s8 gd32_path[NFS_MAXPATHLEN+1]; 1713 compat_int_t gd32_maxlen; 1714}; 1715 1716struct compat_nfsctl_arg { 1717 compat_int_t ca32_version; /* safeguard */ 1718 union { 1719 struct compat_nfsctl_svc u32_svc; 1720 struct compat_nfsctl_client u32_client; 1721 struct compat_nfsctl_export u32_export; 1722 struct compat_nfsctl_fdparm u32_getfd; 1723 struct compat_nfsctl_fsparm u32_getfs; 1724 } u; 1725#define ca32_svc u.u32_svc 1726#define ca32_client u.u32_client 1727#define ca32_export u.u32_export 1728#define ca32_getfd u.u32_getfd 1729#define ca32_getfs u.u32_getfs 1730}; 1731 1732union compat_nfsctl_res { 1733 __u8 cr32_getfh[NFS_FHSIZE]; 1734 struct knfsd_fh cr32_getfs; 1735}; 1736 1737static int compat_nfs_svc_trans(struct nfsctl_arg *karg, 1738 struct compat_nfsctl_arg __user *arg) 1739{ 1740 if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) || 1741 get_user(karg->ca_version, &arg->ca32_version) || 1742 __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) || 1743 __get_user(karg->ca_svc.svc_nthreads, 1744 &arg->ca32_svc.svc32_nthreads)) 1745 return -EFAULT; 1746 return 0; 1747} 1748 1749static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, 1750 struct compat_nfsctl_arg __user *arg) 1751{ 1752 if (!access_ok(VERIFY_READ, &arg->ca32_client, 1753 sizeof(arg->ca32_client)) || 1754 get_user(karg->ca_version, &arg->ca32_version) || 1755 __copy_from_user(&karg->ca_client.cl_ident[0], 1756 &arg->ca32_client.cl32_ident[0], 1757 NFSCLNT_IDMAX) || 1758 __get_user(karg->ca_client.cl_naddr, 1759 &arg->ca32_client.cl32_naddr) || 1760 __copy_from_user(&karg->ca_client.cl_addrlist[0], 1761 &arg->ca32_client.cl32_addrlist[0], 1762 (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) || 1763 __get_user(karg->ca_client.cl_fhkeytype, 1764 &arg->ca32_client.cl32_fhkeytype) || 1765 __get_user(karg->ca_client.cl_fhkeylen, 1766 &arg->ca32_client.cl32_fhkeylen) || 1767 __copy_from_user(&karg->ca_client.cl_fhkey[0], 1768 &arg->ca32_client.cl32_fhkey[0], 1769 NFSCLNT_KEYMAX)) 1770 return -EFAULT; 1771 1772 return 0; 1773} 1774 1775static int compat_nfs_exp_trans(struct nfsctl_arg *karg, 1776 struct compat_nfsctl_arg __user *arg) 1777{ 1778 if (!access_ok(VERIFY_READ, &arg->ca32_export, 1779 sizeof(arg->ca32_export)) || 1780 get_user(karg->ca_version, &arg->ca32_version) || 1781 __copy_from_user(&karg->ca_export.ex_client[0], 1782 &arg->ca32_export.ex32_client[0], 1783 NFSCLNT_IDMAX) || 1784 __copy_from_user(&karg->ca_export.ex_path[0], 1785 &arg->ca32_export.ex32_path[0], 1786 NFS_MAXPATHLEN) || 1787 __get_user(karg->ca_export.ex_dev, 1788 &arg->ca32_export.ex32_dev) || 1789 __get_user(karg->ca_export.ex_ino, 1790 &arg->ca32_export.ex32_ino) || 1791 __get_user(karg->ca_export.ex_flags, 1792 &arg->ca32_export.ex32_flags) || 1793 __get_user(karg->ca_export.ex_anon_uid, 1794 &arg->ca32_export.ex32_anon_uid) || 1795 __get_user(karg->ca_export.ex_anon_gid, 1796 &arg->ca32_export.ex32_anon_gid)) 1797 return -EFAULT; 1798 SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid); 1799 SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid); 1800 1801 return 0; 1802} 1803 1804static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, 1805 struct compat_nfsctl_arg __user *arg) 1806{ 1807 if (!access_ok(VERIFY_READ, &arg->ca32_getfd, 1808 sizeof(arg->ca32_getfd)) || 1809 get_user(karg->ca_version, &arg->ca32_version) || 1810 __copy_from_user(&karg->ca_getfd.gd_addr, 1811 &arg->ca32_getfd.gd32_addr, 1812 (sizeof(struct sockaddr))) || 1813 __copy_from_user(&karg->ca_getfd.gd_path, 1814 &arg->ca32_getfd.gd32_path, 1815 (NFS_MAXPATHLEN+1)) || 1816 __get_user(karg->ca_getfd.gd_version, 1817 &arg->ca32_getfd.gd32_version)) 1818 return -EFAULT; 1819 1820 return 0; 1821} 1822 1823static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, 1824 struct compat_nfsctl_arg __user *arg) 1825{ 1826 if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) || 1827 get_user(karg->ca_version, &arg->ca32_version) || 1828 __copy_from_user(&karg->ca_getfs.gd_addr, 1829 &arg->ca32_getfs.gd32_addr, 1830 (sizeof(struct sockaddr))) || 1831 __copy_from_user(&karg->ca_getfs.gd_path, 1832 &arg->ca32_getfs.gd32_path, 1833 (NFS_MAXPATHLEN+1)) || 1834 __get_user(karg->ca_getfs.gd_maxlen, 1835 &arg->ca32_getfs.gd32_maxlen)) 1836 return -EFAULT; 1837 1838 return 0; 1839} 1840 1841/* This really doesn't need translations, we are only passing 1842 * back a union which contains opaque nfs file handle data. 1843 */ 1844static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, 1845 union compat_nfsctl_res __user *res) 1846{ 1847 int err; 1848 1849 err = copy_to_user(res, kres, sizeof(*res)); 1850 1851 return (err) ? -EFAULT : 0; 1852} 1853 1854asmlinkage long compat_sys_nfsservctl(int cmd, 1855 struct compat_nfsctl_arg __user *arg, 1856 union compat_nfsctl_res __user *res) 1857{ 1858 struct nfsctl_arg *karg; 1859 union nfsctl_res *kres; 1860 mm_segment_t oldfs; 1861 int err; 1862 1863 karg = kmalloc(sizeof(*karg), GFP_USER); 1864 kres = kmalloc(sizeof(*kres), GFP_USER); 1865 if(!karg || !kres) { 1866 err = -ENOMEM; 1867 goto done; 1868 } 1869 1870 switch(cmd) { 1871 case NFSCTL_SVC: 1872 err = compat_nfs_svc_trans(karg, arg); 1873 break; 1874 1875 case NFSCTL_ADDCLIENT: 1876 err = compat_nfs_clnt_trans(karg, arg); 1877 break; 1878 1879 case NFSCTL_DELCLIENT: 1880 err = compat_nfs_clnt_trans(karg, arg); 1881 break; 1882 1883 case NFSCTL_EXPORT: 1884 case NFSCTL_UNEXPORT: 1885 err = compat_nfs_exp_trans(karg, arg); 1886 break; 1887 1888 case NFSCTL_GETFD: 1889 err = compat_nfs_getfd_trans(karg, arg); 1890 break; 1891 1892 case NFSCTL_GETFS: 1893 err = compat_nfs_getfs_trans(karg, arg); 1894 break; 1895 1896 default: 1897 err = -EINVAL; 1898 break; 1899 } 1900 1901 if (err) 1902 goto done; 1903 1904 oldfs = get_fs(); 1905 set_fs(KERNEL_DS); 1906 /* The __user pointer casts are valid because of the set_fs() */ 1907 err = sys_nfsservctl(cmd, (void __user *) karg, (void __user *) kres); 1908 set_fs(oldfs); 1909 1910 if (err) 1911 goto done; 1912 1913 if((cmd == NFSCTL_GETFD) || 1914 (cmd == NFSCTL_GETFS)) 1915 err = compat_nfs_getfh_res_trans(kres, res); 1916 1917done: 1918 kfree(karg); 1919 kfree(kres); 1920 return err; 1921} 1922#else /* !NFSD */ 1923long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2) 1924{ 1925 return sys_ni_syscall(); 1926} 1927#endif 1928 1929#ifdef CONFIG_EPOLL 1930 1931#ifdef HAVE_SET_RESTORE_SIGMASK 1932asmlinkage long compat_sys_epoll_pwait(int epfd, 1933 struct compat_epoll_event __user *events, 1934 int maxevents, int timeout, 1935 const compat_sigset_t __user *sigmask, 1936 compat_size_t sigsetsize) 1937{ 1938 long err; 1939 compat_sigset_t csigmask; 1940 sigset_t ksigmask, sigsaved; 1941 1942 /* 1943 * If the caller wants a certain signal mask to be set during the wait, 1944 * we apply it here. 1945 */ 1946 if (sigmask) { 1947 if (sigsetsize != sizeof(compat_sigset_t)) 1948 return -EINVAL; 1949 if (copy_from_user(&csigmask, sigmask, sizeof(csigmask))) 1950 return -EFAULT; 1951 sigset_from_compat(&ksigmask, &csigmask); 1952 sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); 1953 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1954 } 1955 1956 err = sys_epoll_wait(epfd, events, maxevents, timeout); 1957 1958 /* 1959 * If we changed the signal mask, we need to restore the original one. 1960 * In case we've got a signal while waiting, we do not restore the 1961 * signal mask yet, and we allow do_signal() to deliver the signal on 1962 * the way back to userspace, before the signal mask is restored. 1963 */ 1964 if (sigmask) { 1965 if (err == -EINTR) { 1966 memcpy(&current->saved_sigmask, &sigsaved, 1967 sizeof(sigsaved)); 1968 set_restore_sigmask(); 1969 } else 1970 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1971 } 1972 1973 return err; 1974} 1975#endif /* HAVE_SET_RESTORE_SIGMASK */ 1976 1977#endif /* CONFIG_EPOLL */ 1978 1979#ifdef CONFIG_SIGNALFD 1980 1981asmlinkage long compat_sys_signalfd4(int ufd, 1982 const compat_sigset_t __user *sigmask, 1983 compat_size_t sigsetsize, int flags) 1984{ 1985 compat_sigset_t ss32; 1986 sigset_t tmp; 1987 sigset_t __user *ksigmask; 1988 1989 if (sigsetsize != sizeof(compat_sigset_t)) 1990 return -EINVAL; 1991 if (copy_from_user(&ss32, sigmask, sizeof(ss32))) 1992 return -EFAULT; 1993 sigset_from_compat(&tmp, &ss32); 1994 ksigmask = compat_alloc_user_space(sizeof(sigset_t)); 1995 if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t))) 1996 return -EFAULT; 1997 1998 return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags); 1999} 2000 2001asmlinkage long compat_sys_signalfd(int ufd, 2002 const compat_sigset_t __user *sigmask, 2003 compat_size_t sigsetsize) 2004{ 2005 return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0); 2006} 2007#endif /* CONFIG_SIGNALFD */ 2008 2009#ifdef CONFIG_TIMERFD 2010 2011asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, 2012 const struct compat_itimerspec __user *utmr, 2013 struct compat_itimerspec __user *otmr) 2014{ 2015 int error; 2016 struct itimerspec t; 2017 struct itimerspec __user *ut; 2018 2019 if (get_compat_itimerspec(&t, utmr)) 2020 return -EFAULT; 2021 ut = compat_alloc_user_space(2 * sizeof(struct itimerspec)); 2022 if (copy_to_user(&ut[0], &t, sizeof(t))) 2023 return -EFAULT; 2024 error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]); 2025 if (!error && otmr) 2026 error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) || 2027 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; 2028 2029 return error; 2030} 2031 2032asmlinkage long compat_sys_timerfd_gettime(int ufd, 2033 struct compat_itimerspec __user *otmr) 2034{ 2035 int error; 2036 struct itimerspec t; 2037 struct itimerspec __user *ut; 2038 2039 ut = compat_alloc_user_space(sizeof(struct itimerspec)); 2040 error = sys_timerfd_gettime(ufd, ut); 2041 if (!error) 2042 error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) || 2043 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; 2044 2045 return error; 2046} 2047 2048#endif /* CONFIG_TIMERFD */ 2049 2050#ifdef CONFIG_FHANDLE 2051/* 2052 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it 2053 * doesn't set the O_LARGEFILE flag. 2054 */ 2055asmlinkage long 2056compat_sys_open_by_handle_at(int mountdirfd, 2057 struct file_handle __user *handle, int flags) 2058{ 2059 return do_handle_open(mountdirfd, handle, flags); 2060} 2061#endif