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