1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1994-1995 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/capsicum.h> 35 #include <sys/conf.h> 36 #include <sys/dirent.h> 37 #include <sys/fcntl.h> 38 #include <sys/file.h> 39 #include <sys/filedesc.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/mman.h> 43 #include <sys/mount.h> 44 #include <sys/mutex.h> 45 #include <sys/namei.h> 46 #include <sys/selinfo.h> 47 #include <sys/pipe.h> 48 #include <sys/proc.h> 49 #include <sys/stat.h> 50 #include <sys/sx.h> 51 #include <sys/syscallsubr.h> 52 #include <sys/sysproto.h> 53 #include <sys/tty.h> 54 #include <sys/unistd.h> 55 #include <sys/vnode.h> 56 57 #ifdef COMPAT_LINUX32 58 #include <compat/freebsd32/freebsd32_misc.h> 59 #include <machine/../linux32/linux.h> 60 #include <machine/../linux32/linux32_proto.h> 61 #else 62 #include <machine/../linux/linux.h> 63 #include <machine/../linux/linux_proto.h> 64 #endif 65 #include <compat/linux/linux_misc.h> 66 #include <compat/linux/linux_util.h> 67 #include <compat/linux/linux_file.h> 68 69 static int linux_common_open(struct thread *, int, const char *, int, int, 70 enum uio_seg); 71 static int linux_do_accessat(struct thread *t, int, const char *, int, int); 72 static int linux_getdents_error(struct thread *, int, int); 73 74 static struct bsd_to_linux_bitmap seal_bitmap[] = { 75 BITMAP_1t1_LINUX(F_SEAL_SEAL), 76 BITMAP_1t1_LINUX(F_SEAL_SHRINK), 77 BITMAP_1t1_LINUX(F_SEAL_GROW), 78 BITMAP_1t1_LINUX(F_SEAL_WRITE), 79 }; 80 81 #define MFD_HUGETLB_ENTRY(_size) \ 82 { \ 83 .bsd_value = MFD_HUGE_##_size, \ 84 .linux_value = LINUX_HUGETLB_FLAG_ENCODE_##_size \ 85 } 86 static struct bsd_to_linux_bitmap mfd_bitmap[] = { 87 BITMAP_1t1_LINUX(MFD_CLOEXEC), 88 BITMAP_1t1_LINUX(MFD_ALLOW_SEALING), 89 BITMAP_1t1_LINUX(MFD_HUGETLB), 90 MFD_HUGETLB_ENTRY(64KB), 91 MFD_HUGETLB_ENTRY(512KB), 92 MFD_HUGETLB_ENTRY(1MB), 93 MFD_HUGETLB_ENTRY(2MB), 94 MFD_HUGETLB_ENTRY(8MB), 95 MFD_HUGETLB_ENTRY(16MB), 96 MFD_HUGETLB_ENTRY(32MB), 97 MFD_HUGETLB_ENTRY(256MB), 98 MFD_HUGETLB_ENTRY(512MB), 99 MFD_HUGETLB_ENTRY(1GB), 100 MFD_HUGETLB_ENTRY(2GB), 101 MFD_HUGETLB_ENTRY(16GB), 102 }; 103 #undef MFD_HUGETLB_ENTRY 104 105 #ifdef LINUX_LEGACY_SYSCALLS 106 int 107 linux_creat(struct thread *td, struct linux_creat_args *args) 108 { 109 char *path; 110 int error; 111 112 if (!LUSECONVPATH(td)) { 113 return (kern_openat(td, AT_FDCWD, args->path, UIO_USERSPACE, 114 O_WRONLY | O_CREAT | O_TRUNC, args->mode)); 115 } 116 LCONVPATHEXIST(args->path, &path); 117 error = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE, 118 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 119 LFREEPATH(path); 120 return (error); 121 } 122 #endif 123 124 static int 125 linux_common_openflags(int l_flags) 126 { 127 int bsd_flags; 128 129 bsd_flags = 0; 130 switch (l_flags & LINUX_O_ACCMODE) { 131 case LINUX_O_WRONLY: 132 bsd_flags |= O_WRONLY; 133 break; 134 case LINUX_O_RDWR: 135 bsd_flags |= O_RDWR; 136 break; 137 default: 138 bsd_flags |= O_RDONLY; 139 } 140 if (l_flags & LINUX_O_NDELAY) 141 bsd_flags |= O_NONBLOCK; 142 if (l_flags & LINUX_O_APPEND) 143 bsd_flags |= O_APPEND; 144 if (l_flags & LINUX_O_SYNC) 145 bsd_flags |= O_FSYNC; 146 if (l_flags & LINUX_O_CLOEXEC) 147 bsd_flags |= O_CLOEXEC; 148 if (l_flags & LINUX_O_NONBLOCK) 149 bsd_flags |= O_NONBLOCK; 150 if (l_flags & LINUX_O_ASYNC) 151 bsd_flags |= O_ASYNC; 152 if (l_flags & LINUX_O_CREAT) 153 bsd_flags |= O_CREAT; 154 if (l_flags & LINUX_O_TRUNC) 155 bsd_flags |= O_TRUNC; 156 if (l_flags & LINUX_O_EXCL) 157 bsd_flags |= O_EXCL; 158 if (l_flags & LINUX_O_NOCTTY) 159 bsd_flags |= O_NOCTTY; 160 if (l_flags & LINUX_O_DIRECT) 161 bsd_flags |= O_DIRECT; 162 if (l_flags & LINUX_O_NOFOLLOW) 163 bsd_flags |= O_NOFOLLOW; 164 if (l_flags & LINUX_O_DIRECTORY) 165 bsd_flags |= O_DIRECTORY; 166 if (l_flags & LINUX_O_PATH) 167 bsd_flags |= O_PATH; 168 /* XXX LINUX_O_NOATIME: unable to be easily implemented. */ 169 return (bsd_flags); 170 } 171 172 static int 173 linux_common_open(struct thread *td, int dirfd, const char *path, int l_flags, 174 int mode, enum uio_seg seg) 175 { 176 struct proc *p = td->td_proc; 177 struct file *fp; 178 int fd; 179 int bsd_flags, error; 180 181 bsd_flags = linux_common_openflags(l_flags); 182 error = kern_openat(td, dirfd, path, seg, bsd_flags, mode); 183 if (error != 0) { 184 if (error == EMLINK) 185 error = ELOOP; 186 goto done; 187 } 188 if (p->p_flag & P_CONTROLT) 189 goto done; 190 if (bsd_flags & O_NOCTTY) 191 goto done; 192 193 /* 194 * XXX In between kern_openat() and fget(), another process 195 * having the same filedesc could use that fd without 196 * checking below. 197 */ 198 fd = td->td_retval[0]; 199 if (fget(td, fd, &cap_ioctl_rights, &fp) == 0) { 200 if (fp->f_type != DTYPE_VNODE) { 201 fdrop(fp, td); 202 goto done; 203 } 204 sx_slock(&proctree_lock); 205 PROC_LOCK(p); 206 if (SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 207 PROC_UNLOCK(p); 208 sx_sunlock(&proctree_lock); 209 /* XXXPJD: Verify if TIOCSCTTY is allowed. */ 210 (void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, 211 td->td_ucred, td); 212 } else { 213 PROC_UNLOCK(p); 214 sx_sunlock(&proctree_lock); 215 } 216 fdrop(fp, td); 217 } 218 219 done: 220 return (error); 221 } 222 223 int 224 linux_openat(struct thread *td, struct linux_openat_args *args) 225 { 226 char *path; 227 int dfd, error; 228 229 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 230 if (!LUSECONVPATH(td)) { 231 return (linux_common_open(td, dfd, args->filename, args->flags, 232 args->mode, UIO_USERSPACE)); 233 } 234 if (args->flags & LINUX_O_CREAT) 235 LCONVPATH_AT(args->filename, &path, 1, dfd); 236 else 237 LCONVPATH_AT(args->filename, &path, 0, dfd); 238 239 error = linux_common_open(td, dfd, path, args->flags, args->mode, 240 UIO_SYSSPACE); 241 LFREEPATH(path); 242 return (error); 243 } 244 245 #ifdef LINUX_LEGACY_SYSCALLS 246 int 247 linux_open(struct thread *td, struct linux_open_args *args) 248 { 249 char *path; 250 int error; 251 252 if (!LUSECONVPATH(td)) { 253 return (linux_common_open(td, AT_FDCWD, args->path, args->flags, 254 args->mode, UIO_USERSPACE)); 255 } 256 if (args->flags & LINUX_O_CREAT) 257 LCONVPATHCREAT(args->path, &path); 258 else 259 LCONVPATHEXIST(args->path, &path); 260 261 error = linux_common_open(td, AT_FDCWD, path, args->flags, args->mode, 262 UIO_SYSSPACE); 263 LFREEPATH(path); 264 return (error); 265 } 266 #endif 267 268 int 269 linux_name_to_handle_at(struct thread *td, 270 struct linux_name_to_handle_at_args *args) 271 { 272 static const l_int valid_flags = (LINUX_AT_SYMLINK_FOLLOW | 273 LINUX_AT_EMPTY_PATH); 274 static const l_uint fh_size = sizeof(fhandle_t); 275 276 fhandle_t fh; 277 l_uint fh_bytes; 278 l_int mount_id; 279 int error, fd, bsd_flags; 280 281 if (args->flags & ~valid_flags) 282 return (EINVAL); 283 284 fd = args->dirfd; 285 if (fd == LINUX_AT_FDCWD) 286 fd = AT_FDCWD; 287 288 bsd_flags = 0; 289 if (!(args->flags & LINUX_AT_SYMLINK_FOLLOW)) 290 bsd_flags |= AT_SYMLINK_NOFOLLOW; 291 if ((args->flags & LINUX_AT_EMPTY_PATH) != 0) 292 bsd_flags |= AT_EMPTY_PATH; 293 294 if (!LUSECONVPATH(td)) { 295 error = kern_getfhat(td, bsd_flags, fd, args->name, 296 UIO_USERSPACE, &fh, UIO_SYSSPACE); 297 } else { 298 char *path; 299 300 LCONVPATH_AT(args->name, &path, 0, fd); 301 error = kern_getfhat(td, bsd_flags, fd, path, UIO_SYSSPACE, 302 &fh, UIO_SYSSPACE); 303 LFREEPATH(path); 304 } 305 if (error != 0) 306 return (error); 307 308 /* Emit mount_id -- required before EOVERFLOW case. */ 309 mount_id = (fh.fh_fsid.val[0] ^ fh.fh_fsid.val[1]); 310 error = copyout(&mount_id, args->mnt_id, sizeof(mount_id)); 311 if (error != 0) 312 return (error); 313 314 /* Check if there is room for handle. */ 315 error = copyin(&args->handle->handle_bytes, &fh_bytes, 316 sizeof(fh_bytes)); 317 if (error != 0) 318 return (error); 319 320 if (fh_bytes < fh_size) { 321 error = copyout(&fh_size, &args->handle->handle_bytes, 322 sizeof(fh_size)); 323 if (error == 0) 324 error = EOVERFLOW; 325 return (error); 326 } 327 328 /* Emit handle. */ 329 mount_id = 0; 330 /* 331 * We don't use handle_type for anything yet, but initialize a known 332 * value. 333 */ 334 error = copyout(&mount_id, &args->handle->handle_type, 335 sizeof(mount_id)); 336 if (error != 0) 337 return (error); 338 339 error = copyout(&fh, &args->handle->f_handle, 340 sizeof(fh)); 341 return (error); 342 } 343 344 int 345 linux_open_by_handle_at(struct thread *td, 346 struct linux_open_by_handle_at_args *args) 347 { 348 l_uint fh_bytes; 349 int bsd_flags, error; 350 351 error = copyin(&args->handle->handle_bytes, &fh_bytes, 352 sizeof(fh_bytes)); 353 if (error != 0) 354 return (error); 355 356 if (fh_bytes < sizeof(fhandle_t)) 357 return (EINVAL); 358 359 bsd_flags = linux_common_openflags(args->flags); 360 return (kern_fhopen(td, (void *)&args->handle->f_handle, bsd_flags)); 361 } 362 363 int 364 linux_lseek(struct thread *td, struct linux_lseek_args *args) 365 { 366 367 return (kern_lseek(td, args->fdes, args->off, args->whence)); 368 } 369 370 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 371 int 372 linux_llseek(struct thread *td, struct linux_llseek_args *args) 373 { 374 int error; 375 off_t off; 376 377 off = (args->olow) | (((off_t) args->ohigh) << 32); 378 379 error = kern_lseek(td, args->fd, off, args->whence); 380 if (error != 0) 381 return (error); 382 383 error = copyout(td->td_retval, args->res, sizeof(off_t)); 384 if (error != 0) 385 return (error); 386 387 td->td_retval[0] = 0; 388 return (0); 389 } 390 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 391 392 /* 393 * Note that linux_getdents(2) and linux_getdents64(2) have the same 394 * arguments. They only differ in the definition of struct dirent they 395 * operate on. 396 * Note that linux_readdir(2) is a special case of linux_getdents(2) 397 * where count is always equals 1, meaning that the buffer is one 398 * dirent-structure in size and that the code can't handle more anyway. 399 * Note that linux_readdir(2) can't be implemented by means of linux_getdents(2) 400 * as in case when the *dent buffer size is equal to 1 linux_getdents(2) will 401 * trash user stack. 402 */ 403 404 static int 405 linux_getdents_error(struct thread *td, int fd, int err) 406 { 407 struct vnode *vp; 408 struct file *fp; 409 int error; 410 411 /* Linux return ENOTDIR in case when fd is not a directory. */ 412 error = getvnode(td, fd, &cap_read_rights, &fp); 413 if (error != 0) 414 return (error); 415 vp = fp->f_vnode; 416 if (vp->v_type != VDIR) { 417 fdrop(fp, td); 418 return (ENOTDIR); 419 } 420 fdrop(fp, td); 421 return (err); 422 } 423 424 struct l_dirent { 425 l_ulong d_ino; 426 l_off_t d_off; 427 l_ushort d_reclen; 428 char d_name[LINUX_NAME_MAX + 1]; 429 }; 430 431 struct l_dirent64 { 432 uint64_t d_ino; 433 int64_t d_off; 434 l_ushort d_reclen; 435 u_char d_type; 436 char d_name[LINUX_NAME_MAX + 1]; 437 }; 438 439 /* 440 * Linux uses the last byte in the dirent buffer to store d_type, 441 * at least glibc-2.7 requires it. That is why l_dirent is padded with 2 bytes. 442 */ 443 #define LINUX_RECLEN(namlen) \ 444 roundup(offsetof(struct l_dirent, d_name) + (namlen) + 2, sizeof(l_ulong)) 445 446 #define LINUX_RECLEN64(namlen) \ 447 roundup(offsetof(struct l_dirent64, d_name) + (namlen) + 1, \ 448 sizeof(uint64_t)) 449 450 #ifdef LINUX_LEGACY_SYSCALLS 451 int 452 linux_getdents(struct thread *td, struct linux_getdents_args *args) 453 { 454 struct dirent *bdp; 455 caddr_t inp, buf; /* BSD-format */ 456 int len, reclen; /* BSD-format */ 457 caddr_t outp; /* Linux-format */ 458 int resid, linuxreclen; /* Linux-format */ 459 caddr_t lbuf; /* Linux-format */ 460 off_t base; 461 struct l_dirent *linux_dirent; 462 int buflen, error; 463 size_t retval; 464 465 buflen = min(args->count, MAXBSIZE); 466 buf = malloc(buflen, M_TEMP, M_WAITOK); 467 468 error = kern_getdirentries(td, args->fd, buf, buflen, 469 &base, NULL, UIO_SYSSPACE); 470 if (error != 0) { 471 error = linux_getdents_error(td, args->fd, error); 472 goto out1; 473 } 474 475 lbuf = malloc(LINUX_RECLEN(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO); 476 477 len = td->td_retval[0]; 478 inp = buf; 479 outp = (caddr_t)args->dent; 480 resid = args->count; 481 retval = 0; 482 483 while (len > 0) { 484 bdp = (struct dirent *) inp; 485 reclen = bdp->d_reclen; 486 linuxreclen = LINUX_RECLEN(bdp->d_namlen); 487 /* 488 * No more space in the user supplied dirent buffer. 489 * Return EINVAL. 490 */ 491 if (resid < linuxreclen) { 492 error = EINVAL; 493 goto out; 494 } 495 496 linux_dirent = (struct l_dirent*)lbuf; 497 linux_dirent->d_ino = bdp->d_fileno; 498 linux_dirent->d_off = bdp->d_off; 499 linux_dirent->d_reclen = linuxreclen; 500 /* 501 * Copy d_type to last byte of l_dirent buffer 502 */ 503 lbuf[linuxreclen - 1] = bdp->d_type; 504 strlcpy(linux_dirent->d_name, bdp->d_name, 505 linuxreclen - offsetof(struct l_dirent, d_name)-1); 506 error = copyout(linux_dirent, outp, linuxreclen); 507 if (error != 0) 508 goto out; 509 510 inp += reclen; 511 base += reclen; 512 len -= reclen; 513 514 retval += linuxreclen; 515 outp += linuxreclen; 516 resid -= linuxreclen; 517 } 518 td->td_retval[0] = retval; 519 520 out: 521 free(lbuf, M_TEMP); 522 out1: 523 free(buf, M_TEMP); 524 return (error); 525 } 526 #endif 527 528 int 529 linux_getdents64(struct thread *td, struct linux_getdents64_args *args) 530 { 531 struct dirent *bdp; 532 caddr_t inp, buf; /* BSD-format */ 533 int len, reclen; /* BSD-format */ 534 caddr_t outp; /* Linux-format */ 535 int resid, linuxreclen; /* Linux-format */ 536 caddr_t lbuf; /* Linux-format */ 537 off_t base; 538 struct l_dirent64 *linux_dirent64; 539 int buflen, error; 540 size_t retval; 541 542 buflen = min(args->count, MAXBSIZE); 543 buf = malloc(buflen, M_TEMP, M_WAITOK); 544 545 error = kern_getdirentries(td, args->fd, buf, buflen, 546 &base, NULL, UIO_SYSSPACE); 547 if (error != 0) { 548 error = linux_getdents_error(td, args->fd, error); 549 goto out1; 550 } 551 552 lbuf = malloc(LINUX_RECLEN64(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO); 553 554 len = td->td_retval[0]; 555 inp = buf; 556 outp = (caddr_t)args->dirent; 557 resid = args->count; 558 retval = 0; 559 560 while (len > 0) { 561 bdp = (struct dirent *) inp; 562 reclen = bdp->d_reclen; 563 linuxreclen = LINUX_RECLEN64(bdp->d_namlen); 564 /* 565 * No more space in the user supplied dirent buffer. 566 * Return EINVAL. 567 */ 568 if (resid < linuxreclen) { 569 error = EINVAL; 570 goto out; 571 } 572 573 linux_dirent64 = (struct l_dirent64*)lbuf; 574 linux_dirent64->d_ino = bdp->d_fileno; 575 linux_dirent64->d_off = bdp->d_off; 576 linux_dirent64->d_reclen = linuxreclen; 577 linux_dirent64->d_type = bdp->d_type; 578 strlcpy(linux_dirent64->d_name, bdp->d_name, 579 linuxreclen - offsetof(struct l_dirent64, d_name)); 580 error = copyout(linux_dirent64, outp, linuxreclen); 581 if (error != 0) 582 goto out; 583 584 inp += reclen; 585 base += reclen; 586 len -= reclen; 587 588 retval += linuxreclen; 589 outp += linuxreclen; 590 resid -= linuxreclen; 591 } 592 td->td_retval[0] = retval; 593 594 out: 595 free(lbuf, M_TEMP); 596 out1: 597 free(buf, M_TEMP); 598 return (error); 599 } 600 601 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 602 int 603 linux_readdir(struct thread *td, struct linux_readdir_args *args) 604 { 605 struct dirent *bdp; 606 caddr_t buf; /* BSD-format */ 607 int linuxreclen; /* Linux-format */ 608 caddr_t lbuf; /* Linux-format */ 609 off_t base; 610 struct l_dirent *linux_dirent; 611 int buflen, error; 612 613 buflen = LINUX_RECLEN(LINUX_NAME_MAX); 614 buf = malloc(buflen, M_TEMP, M_WAITOK); 615 616 error = kern_getdirentries(td, args->fd, buf, buflen, 617 &base, NULL, UIO_SYSSPACE); 618 if (error != 0) { 619 error = linux_getdents_error(td, args->fd, error); 620 goto out; 621 } 622 if (td->td_retval[0] == 0) 623 goto out; 624 625 lbuf = malloc(LINUX_RECLEN(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO); 626 627 bdp = (struct dirent *) buf; 628 linuxreclen = LINUX_RECLEN(bdp->d_namlen); 629 630 linux_dirent = (struct l_dirent*)lbuf; 631 linux_dirent->d_ino = bdp->d_fileno; 632 linux_dirent->d_off = bdp->d_off; 633 linux_dirent->d_reclen = bdp->d_namlen; 634 strlcpy(linux_dirent->d_name, bdp->d_name, 635 linuxreclen - offsetof(struct l_dirent, d_name)); 636 error = copyout(linux_dirent, args->dent, linuxreclen); 637 if (error == 0) 638 td->td_retval[0] = linuxreclen; 639 640 free(lbuf, M_TEMP); 641 out: 642 free(buf, M_TEMP); 643 return (error); 644 } 645 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 646 647 /* 648 * These exist mainly for hooks for doing /compat/linux translation. 649 */ 650 651 #ifdef LINUX_LEGACY_SYSCALLS 652 int 653 linux_access(struct thread *td, struct linux_access_args *args) 654 { 655 char *path; 656 int error; 657 658 /* Linux convention. */ 659 if (args->amode & ~(F_OK | X_OK | W_OK | R_OK)) 660 return (EINVAL); 661 662 if (!LUSECONVPATH(td)) { 663 error = kern_accessat(td, AT_FDCWD, args->path, UIO_USERSPACE, 0, 664 args->amode); 665 } else { 666 LCONVPATHEXIST(args->path, &path); 667 error = kern_accessat(td, AT_FDCWD, path, UIO_SYSSPACE, 0, 668 args->amode); 669 LFREEPATH(path); 670 } 671 672 return (error); 673 } 674 #endif 675 676 static int 677 linux_do_accessat(struct thread *td, int ldfd, const char *filename, 678 int amode, int flags) 679 { 680 char *path; 681 int error, dfd; 682 683 /* Linux convention. */ 684 if (amode & ~(F_OK | X_OK | W_OK | R_OK)) 685 return (EINVAL); 686 687 dfd = (ldfd == LINUX_AT_FDCWD) ? AT_FDCWD : ldfd; 688 if (!LUSECONVPATH(td)) { 689 error = kern_accessat(td, dfd, filename, UIO_USERSPACE, flags, amode); 690 } else { 691 LCONVPATHEXIST_AT(filename, &path, dfd); 692 error = kern_accessat(td, dfd, path, UIO_SYSSPACE, flags, amode); 693 LFREEPATH(path); 694 } 695 696 return (error); 697 } 698 699 int 700 linux_faccessat(struct thread *td, struct linux_faccessat_args *args) 701 { 702 703 return (linux_do_accessat(td, args->dfd, args->filename, args->amode, 704 0)); 705 } 706 707 int 708 linux_faccessat2(struct thread *td, struct linux_faccessat2_args *args) 709 { 710 int flags, unsupported; 711 712 /* XXX. AT_SYMLINK_NOFOLLOW is not supported by kern_accessat */ 713 unsupported = args->flags & ~(LINUX_AT_EACCESS | LINUX_AT_EMPTY_PATH); 714 if (unsupported != 0) { 715 linux_msg(td, "faccessat2 unsupported flag 0x%x", unsupported); 716 return (EINVAL); 717 } 718 719 flags = (args->flags & LINUX_AT_EACCESS) == 0 ? 0 : 720 AT_EACCESS; 721 flags |= (args->flags & LINUX_AT_EMPTY_PATH) == 0 ? 0 : 722 AT_EMPTY_PATH; 723 return (linux_do_accessat(td, args->dfd, args->filename, args->amode, 724 flags)); 725 } 726 727 728 #ifdef LINUX_LEGACY_SYSCALLS 729 int 730 linux_unlink(struct thread *td, struct linux_unlink_args *args) 731 { 732 char *path; 733 int error; 734 struct stat st; 735 736 if (!LUSECONVPATH(td)) { 737 error = kern_funlinkat(td, AT_FDCWD, args->path, FD_NONE, 738 UIO_USERSPACE, 0, 0); 739 if (error == EPERM) { 740 /* Introduce POSIX noncompliant behaviour of Linux */ 741 if (kern_statat(td, 0, AT_FDCWD, args->path, 742 UIO_USERSPACE, &st, NULL) == 0) { 743 if (S_ISDIR(st.st_mode)) 744 error = EISDIR; 745 } 746 } 747 } else { 748 LCONVPATHEXIST(args->path, &path); 749 error = kern_funlinkat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0, 0); 750 if (error == EPERM) { 751 /* Introduce POSIX noncompliant behaviour of Linux */ 752 if (kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, 753 NULL) == 0) { 754 if (S_ISDIR(st.st_mode)) 755 error = EISDIR; 756 } 757 } 758 LFREEPATH(path); 759 } 760 761 return (error); 762 } 763 #endif 764 765 static int 766 linux_unlinkat_impl(struct thread *td, enum uio_seg pathseg, const char *path, 767 int dfd, struct linux_unlinkat_args *args) 768 { 769 struct stat st; 770 int error; 771 772 if (args->flag & LINUX_AT_REMOVEDIR) 773 error = kern_frmdirat(td, dfd, path, FD_NONE, pathseg, 0); 774 else 775 error = kern_funlinkat(td, dfd, path, FD_NONE, pathseg, 0, 0); 776 if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) { 777 /* Introduce POSIX noncompliant behaviour of Linux */ 778 if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path, 779 pathseg, &st, NULL) == 0 && S_ISDIR(st.st_mode)) 780 error = EISDIR; 781 } 782 return (error); 783 } 784 785 int 786 linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args) 787 { 788 char *path; 789 int error, dfd; 790 791 if (args->flag & ~LINUX_AT_REMOVEDIR) 792 return (EINVAL); 793 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 794 if (!LUSECONVPATH(td)) { 795 return (linux_unlinkat_impl(td, UIO_USERSPACE, args->pathname, 796 dfd, args)); 797 } 798 LCONVPATHEXIST_AT(args->pathname, &path, dfd); 799 error = linux_unlinkat_impl(td, UIO_SYSSPACE, path, dfd, args); 800 LFREEPATH(path); 801 return (error); 802 } 803 int 804 linux_chdir(struct thread *td, struct linux_chdir_args *args) 805 { 806 char *path; 807 int error; 808 809 if (!LUSECONVPATH(td)) { 810 return (kern_chdir(td, args->path, UIO_USERSPACE)); 811 } 812 LCONVPATHEXIST(args->path, &path); 813 error = kern_chdir(td, path, UIO_SYSSPACE); 814 LFREEPATH(path); 815 return (error); 816 } 817 818 #ifdef LINUX_LEGACY_SYSCALLS 819 int 820 linux_chmod(struct thread *td, struct linux_chmod_args *args) 821 { 822 char *path; 823 int error; 824 825 if (!LUSECONVPATH(td)) { 826 return (kern_fchmodat(td, AT_FDCWD, args->path, UIO_USERSPACE, 827 args->mode, 0)); 828 } 829 LCONVPATHEXIST(args->path, &path); 830 error = kern_fchmodat(td, AT_FDCWD, path, UIO_SYSSPACE, args->mode, 0); 831 LFREEPATH(path); 832 return (error); 833 } 834 #endif 835 836 int 837 linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args) 838 { 839 char *path; 840 int error, dfd; 841 842 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 843 if (!LUSECONVPATH(td)) { 844 return (kern_fchmodat(td, dfd, args->filename, UIO_USERSPACE, 845 args->mode, 0)); 846 } 847 LCONVPATHEXIST_AT(args->filename, &path, dfd); 848 error = kern_fchmodat(td, dfd, path, UIO_SYSSPACE, args->mode, 0); 849 LFREEPATH(path); 850 return (error); 851 } 852 853 #ifdef LINUX_LEGACY_SYSCALLS 854 int 855 linux_mkdir(struct thread *td, struct linux_mkdir_args *args) 856 { 857 char *path; 858 int error; 859 860 if (!LUSECONVPATH(td)) { 861 return (kern_mkdirat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->mode)); 862 } 863 LCONVPATHCREAT(args->path, &path); 864 error = kern_mkdirat(td, AT_FDCWD, path, UIO_SYSSPACE, args->mode); 865 LFREEPATH(path); 866 return (error); 867 } 868 #endif 869 870 int 871 linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args) 872 { 873 char *path; 874 int error, dfd; 875 876 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 877 if (!LUSECONVPATH(td)) { 878 return (kern_mkdirat(td, dfd, args->pathname, UIO_USERSPACE, args->mode)); 879 } 880 LCONVPATHCREAT_AT(args->pathname, &path, dfd); 881 error = kern_mkdirat(td, dfd, path, UIO_SYSSPACE, args->mode); 882 LFREEPATH(path); 883 return (error); 884 } 885 886 #ifdef LINUX_LEGACY_SYSCALLS 887 int 888 linux_rmdir(struct thread *td, struct linux_rmdir_args *args) 889 { 890 char *path; 891 int error; 892 893 if (!LUSECONVPATH(td)) { 894 return (kern_frmdirat(td, AT_FDCWD, args->path, FD_NONE, 895 UIO_USERSPACE, 0)); 896 } 897 LCONVPATHEXIST(args->path, &path); 898 error = kern_frmdirat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0); 899 LFREEPATH(path); 900 return (error); 901 } 902 903 int 904 linux_rename(struct thread *td, struct linux_rename_args *args) 905 { 906 char *from, *to; 907 int error; 908 909 if (!LUSECONVPATH(td)) { 910 return (kern_renameat(td, AT_FDCWD, args->from, AT_FDCWD, 911 args->to, UIO_USERSPACE)); 912 } 913 LCONVPATHEXIST(args->from, &from); 914 /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ 915 error = linux_emul_convpath(args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); 916 if (to == NULL) { 917 LFREEPATH(from); 918 return (error); 919 } 920 error = kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, UIO_SYSSPACE); 921 LFREEPATH(from); 922 LFREEPATH(to); 923 return (error); 924 } 925 #endif 926 927 int 928 linux_renameat(struct thread *td, struct linux_renameat_args *args) 929 { 930 struct linux_renameat2_args renameat2_args = { 931 .olddfd = args->olddfd, 932 .oldname = args->oldname, 933 .newdfd = args->newdfd, 934 .newname = args->newname, 935 .flags = 0 936 }; 937 938 return (linux_renameat2(td, &renameat2_args)); 939 } 940 941 int 942 linux_renameat2(struct thread *td, struct linux_renameat2_args *args) 943 { 944 char *from, *to; 945 int error, olddfd, newdfd; 946 947 if (args->flags != 0) { 948 if (args->flags & ~(LINUX_RENAME_EXCHANGE | 949 LINUX_RENAME_NOREPLACE | LINUX_RENAME_WHITEOUT)) 950 return (EINVAL); 951 if (args->flags & LINUX_RENAME_EXCHANGE && 952 args->flags & (LINUX_RENAME_NOREPLACE | 953 LINUX_RENAME_WHITEOUT)) 954 return (EINVAL); 955 #if 0 956 /* 957 * This spams the console on Ubuntu Focal. 958 * 959 * What's needed here is a general mechanism to let users know 960 * about missing features without hogging the system. 961 */ 962 linux_msg(td, "renameat2 unsupported flags 0x%x", 963 args->flags); 964 #endif 965 return (EINVAL); 966 } 967 968 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; 969 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; 970 if (!LUSECONVPATH(td)) { 971 return (kern_renameat(td, olddfd, args->oldname, newdfd, 972 args->newname, UIO_USERSPACE)); 973 } 974 LCONVPATHEXIST_AT(args->oldname, &from, olddfd); 975 /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ 976 error = linux_emul_convpath(args->newname, UIO_USERSPACE, &to, 1, newdfd); 977 if (to == NULL) { 978 LFREEPATH(from); 979 return (error); 980 } 981 error = kern_renameat(td, olddfd, from, newdfd, to, UIO_SYSSPACE); 982 LFREEPATH(from); 983 LFREEPATH(to); 984 return (error); 985 } 986 987 #ifdef LINUX_LEGACY_SYSCALLS 988 int 989 linux_symlink(struct thread *td, struct linux_symlink_args *args) 990 { 991 char *path, *to; 992 int error; 993 994 if (!LUSECONVPATH(td)) { 995 return (kern_symlinkat(td, args->path, AT_FDCWD, args->to, 996 UIO_USERSPACE)); 997 } 998 LCONVPATHEXIST(args->path, &path); 999 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 1000 error = linux_emul_convpath(args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); 1001 if (to == NULL) { 1002 LFREEPATH(path); 1003 return (error); 1004 } 1005 error = kern_symlinkat(td, path, AT_FDCWD, to, UIO_SYSSPACE); 1006 LFREEPATH(path); 1007 LFREEPATH(to); 1008 return (error); 1009 } 1010 #endif 1011 1012 int 1013 linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args) 1014 { 1015 char *path, *to; 1016 int error, dfd; 1017 1018 dfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; 1019 if (!LUSECONVPATH(td)) { 1020 return (kern_symlinkat(td, args->oldname, dfd, args->newname, 1021 UIO_USERSPACE)); 1022 } 1023 LCONVPATHEXIST(args->oldname, &path); 1024 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 1025 error = linux_emul_convpath(args->newname, UIO_USERSPACE, &to, 1, dfd); 1026 if (to == NULL) { 1027 LFREEPATH(path); 1028 return (error); 1029 } 1030 error = kern_symlinkat(td, path, dfd, to, UIO_SYSSPACE); 1031 LFREEPATH(path); 1032 LFREEPATH(to); 1033 return (error); 1034 } 1035 1036 #ifdef LINUX_LEGACY_SYSCALLS 1037 int 1038 linux_readlink(struct thread *td, struct linux_readlink_args *args) 1039 { 1040 char *name; 1041 int error; 1042 1043 if (args->count <= 0) 1044 return (EINVAL); 1045 1046 if (!LUSECONVPATH(td)) { 1047 return (kern_readlinkat(td, AT_FDCWD, args->name, UIO_USERSPACE, 1048 args->buf, UIO_USERSPACE, args->count)); 1049 } 1050 LCONVPATHEXIST(args->name, &name); 1051 error = kern_readlinkat(td, AT_FDCWD, name, UIO_SYSSPACE, 1052 args->buf, UIO_USERSPACE, args->count); 1053 LFREEPATH(name); 1054 return (error); 1055 } 1056 #endif 1057 1058 int 1059 linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args) 1060 { 1061 char *name; 1062 int error, dfd; 1063 1064 if (args->bufsiz <= 0) 1065 return (EINVAL); 1066 1067 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 1068 if (!LUSECONVPATH(td)) { 1069 return (kern_readlinkat(td, dfd, args->path, UIO_USERSPACE, 1070 args->buf, UIO_USERSPACE, args->bufsiz)); 1071 } 1072 LCONVPATHEXIST_AT(args->path, &name, dfd); 1073 error = kern_readlinkat(td, dfd, name, UIO_SYSSPACE, args->buf, 1074 UIO_USERSPACE, args->bufsiz); 1075 LFREEPATH(name); 1076 return (error); 1077 } 1078 1079 int 1080 linux_truncate(struct thread *td, struct linux_truncate_args *args) 1081 { 1082 char *path; 1083 int error; 1084 1085 if (!LUSECONVPATH(td)) { 1086 return (kern_truncate(td, args->path, UIO_USERSPACE, args->length)); 1087 } 1088 LCONVPATHEXIST(args->path, &path); 1089 error = kern_truncate(td, path, UIO_SYSSPACE, args->length); 1090 LFREEPATH(path); 1091 return (error); 1092 } 1093 1094 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1095 int 1096 linux_truncate64(struct thread *td, struct linux_truncate64_args *args) 1097 { 1098 char *path; 1099 off_t length; 1100 int error; 1101 1102 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1103 length = PAIR32TO64(off_t, args->length); 1104 #else 1105 length = args->length; 1106 #endif 1107 1108 if (!LUSECONVPATH(td)) { 1109 return (kern_truncate(td, args->path, UIO_USERSPACE, length)); 1110 } 1111 LCONVPATHEXIST(args->path, &path); 1112 error = kern_truncate(td, path, UIO_SYSSPACE, length); 1113 LFREEPATH(path); 1114 return (error); 1115 } 1116 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1117 1118 int 1119 linux_ftruncate(struct thread *td, struct linux_ftruncate_args *args) 1120 { 1121 1122 return (kern_ftruncate(td, args->fd, args->length)); 1123 } 1124 1125 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1126 int 1127 linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) 1128 { 1129 off_t length; 1130 1131 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1132 length = PAIR32TO64(off_t, args->length); 1133 #else 1134 length = args->length; 1135 #endif 1136 1137 return (kern_ftruncate(td, args->fd, length)); 1138 } 1139 #endif 1140 1141 #ifdef LINUX_LEGACY_SYSCALLS 1142 int 1143 linux_link(struct thread *td, struct linux_link_args *args) 1144 { 1145 char *path, *to; 1146 int error; 1147 1148 if (!LUSECONVPATH(td)) { 1149 return (kern_linkat(td, AT_FDCWD, AT_FDCWD, args->path, args->to, 1150 UIO_USERSPACE, AT_SYMLINK_FOLLOW)); 1151 } 1152 LCONVPATHEXIST(args->path, &path); 1153 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 1154 error = linux_emul_convpath(args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); 1155 if (to == NULL) { 1156 LFREEPATH(path); 1157 return (error); 1158 } 1159 error = kern_linkat(td, AT_FDCWD, AT_FDCWD, path, to, UIO_SYSSPACE, 1160 AT_SYMLINK_FOLLOW); 1161 LFREEPATH(path); 1162 LFREEPATH(to); 1163 return (error); 1164 } 1165 #endif 1166 1167 int 1168 linux_linkat(struct thread *td, struct linux_linkat_args *args) 1169 { 1170 char *path, *to; 1171 int error, olddfd, newdfd, flag; 1172 1173 if (args->flag & ~(LINUX_AT_SYMLINK_FOLLOW | LINUX_AT_EMPTY_PATH)) 1174 return (EINVAL); 1175 1176 flag = (args->flag & LINUX_AT_SYMLINK_FOLLOW) != 0 ? AT_SYMLINK_FOLLOW : 1177 0; 1178 flag |= (args->flag & LINUX_AT_EMPTY_PATH) != 0 ? AT_EMPTY_PATH : 0; 1179 1180 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; 1181 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; 1182 if (!LUSECONVPATH(td)) { 1183 return (kern_linkat(td, olddfd, newdfd, args->oldname, 1184 args->newname, UIO_USERSPACE, flag)); 1185 } 1186 LCONVPATHEXIST_AT(args->oldname, &path, olddfd); 1187 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 1188 error = linux_emul_convpath(args->newname, UIO_USERSPACE, &to, 1, newdfd); 1189 if (to == NULL) { 1190 LFREEPATH(path); 1191 return (error); 1192 } 1193 error = kern_linkat(td, olddfd, newdfd, path, to, UIO_SYSSPACE, flag); 1194 LFREEPATH(path); 1195 LFREEPATH(to); 1196 return (error); 1197 } 1198 1199 int 1200 linux_fdatasync(struct thread *td, struct linux_fdatasync_args *uap) 1201 { 1202 1203 return (kern_fsync(td, uap->fd, false)); 1204 } 1205 1206 int 1207 linux_sync_file_range(struct thread *td, struct linux_sync_file_range_args *uap) 1208 { 1209 off_t nbytes, offset; 1210 1211 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1212 nbytes = PAIR32TO64(off_t, uap->nbytes); 1213 offset = PAIR32TO64(off_t, uap->offset); 1214 #else 1215 nbytes = uap->nbytes; 1216 offset = uap->offset; 1217 #endif 1218 1219 if (offset < 0 || nbytes < 0 || 1220 (uap->flags & ~(LINUX_SYNC_FILE_RANGE_WAIT_BEFORE | 1221 LINUX_SYNC_FILE_RANGE_WRITE | 1222 LINUX_SYNC_FILE_RANGE_WAIT_AFTER)) != 0) { 1223 return (EINVAL); 1224 } 1225 1226 return (kern_fsync(td, uap->fd, false)); 1227 } 1228 1229 int 1230 linux_pread(struct thread *td, struct linux_pread_args *uap) 1231 { 1232 struct vnode *vp; 1233 off_t offset; 1234 int error; 1235 1236 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1237 offset = PAIR32TO64(off_t, uap->offset); 1238 #else 1239 offset = uap->offset; 1240 #endif 1241 1242 error = kern_pread(td, uap->fd, uap->buf, uap->nbyte, offset); 1243 if (error == 0) { 1244 /* This seems to violate POSIX but Linux does it. */ 1245 error = fgetvp(td, uap->fd, &cap_pread_rights, &vp); 1246 if (error != 0) 1247 return (error); 1248 if (vp->v_type == VDIR) 1249 error = EISDIR; 1250 vrele(vp); 1251 } 1252 return (error); 1253 } 1254 1255 int 1256 linux_pwrite(struct thread *td, struct linux_pwrite_args *uap) 1257 { 1258 off_t offset; 1259 1260 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1261 offset = PAIR32TO64(off_t, uap->offset); 1262 #else 1263 offset = uap->offset; 1264 #endif 1265 1266 return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte, offset)); 1267 } 1268 1269 #define HALF_LONG_BITS ((sizeof(l_long) * NBBY / 2)) 1270 1271 static inline off_t 1272 pos_from_hilo(unsigned long high, unsigned long low) 1273 { 1274 1275 return (((off_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low; 1276 } 1277 1278 int 1279 linux_preadv(struct thread *td, struct linux_preadv_args *uap) 1280 { 1281 struct uio *auio; 1282 int error; 1283 off_t offset; 1284 1285 /* 1286 * According http://man7.org/linux/man-pages/man2/preadv.2.html#NOTES 1287 * pos_l and pos_h, respectively, contain the 1288 * low order and high order 32 bits of offset. 1289 */ 1290 offset = pos_from_hilo(uap->pos_h, uap->pos_l); 1291 if (offset < 0) 1292 return (EINVAL); 1293 #ifdef COMPAT_LINUX32 1294 error = linux32_copyinuio(PTRIN(uap->vec), uap->vlen, &auio); 1295 #else 1296 error = copyinuio(uap->vec, uap->vlen, &auio); 1297 #endif 1298 if (error != 0) 1299 return (error); 1300 error = kern_preadv(td, uap->fd, auio, offset); 1301 free(auio, M_IOV); 1302 return (error); 1303 } 1304 1305 int 1306 linux_pwritev(struct thread *td, struct linux_pwritev_args *uap) 1307 { 1308 struct uio *auio; 1309 int error; 1310 off_t offset; 1311 1312 /* 1313 * According http://man7.org/linux/man-pages/man2/pwritev.2.html#NOTES 1314 * pos_l and pos_h, respectively, contain the 1315 * low order and high order 32 bits of offset. 1316 */ 1317 offset = pos_from_hilo(uap->pos_h, uap->pos_l); 1318 if (offset < 0) 1319 return (EINVAL); 1320 #ifdef COMPAT_LINUX32 1321 error = linux32_copyinuio(PTRIN(uap->vec), uap->vlen, &auio); 1322 #else 1323 error = copyinuio(uap->vec, uap->vlen, &auio); 1324 #endif 1325 if (error != 0) 1326 return (error); 1327 error = kern_pwritev(td, uap->fd, auio, offset); 1328 free(auio, M_IOV); 1329 return (error); 1330 } 1331 1332 int 1333 linux_mount(struct thread *td, struct linux_mount_args *args) 1334 { 1335 struct mntarg *ma = NULL; 1336 char *fstypename, *mntonname, *mntfromname, *data; 1337 int error, fsflags; 1338 1339 fstypename = malloc(MNAMELEN, M_TEMP, M_WAITOK); 1340 mntonname = malloc(MNAMELEN, M_TEMP, M_WAITOK); 1341 mntfromname = malloc(MNAMELEN, M_TEMP, M_WAITOK); 1342 data = NULL; 1343 error = copyinstr(args->filesystemtype, fstypename, MNAMELEN - 1, 1344 NULL); 1345 if (error != 0) 1346 goto out; 1347 if (args->specialfile != NULL) { 1348 error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL); 1349 if (error != 0) 1350 goto out; 1351 } else { 1352 mntfromname[0] = '\0'; 1353 } 1354 error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL); 1355 if (error != 0) 1356 goto out; 1357 1358 if (strcmp(fstypename, "ext2") == 0) { 1359 strcpy(fstypename, "ext2fs"); 1360 } else if (strcmp(fstypename, "proc") == 0) { 1361 strcpy(fstypename, "linprocfs"); 1362 } else if (strcmp(fstypename, "vfat") == 0) { 1363 strcpy(fstypename, "msdosfs"); 1364 } else if (strcmp(fstypename, "fuse") == 0 || 1365 strncmp(fstypename, "fuse.", 5) == 0) { 1366 char *fuse_options, *fuse_option, *fuse_name; 1367 1368 strcpy(mntfromname, "/dev/fuse"); 1369 strcpy(fstypename, "fusefs"); 1370 data = malloc(MNAMELEN, M_TEMP, M_WAITOK); 1371 error = copyinstr(args->data, data, MNAMELEN - 1, NULL); 1372 if (error != 0) 1373 goto out; 1374 1375 fuse_options = data; 1376 while ((fuse_option = strsep(&fuse_options, ",")) != NULL) { 1377 fuse_name = strsep(&fuse_option, "="); 1378 if (fuse_name == NULL || fuse_option == NULL) 1379 goto out; 1380 ma = mount_arg(ma, fuse_name, fuse_option, -1); 1381 } 1382 1383 /* 1384 * The FUSE server uses Linux errno values instead of FreeBSD 1385 * ones; add a flag to tell fuse(4) to do errno translation. 1386 */ 1387 ma = mount_arg(ma, "linux_errnos", "1", -1); 1388 } 1389 1390 fsflags = 0; 1391 1392 /* 1393 * Linux SYNC flag is not included; the closest equivalent 1394 * FreeBSD has is !ASYNC, which is our default. 1395 */ 1396 if (args->rwflag & LINUX_MS_RDONLY) 1397 fsflags |= MNT_RDONLY; 1398 if (args->rwflag & LINUX_MS_NOSUID) 1399 fsflags |= MNT_NOSUID; 1400 if (args->rwflag & LINUX_MS_NOEXEC) 1401 fsflags |= MNT_NOEXEC; 1402 if (args->rwflag & LINUX_MS_REMOUNT) 1403 fsflags |= MNT_UPDATE; 1404 1405 ma = mount_arg(ma, "fstype", fstypename, -1); 1406 ma = mount_arg(ma, "fspath", mntonname, -1); 1407 ma = mount_arg(ma, "from", mntfromname, -1); 1408 error = kernel_mount(ma, fsflags); 1409 out: 1410 free(fstypename, M_TEMP); 1411 free(mntonname, M_TEMP); 1412 free(mntfromname, M_TEMP); 1413 free(data, M_TEMP); 1414 return (error); 1415 } 1416 1417 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1418 int 1419 linux_oldumount(struct thread *td, struct linux_oldumount_args *args) 1420 { 1421 1422 return (kern_unmount(td, args->path, 0)); 1423 } 1424 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1425 1426 #ifdef LINUX_LEGACY_SYSCALLS 1427 int 1428 linux_umount(struct thread *td, struct linux_umount_args *args) 1429 { 1430 int flags; 1431 1432 flags = 0; 1433 if ((args->flags & LINUX_MNT_FORCE) != 0) { 1434 args->flags &= ~LINUX_MNT_FORCE; 1435 flags |= MNT_FORCE; 1436 } 1437 if (args->flags != 0) { 1438 linux_msg(td, "unsupported umount2 flags %#x", args->flags); 1439 return (EINVAL); 1440 } 1441 1442 return (kern_unmount(td, args->path, flags)); 1443 } 1444 #endif 1445 1446 /* 1447 * fcntl family of syscalls 1448 */ 1449 1450 struct l_flock { 1451 l_short l_type; 1452 l_short l_whence; 1453 l_off_t l_start; 1454 l_off_t l_len; 1455 l_pid_t l_pid; 1456 } 1457 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1458 __packed 1459 #endif 1460 ; 1461 1462 static void 1463 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 1464 { 1465 switch (linux_flock->l_type) { 1466 case LINUX_F_RDLCK: 1467 bsd_flock->l_type = F_RDLCK; 1468 break; 1469 case LINUX_F_WRLCK: 1470 bsd_flock->l_type = F_WRLCK; 1471 break; 1472 case LINUX_F_UNLCK: 1473 bsd_flock->l_type = F_UNLCK; 1474 break; 1475 default: 1476 bsd_flock->l_type = -1; 1477 break; 1478 } 1479 bsd_flock->l_whence = linux_flock->l_whence; 1480 bsd_flock->l_start = (off_t)linux_flock->l_start; 1481 bsd_flock->l_len = (off_t)linux_flock->l_len; 1482 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 1483 bsd_flock->l_sysid = 0; 1484 } 1485 1486 static void 1487 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 1488 { 1489 switch (bsd_flock->l_type) { 1490 case F_RDLCK: 1491 linux_flock->l_type = LINUX_F_RDLCK; 1492 break; 1493 case F_WRLCK: 1494 linux_flock->l_type = LINUX_F_WRLCK; 1495 break; 1496 case F_UNLCK: 1497 linux_flock->l_type = LINUX_F_UNLCK; 1498 break; 1499 } 1500 linux_flock->l_whence = bsd_flock->l_whence; 1501 linux_flock->l_start = (l_off_t)bsd_flock->l_start; 1502 linux_flock->l_len = (l_off_t)bsd_flock->l_len; 1503 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 1504 } 1505 1506 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1507 struct l_flock64 { 1508 l_short l_type; 1509 l_short l_whence; 1510 l_loff_t l_start; 1511 l_loff_t l_len; 1512 l_pid_t l_pid; 1513 } 1514 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1515 __packed 1516 #endif 1517 ; 1518 1519 static void 1520 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 1521 { 1522 switch (linux_flock->l_type) { 1523 case LINUX_F_RDLCK: 1524 bsd_flock->l_type = F_RDLCK; 1525 break; 1526 case LINUX_F_WRLCK: 1527 bsd_flock->l_type = F_WRLCK; 1528 break; 1529 case LINUX_F_UNLCK: 1530 bsd_flock->l_type = F_UNLCK; 1531 break; 1532 default: 1533 bsd_flock->l_type = -1; 1534 break; 1535 } 1536 bsd_flock->l_whence = linux_flock->l_whence; 1537 bsd_flock->l_start = (off_t)linux_flock->l_start; 1538 bsd_flock->l_len = (off_t)linux_flock->l_len; 1539 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 1540 bsd_flock->l_sysid = 0; 1541 } 1542 1543 static void 1544 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 1545 { 1546 switch (bsd_flock->l_type) { 1547 case F_RDLCK: 1548 linux_flock->l_type = LINUX_F_RDLCK; 1549 break; 1550 case F_WRLCK: 1551 linux_flock->l_type = LINUX_F_WRLCK; 1552 break; 1553 case F_UNLCK: 1554 linux_flock->l_type = LINUX_F_UNLCK; 1555 break; 1556 } 1557 linux_flock->l_whence = bsd_flock->l_whence; 1558 linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 1559 linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 1560 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 1561 } 1562 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1563 1564 static int 1565 fcntl_common(struct thread *td, struct linux_fcntl_args *args) 1566 { 1567 struct l_flock linux_flock; 1568 struct flock bsd_flock; 1569 struct pipe *fpipe; 1570 struct file *fp; 1571 long arg; 1572 int error, result; 1573 1574 switch (args->cmd) { 1575 case LINUX_F_DUPFD: 1576 return (kern_fcntl(td, args->fd, F_DUPFD, args->arg)); 1577 1578 case LINUX_F_GETFD: 1579 return (kern_fcntl(td, args->fd, F_GETFD, 0)); 1580 1581 case LINUX_F_SETFD: 1582 return (kern_fcntl(td, args->fd, F_SETFD, args->arg)); 1583 1584 case LINUX_F_GETFL: 1585 error = kern_fcntl(td, args->fd, F_GETFL, 0); 1586 result = td->td_retval[0]; 1587 td->td_retval[0] = 0; 1588 if (result & O_RDONLY) 1589 td->td_retval[0] |= LINUX_O_RDONLY; 1590 if (result & O_WRONLY) 1591 td->td_retval[0] |= LINUX_O_WRONLY; 1592 if (result & O_RDWR) 1593 td->td_retval[0] |= LINUX_O_RDWR; 1594 if (result & O_NDELAY) 1595 td->td_retval[0] |= LINUX_O_NONBLOCK; 1596 if (result & O_APPEND) 1597 td->td_retval[0] |= LINUX_O_APPEND; 1598 if (result & O_FSYNC) 1599 td->td_retval[0] |= LINUX_O_SYNC; 1600 if (result & O_ASYNC) 1601 td->td_retval[0] |= LINUX_O_ASYNC; 1602 #ifdef LINUX_O_NOFOLLOW 1603 if (result & O_NOFOLLOW) 1604 td->td_retval[0] |= LINUX_O_NOFOLLOW; 1605 #endif 1606 #ifdef LINUX_O_DIRECT 1607 if (result & O_DIRECT) 1608 td->td_retval[0] |= LINUX_O_DIRECT; 1609 #endif 1610 return (error); 1611 1612 case LINUX_F_SETFL: 1613 arg = 0; 1614 if (args->arg & LINUX_O_NDELAY) 1615 arg |= O_NONBLOCK; 1616 if (args->arg & LINUX_O_APPEND) 1617 arg |= O_APPEND; 1618 if (args->arg & LINUX_O_SYNC) 1619 arg |= O_FSYNC; 1620 if (args->arg & LINUX_O_ASYNC) 1621 arg |= O_ASYNC; 1622 #ifdef LINUX_O_NOFOLLOW 1623 if (args->arg & LINUX_O_NOFOLLOW) 1624 arg |= O_NOFOLLOW; 1625 #endif 1626 #ifdef LINUX_O_DIRECT 1627 if (args->arg & LINUX_O_DIRECT) 1628 arg |= O_DIRECT; 1629 #endif 1630 return (kern_fcntl(td, args->fd, F_SETFL, arg)); 1631 1632 case LINUX_F_GETLK: 1633 error = copyin((void *)args->arg, &linux_flock, 1634 sizeof(linux_flock)); 1635 if (error) 1636 return (error); 1637 linux_to_bsd_flock(&linux_flock, &bsd_flock); 1638 error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 1639 if (error) 1640 return (error); 1641 bsd_to_linux_flock(&bsd_flock, &linux_flock); 1642 return (copyout(&linux_flock, (void *)args->arg, 1643 sizeof(linux_flock))); 1644 1645 case LINUX_F_SETLK: 1646 error = copyin((void *)args->arg, &linux_flock, 1647 sizeof(linux_flock)); 1648 if (error) 1649 return (error); 1650 linux_to_bsd_flock(&linux_flock, &bsd_flock); 1651 return (kern_fcntl(td, args->fd, F_SETLK, 1652 (intptr_t)&bsd_flock)); 1653 1654 case LINUX_F_SETLKW: 1655 error = copyin((void *)args->arg, &linux_flock, 1656 sizeof(linux_flock)); 1657 if (error) 1658 return (error); 1659 linux_to_bsd_flock(&linux_flock, &bsd_flock); 1660 return (kern_fcntl(td, args->fd, F_SETLKW, 1661 (intptr_t)&bsd_flock)); 1662 1663 case LINUX_F_GETOWN: 1664 return (kern_fcntl(td, args->fd, F_GETOWN, 0)); 1665 1666 case LINUX_F_SETOWN: 1667 /* 1668 * XXX some Linux applications depend on F_SETOWN having no 1669 * significant effect for pipes (SIGIO is not delivered for 1670 * pipes under Linux-2.2.35 at least). 1671 */ 1672 error = fget(td, args->fd, 1673 &cap_fcntl_rights, &fp); 1674 if (error) 1675 return (error); 1676 if (fp->f_type == DTYPE_PIPE) { 1677 fdrop(fp, td); 1678 return (EINVAL); 1679 } 1680 fdrop(fp, td); 1681 1682 return (kern_fcntl(td, args->fd, F_SETOWN, args->arg)); 1683 1684 case LINUX_F_DUPFD_CLOEXEC: 1685 return (kern_fcntl(td, args->fd, F_DUPFD_CLOEXEC, args->arg)); 1686 /* 1687 * Our F_SEAL_* values match Linux one for maximum compatibility. So we 1688 * only needed to account for different values for fcntl(2) commands. 1689 */ 1690 case LINUX_F_GET_SEALS: 1691 error = kern_fcntl(td, args->fd, F_GET_SEALS, 0); 1692 if (error != 0) 1693 return (error); 1694 td->td_retval[0] = bsd_to_linux_bits(td->td_retval[0], 1695 seal_bitmap, 0); 1696 return (0); 1697 1698 case LINUX_F_ADD_SEALS: 1699 return (kern_fcntl(td, args->fd, F_ADD_SEALS, 1700 linux_to_bsd_bits(args->arg, seal_bitmap, 0))); 1701 1702 case LINUX_F_GETPIPE_SZ: 1703 error = fget(td, args->fd, 1704 &cap_fcntl_rights, &fp); 1705 if (error != 0) 1706 return (error); 1707 if (fp->f_type != DTYPE_PIPE) { 1708 fdrop(fp, td); 1709 return (EINVAL); 1710 } 1711 fpipe = fp->f_data; 1712 td->td_retval[0] = fpipe->pipe_buffer.size; 1713 fdrop(fp, td); 1714 return (0); 1715 1716 default: 1717 linux_msg(td, "unsupported fcntl cmd %d", args->cmd); 1718 return (EINVAL); 1719 } 1720 } 1721 1722 int 1723 linux_fcntl(struct thread *td, struct linux_fcntl_args *args) 1724 { 1725 1726 return (fcntl_common(td, args)); 1727 } 1728 1729 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1730 int 1731 linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 1732 { 1733 struct l_flock64 linux_flock; 1734 struct flock bsd_flock; 1735 struct linux_fcntl_args fcntl_args; 1736 int error; 1737 1738 switch (args->cmd) { 1739 case LINUX_F_GETLK64: 1740 error = copyin((void *)args->arg, &linux_flock, 1741 sizeof(linux_flock)); 1742 if (error) 1743 return (error); 1744 linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1745 error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 1746 if (error) 1747 return (error); 1748 bsd_to_linux_flock64(&bsd_flock, &linux_flock); 1749 return (copyout(&linux_flock, (void *)args->arg, 1750 sizeof(linux_flock))); 1751 1752 case LINUX_F_SETLK64: 1753 error = copyin((void *)args->arg, &linux_flock, 1754 sizeof(linux_flock)); 1755 if (error) 1756 return (error); 1757 linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1758 return (kern_fcntl(td, args->fd, F_SETLK, 1759 (intptr_t)&bsd_flock)); 1760 1761 case LINUX_F_SETLKW64: 1762 error = copyin((void *)args->arg, &linux_flock, 1763 sizeof(linux_flock)); 1764 if (error) 1765 return (error); 1766 linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1767 return (kern_fcntl(td, args->fd, F_SETLKW, 1768 (intptr_t)&bsd_flock)); 1769 } 1770 1771 fcntl_args.fd = args->fd; 1772 fcntl_args.cmd = args->cmd; 1773 fcntl_args.arg = args->arg; 1774 return (fcntl_common(td, &fcntl_args)); 1775 } 1776 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1777 1778 #ifdef LINUX_LEGACY_SYSCALLS 1779 int 1780 linux_chown(struct thread *td, struct linux_chown_args *args) 1781 { 1782 char *path; 1783 int error; 1784 1785 if (!LUSECONVPATH(td)) { 1786 return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, 1787 args->uid, args->gid, 0)); 1788 } 1789 LCONVPATHEXIST(args->path, &path); 1790 error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid, 1791 args->gid, 0); 1792 LFREEPATH(path); 1793 return (error); 1794 } 1795 #endif 1796 1797 int 1798 linux_fchownat(struct thread *td, struct linux_fchownat_args *args) 1799 { 1800 char *path; 1801 int error, dfd, flag, unsupported; 1802 1803 unsupported = args->flag & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH); 1804 if (unsupported != 0) { 1805 linux_msg(td, "fchownat unsupported flag 0x%x", unsupported); 1806 return (EINVAL); 1807 } 1808 1809 flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 : 1810 AT_SYMLINK_NOFOLLOW; 1811 flag |= (args->flag & LINUX_AT_EMPTY_PATH) == 0 ? 0 : 1812 AT_EMPTY_PATH; 1813 1814 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 1815 if (!LUSECONVPATH(td)) { 1816 return (kern_fchownat(td, dfd, args->filename, UIO_USERSPACE, 1817 args->uid, args->gid, flag)); 1818 } 1819 LCONVPATHEXIST_AT(args->filename, &path, dfd); 1820 error = kern_fchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid, 1821 flag); 1822 LFREEPATH(path); 1823 return (error); 1824 } 1825 1826 #ifdef LINUX_LEGACY_SYSCALLS 1827 int 1828 linux_lchown(struct thread *td, struct linux_lchown_args *args) 1829 { 1830 char *path; 1831 int error; 1832 1833 if (!LUSECONVPATH(td)) { 1834 return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->uid, 1835 args->gid, AT_SYMLINK_NOFOLLOW)); 1836 } 1837 LCONVPATHEXIST(args->path, &path); 1838 error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid, args->gid, 1839 AT_SYMLINK_NOFOLLOW); 1840 LFREEPATH(path); 1841 return (error); 1842 } 1843 #endif 1844 1845 static int 1846 convert_fadvice(int advice) 1847 { 1848 switch (advice) { 1849 case LINUX_POSIX_FADV_NORMAL: 1850 return (POSIX_FADV_NORMAL); 1851 case LINUX_POSIX_FADV_RANDOM: 1852 return (POSIX_FADV_RANDOM); 1853 case LINUX_POSIX_FADV_SEQUENTIAL: 1854 return (POSIX_FADV_SEQUENTIAL); 1855 case LINUX_POSIX_FADV_WILLNEED: 1856 return (POSIX_FADV_WILLNEED); 1857 case LINUX_POSIX_FADV_DONTNEED: 1858 return (POSIX_FADV_DONTNEED); 1859 case LINUX_POSIX_FADV_NOREUSE: 1860 return (POSIX_FADV_NOREUSE); 1861 default: 1862 return (-1); 1863 } 1864 } 1865 1866 int 1867 linux_fadvise64(struct thread *td, struct linux_fadvise64_args *args) 1868 { 1869 off_t offset; 1870 int advice; 1871 1872 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1873 offset = PAIR32TO64(off_t, args->offset); 1874 #else 1875 offset = args->offset; 1876 #endif 1877 1878 advice = convert_fadvice(args->advice); 1879 if (advice == -1) 1880 return (EINVAL); 1881 return (kern_posix_fadvise(td, args->fd, offset, args->len, advice)); 1882 } 1883 1884 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1885 int 1886 linux_fadvise64_64(struct thread *td, struct linux_fadvise64_64_args *args) 1887 { 1888 off_t len, offset; 1889 int advice; 1890 1891 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1892 len = PAIR32TO64(off_t, args->len); 1893 offset = PAIR32TO64(off_t, args->offset); 1894 #else 1895 len = args->len; 1896 offset = args->offset; 1897 #endif 1898 1899 advice = convert_fadvice(args->advice); 1900 if (advice == -1) 1901 return (EINVAL); 1902 return (kern_posix_fadvise(td, args->fd, offset, len, advice)); 1903 } 1904 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1905 1906 #ifdef LINUX_LEGACY_SYSCALLS 1907 int 1908 linux_pipe(struct thread *td, struct linux_pipe_args *args) 1909 { 1910 int fildes[2]; 1911 int error; 1912 1913 error = kern_pipe(td, fildes, 0, NULL, NULL); 1914 if (error != 0) 1915 return (error); 1916 1917 error = copyout(fildes, args->pipefds, sizeof(fildes)); 1918 if (error != 0) { 1919 (void)kern_close(td, fildes[0]); 1920 (void)kern_close(td, fildes[1]); 1921 } 1922 1923 return (error); 1924 } 1925 #endif 1926 1927 int 1928 linux_pipe2(struct thread *td, struct linux_pipe2_args *args) 1929 { 1930 int fildes[2]; 1931 int error, flags; 1932 1933 if ((args->flags & ~(LINUX_O_NONBLOCK | LINUX_O_CLOEXEC)) != 0) 1934 return (EINVAL); 1935 1936 flags = 0; 1937 if ((args->flags & LINUX_O_NONBLOCK) != 0) 1938 flags |= O_NONBLOCK; 1939 if ((args->flags & LINUX_O_CLOEXEC) != 0) 1940 flags |= O_CLOEXEC; 1941 error = kern_pipe(td, fildes, flags, NULL, NULL); 1942 if (error != 0) 1943 return (error); 1944 1945 error = copyout(fildes, args->pipefds, sizeof(fildes)); 1946 if (error != 0) { 1947 (void)kern_close(td, fildes[0]); 1948 (void)kern_close(td, fildes[1]); 1949 } 1950 1951 return (error); 1952 } 1953 1954 int 1955 linux_dup3(struct thread *td, struct linux_dup3_args *args) 1956 { 1957 int cmd; 1958 intptr_t newfd; 1959 1960 if (args->oldfd == args->newfd) 1961 return (EINVAL); 1962 if ((args->flags & ~LINUX_O_CLOEXEC) != 0) 1963 return (EINVAL); 1964 if (args->flags & LINUX_O_CLOEXEC) 1965 cmd = F_DUP2FD_CLOEXEC; 1966 else 1967 cmd = F_DUP2FD; 1968 1969 newfd = args->newfd; 1970 return (kern_fcntl(td, args->oldfd, cmd, newfd)); 1971 } 1972 1973 int 1974 linux_fallocate(struct thread *td, struct linux_fallocate_args *args) 1975 { 1976 off_t len, offset; 1977 1978 /* 1979 * We emulate only posix_fallocate system call for which 1980 * mode should be 0. 1981 */ 1982 if (args->mode != 0) 1983 return (EOPNOTSUPP); 1984 1985 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1986 len = PAIR32TO64(off_t, args->len); 1987 offset = PAIR32TO64(off_t, args->offset); 1988 #else 1989 len = args->len; 1990 offset = args->offset; 1991 #endif 1992 1993 return (kern_posix_fallocate(td, args->fd, offset, len)); 1994 } 1995 1996 int 1997 linux_copy_file_range(struct thread *td, struct linux_copy_file_range_args 1998 *args) 1999 { 2000 l_loff_t inoff, outoff, *inoffp, *outoffp; 2001 int error, flags; 2002 2003 /* 2004 * copy_file_range(2) on Linux doesn't define any flags (yet), so is 2005 * the native implementation. Enforce it. 2006 */ 2007 if (args->flags != 0) { 2008 linux_msg(td, "copy_file_range unsupported flags 0x%x", 2009 args->flags); 2010 return (EINVAL); 2011 } 2012 flags = 0; 2013 inoffp = outoffp = NULL; 2014 if (args->off_in != NULL) { 2015 error = copyin(args->off_in, &inoff, sizeof(l_loff_t)); 2016 if (error != 0) 2017 return (error); 2018 inoffp = &inoff; 2019 } 2020 if (args->off_out != NULL) { 2021 error = copyin(args->off_out, &outoff, sizeof(l_loff_t)); 2022 if (error != 0) 2023 return (error); 2024 outoffp = &outoff; 2025 } 2026 2027 error = kern_copy_file_range(td, args->fd_in, inoffp, args->fd_out, 2028 outoffp, args->len, flags); 2029 if (error == 0 && args->off_in != NULL) 2030 error = copyout(inoffp, args->off_in, sizeof(l_loff_t)); 2031 if (error == 0 && args->off_out != NULL) 2032 error = copyout(outoffp, args->off_out, sizeof(l_loff_t)); 2033 return (error); 2034 } 2035 2036 #define LINUX_MEMFD_PREFIX "memfd:" 2037 2038 int 2039 linux_memfd_create(struct thread *td, struct linux_memfd_create_args *args) 2040 { 2041 char memfd_name[LINUX_NAME_MAX + 1]; 2042 int error, flags, shmflags, oflags; 2043 2044 /* 2045 * This is our clever trick to avoid the heap allocation to copy in the 2046 * uname. We don't really need to go this far out of our way, but it 2047 * does keep the rest of this function fairly clean as they don't have 2048 * to worry about cleanup on the way out. 2049 */ 2050 error = copyinstr(args->uname_ptr, 2051 memfd_name + sizeof(LINUX_MEMFD_PREFIX) - 1, 2052 LINUX_NAME_MAX - sizeof(LINUX_MEMFD_PREFIX) - 1, NULL); 2053 if (error != 0) { 2054 if (error == ENAMETOOLONG) 2055 error = EINVAL; 2056 return (error); 2057 } 2058 2059 memcpy(memfd_name, LINUX_MEMFD_PREFIX, sizeof(LINUX_MEMFD_PREFIX) - 1); 2060 flags = linux_to_bsd_bits(args->flags, mfd_bitmap, 0); 2061 if ((flags & ~(MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB | 2062 MFD_HUGE_MASK)) != 0) 2063 return (EINVAL); 2064 /* Size specified but no HUGETLB. */ 2065 if ((flags & MFD_HUGE_MASK) != 0 && (flags & MFD_HUGETLB) == 0) 2066 return (EINVAL); 2067 /* We don't actually support HUGETLB. */ 2068 if ((flags & MFD_HUGETLB) != 0) 2069 return (ENOSYS); 2070 oflags = O_RDWR; 2071 shmflags = SHM_GROW_ON_WRITE; 2072 if ((flags & MFD_CLOEXEC) != 0) 2073 oflags |= O_CLOEXEC; 2074 if ((flags & MFD_ALLOW_SEALING) != 0) 2075 shmflags |= SHM_ALLOW_SEALING; 2076 return (kern_shm_open2(td, SHM_ANON, oflags, 0, shmflags, NULL, 2077 memfd_name)); 2078 } 2079 2080 int 2081 linux_splice(struct thread *td, struct linux_splice_args *args) 2082 { 2083 2084 linux_msg(td, "syscall splice not really implemented"); 2085 2086 /* 2087 * splice(2) is documented to return EINVAL in various circumstances; 2088 * returning it instead of ENOSYS should hint the caller to use fallback 2089 * instead. 2090 */ 2091 return (EINVAL); 2092 } 2093