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