diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c --- a/sys/amd64/amd64/elf_machdep.c +++ b/sys/amd64/amd64/elf_machdep.c @@ -69,7 +69,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS_LA48, @@ -112,7 +111,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS_LA57, @@ -184,7 +182,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_X86_64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec_la48, .interp_newpath = NULL, @@ -196,7 +193,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_X86_64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec_la57, .interp_newpath = NULL, @@ -223,7 +219,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_X86_64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/usr/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec_la48, .interp_newpath = NULL, @@ -238,7 +233,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_X86_64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/lib/ld-kfreebsd-x86-64.so.1", .sysvec = &elf64_freebsd_sysvec_la48, .interp_newpath = NULL, diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c --- a/sys/amd64/linux/linux_sysvec.c +++ b/sys/amd64/linux/linux_sysvec.c @@ -577,7 +577,6 @@ .sv_elf_core_osabi = ELFOSABI_NONE, .sv_elf_core_abi_vendor = LINUX_ABI_VENDOR, .sv_elf_core_prepare_notes = linux64_prepare_notes, - .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS_LA48, @@ -617,7 +616,7 @@ error = linux_map_vdso(p, linux_vdso_obj, linux_vdso_base, LINUX_VDSOPAGE_SIZE, imgp); if (error == 0) - linux_on_exec(p, imgp); + error = linux_on_exec(p, imgp); return (error); } @@ -757,7 +756,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_X86_64, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib64/ld-linux-x86-64.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -769,7 +767,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_X86_64, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib64/ld-linux.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -781,7 +778,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_X86_64, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-musl-x86_64.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -118,18 +118,10 @@ linux_execve(struct thread *td, struct linux_execve_args *args) { struct image_args eargs; - char *path; int error; - if (!LUSECONVPATH(td)) { - error = freebsd32_exec_copyin_args(&eargs, args->path, UIO_USERSPACE, - args->argp, args->envp); - } else { - LCONVPATHEXIST(args->path, &path); - error = freebsd32_exec_copyin_args(&eargs, path, UIO_SYSSPACE, - args->argp, args->envp); - LFREEPATH(path); - } + error = freebsd32_exec_copyin_args(&eargs, args->path, UIO_USERSPACE, + args->argp, args->envp); if (error == 0) error = linux_common_execve(td, &eargs); AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td); diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -794,7 +794,6 @@ .sv_elf_core_osabi = ELFOSABI_NONE, .sv_elf_core_abi_vendor = LINUX_ABI_VENDOR, .sv_elf_core_prepare_notes = linux32_prepare_notes, - .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = LINUX32_MAXUSER, @@ -834,7 +833,7 @@ error = linux_map_vdso(p, linux_vdso_obj, linux_vdso_base, LINUX32_VDSOPAGE_SIZE, imgp); if (error == 0) - linux_on_exec(p, imgp); + error = linux_on_exec(p, imgp); return (error); } @@ -970,7 +969,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-linux.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -982,7 +980,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-linux.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -994,7 +991,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-musl-i386.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -75,7 +75,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -112,7 +111,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_ARM, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c --- a/sys/arm64/arm64/elf32_machdep.c +++ b/sys/arm64/arm64/elf32_machdep.c @@ -94,7 +94,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = elf32_prepare_notes, - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = FREEBSD32_MINUSER, .sv_maxuser = FREEBSD32_MAXUSER, @@ -130,7 +129,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_ARM, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = "/libexec/ld-elf32.so.1", diff --git a/sys/arm64/arm64/elf_machdep.c b/sys/arm64/arm64/elf_machdep.c --- a/sys/arm64/arm64/elf_machdep.c +++ b/sys/arm64/arm64/elf_machdep.c @@ -73,7 +73,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -109,7 +108,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_AARCH64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec, .interp_newpath = NULL, diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c --- a/sys/arm64/linux/linux_sysvec.c +++ b/sys/arm64/linux/linux_sysvec.c @@ -375,7 +375,6 @@ .sv_elf_core_osabi = ELFOSABI_NONE, .sv_elf_core_abi_vendor = LINUX_ABI_VENDOR, .sv_elf_core_prepare_notes = linux64_prepare_notes, - .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -414,7 +413,7 @@ error = linux_map_vdso(p, linux_vdso_obj, linux_vdso_base, LINUX_VDSOPAGE_SIZE, imgp); if (error == 0) - linux_on_exec(p, imgp); + error = linux_on_exec(p, imgp); return (error); } @@ -535,7 +534,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_AARCH64, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib64/ld-linux-x86-64.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c --- a/sys/compat/ia32/ia32_sysvec.c +++ b/sys/compat/ia32/ia32_sysvec.c @@ -116,7 +116,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = elf32_prepare_notes, - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = FREEBSD32_MINUSER, .sv_maxuser = FREEBSD32_MAXUSER, @@ -151,7 +150,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &ia32_freebsd_sysvec, .interp_newpath = "/libexec/ld-elf32.so.1", @@ -167,7 +165,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/usr/libexec/ld-elf.so.1", .sysvec = &ia32_freebsd_sysvec, .interp_newpath = "/libexec/ld-elf32.so.1", @@ -183,7 +180,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/lib/ld.so.1", .sysvec = &ia32_freebsd_sysvec, .brand_note = &elf32_kfreebsd_brandnote, diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h --- a/sys/compat/linux/linux_emul.h +++ b/sys/compat/linux/linux_emul.h @@ -50,11 +50,10 @@ struct linux_emuldata *em_find(struct thread *); -int linux_exec_imgact_try(struct image_params *); void linux_proc_init(struct thread *, struct thread *, bool); void linux_on_exit(struct proc *); void linux_schedtail(struct thread *); -void linux_on_exec(struct proc *, struct image_params *); +int linux_on_exec(struct proc *, struct image_params *); void linux_thread_dtor(struct thread *); int linux_common_execve(struct thread *, struct image_args *); diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c --- a/sys/compat/linux/linux_emul.c +++ b/sys/compat/linux/linux_emul.c @@ -211,41 +211,6 @@ free(pem, M_LINUX); } -/* - * If a Linux binary is exec'ing something, try this image activator - * first. We override standard shell script execution in order to - * be able to modify the interpreter path. We only do this if a Linux - * binary is doing the exec, so we do not create an EXEC module for it. - */ -int -linux_exec_imgact_try(struct image_params *imgp) -{ - const char *head = (const char *)imgp->image_header; - char *rpath; - int error = -1; - - /* - * The interpreter for shell scripts run from a Linux binary needs - * to be located in /compat/linux if possible in order to recursively - * maintain Linux path emulation. - */ - if (((const short *)head)[0] == SHELLMAGIC) { - /* - * Run our normal shell image activator. If it succeeds attempt - * to use the alternate path for the interpreter. If an - * alternate path is found, use our stringspace to store it. - */ - if ((error = exec_shell_imgact(imgp)) == 0) { - linux_emul_convpath(imgp->interpreter_name, UIO_SYSSPACE, - &rpath, 0, AT_FDCWD); - if (rpath != NULL) - imgp->args->fname_buf = - imgp->interpreter_name = rpath; - } - } - return (error); -} - int linux_common_execve(struct thread *td, struct image_args *eargs) { @@ -271,6 +236,10 @@ * FreeBSD binary we destroy Linux emuldata thread & proc entries. */ if (SV_CURPROC_ABI() != SV_ABI_LINUX) { + + /* Clear ABI root directory if set. */ + linux_pwd_onexec_native(td); + PROC_LOCK(p); em = em_find(td); KASSERT(em != NULL, ("proc_exec: thread emuldata not found.\n")); @@ -287,7 +256,7 @@ return (EJUSTRETURN); } -void +int linux_on_exec(struct proc *p, struct image_params *imgp) { struct thread *td; @@ -295,6 +264,7 @@ #if defined(__amd64__) struct linux_pemuldata *pem; #endif + int error; td = curthread; MPASS((imgp->sysent->sv_flags & SV_ABI_MASK) == SV_ABI_LINUX); @@ -327,6 +297,10 @@ continue; linux_proc_init(td, othertd, true); } + + /* Set ABI root directory. */ + if ((error = linux_pwd_onexec(td)) != 0) + return (error); } #if defined(__amd64__) /* @@ -339,6 +313,7 @@ pem->persona |= LINUX_READ_IMPLIES_EXEC; } #endif + return (0); } void diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -99,18 +99,9 @@ int linux_creat(struct thread *td, struct linux_creat_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_openat(td, AT_FDCWD, args->path, UIO_USERSPACE, - O_WRONLY | O_CREAT | O_TRUNC, args->mode)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE, - O_WRONLY | O_CREAT | O_TRUNC, args->mode); - LFREEPATH(path); - return (error); + return (kern_openat(td, AT_FDCWD, args->path, UIO_USERSPACE, + O_WRONLY | O_CREAT | O_TRUNC, args->mode)); } #endif @@ -216,45 +207,20 @@ int linux_openat(struct thread *td, struct linux_openat_args *args) { - char *path; - int dfd, error; + int dfd; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - return (linux_common_open(td, dfd, args->filename, args->flags, - args->mode, UIO_USERSPACE)); - } - if (args->flags & LINUX_O_CREAT) - LCONVPATH_AT(args->filename, &path, 1, dfd); - else - LCONVPATH_AT(args->filename, &path, 0, dfd); - - error = linux_common_open(td, dfd, path, args->flags, args->mode, - UIO_SYSSPACE); - LFREEPATH(path); - return (error); + return (linux_common_open(td, dfd, args->filename, args->flags, + args->mode, UIO_USERSPACE)); } #ifdef LINUX_LEGACY_SYSCALLS int linux_open(struct thread *td, struct linux_open_args *args) { - char *path; - int error; - - if (!LUSECONVPATH(td)) { - return (linux_common_open(td, AT_FDCWD, args->path, args->flags, - args->mode, UIO_USERSPACE)); - } - if (args->flags & LINUX_O_CREAT) - LCONVPATHCREAT(args->path, &path); - else - LCONVPATHEXIST(args->path, &path); - error = linux_common_open(td, AT_FDCWD, path, args->flags, args->mode, - UIO_SYSSPACE); - LFREEPATH(path); - return (error); + return (linux_common_open(td, AT_FDCWD, args->path, args->flags, + args->mode, UIO_USERSPACE)); } #endif @@ -284,17 +250,8 @@ if ((args->flags & LINUX_AT_EMPTY_PATH) != 0) bsd_flags |= AT_EMPTY_PATH; - if (!LUSECONVPATH(td)) { - error = kern_getfhat(td, bsd_flags, fd, args->name, - UIO_USERSPACE, &fh, UIO_SYSSPACE); - } else { - char *path; - - LCONVPATH_AT(args->name, &path, 0, fd); - error = kern_getfhat(td, bsd_flags, fd, path, UIO_SYSSPACE, - &fh, UIO_SYSSPACE); - LFREEPATH(path); - } + error = kern_getfhat(td, bsd_flags, fd, args->name, + UIO_USERSPACE, &fh, UIO_SYSSPACE); if (error != 0) return (error); @@ -645,24 +602,13 @@ int linux_access(struct thread *td, struct linux_access_args *args) { - char *path; - int error; /* Linux convention. */ if (args->amode & ~(F_OK | X_OK | W_OK | R_OK)) return (EINVAL); - if (!LUSECONVPATH(td)) { - error = kern_accessat(td, AT_FDCWD, args->path, UIO_USERSPACE, 0, - args->amode); - } else { - LCONVPATHEXIST(args->path, &path); - error = kern_accessat(td, AT_FDCWD, path, UIO_SYSSPACE, 0, - args->amode); - LFREEPATH(path); - } - - return (error); + return (kern_accessat(td, AT_FDCWD, args->path, UIO_USERSPACE, 0, + args->amode)); } #endif @@ -670,23 +616,14 @@ linux_do_accessat(struct thread *td, int ldfd, const char *filename, int amode, int flags) { - char *path; - int error, dfd; + int dfd; /* Linux convention. */ if (amode & ~(F_OK | X_OK | W_OK | R_OK)) return (EINVAL); dfd = (ldfd == LINUX_AT_FDCWD) ? AT_FDCWD : ldfd; - if (!LUSECONVPATH(td)) { - error = kern_accessat(td, dfd, filename, UIO_USERSPACE, flags, amode); - } else { - LCONVPATHEXIST_AT(filename, &path, dfd); - error = kern_accessat(td, dfd, path, UIO_SYSSPACE, flags, amode); - LFREEPATH(path); - } - - return (error); + return (kern_accessat(td, dfd, filename, UIO_USERSPACE, flags, amode)); } int @@ -722,33 +659,18 @@ int linux_unlink(struct thread *td, struct linux_unlink_args *args) { - char *path; int error; struct stat st; - if (!LUSECONVPATH(td)) { - error = kern_funlinkat(td, AT_FDCWD, args->path, FD_NONE, - UIO_USERSPACE, 0, 0); - if (error == EPERM) { - /* Introduce POSIX noncompliant behaviour of Linux */ - if (kern_statat(td, 0, AT_FDCWD, args->path, - UIO_USERSPACE, &st, NULL) == 0) { - if (S_ISDIR(st.st_mode)) - error = EISDIR; - } - } - } else { - LCONVPATHEXIST(args->path, &path); - error = kern_funlinkat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0, 0); - if (error == EPERM) { - /* Introduce POSIX noncompliant behaviour of Linux */ - if (kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, - NULL) == 0) { - if (S_ISDIR(st.st_mode)) - error = EISDIR; - } + error = kern_funlinkat(td, AT_FDCWD, args->path, FD_NONE, + UIO_USERSPACE, 0, 0); + if (error == EPERM) { + /* Introduce POSIX noncompliant behaviour of Linux */ + if (kern_statat(td, 0, AT_FDCWD, args->path, + UIO_USERSPACE, &st, NULL) == 0) { + if (S_ISDIR(st.st_mode)) + error = EISDIR; } - LFREEPATH(path); } return (error); @@ -778,142 +700,75 @@ int linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args) { - char *path; - int error, dfd; + int dfd; if (args->flag & ~LINUX_AT_REMOVEDIR) return (EINVAL); dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - return (linux_unlinkat_impl(td, UIO_USERSPACE, args->pathname, - dfd, args)); - } - LCONVPATHEXIST_AT(args->pathname, &path, dfd); - error = linux_unlinkat_impl(td, UIO_SYSSPACE, path, dfd, args); - LFREEPATH(path); - return (error); + return (linux_unlinkat_impl(td, UIO_USERSPACE, args->pathname, + dfd, args)); } + int linux_chdir(struct thread *td, struct linux_chdir_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_chdir(td, args->path, UIO_USERSPACE)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_chdir(td, path, UIO_SYSSPACE); - LFREEPATH(path); - return (error); + return (kern_chdir(td, args->path, UIO_USERSPACE)); } #ifdef LINUX_LEGACY_SYSCALLS int linux_chmod(struct thread *td, struct linux_chmod_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_fchmodat(td, AT_FDCWD, args->path, UIO_USERSPACE, - args->mode, 0)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_fchmodat(td, AT_FDCWD, path, UIO_SYSSPACE, args->mode, 0); - LFREEPATH(path); - return (error); + return (kern_fchmodat(td, AT_FDCWD, args->path, UIO_USERSPACE, + args->mode, 0)); } #endif int linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args) { - char *path; - int error, dfd; + int dfd; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - return (kern_fchmodat(td, dfd, args->filename, UIO_USERSPACE, - args->mode, 0)); - } - LCONVPATHEXIST_AT(args->filename, &path, dfd); - error = kern_fchmodat(td, dfd, path, UIO_SYSSPACE, args->mode, 0); - LFREEPATH(path); - return (error); + return (kern_fchmodat(td, dfd, args->filename, UIO_USERSPACE, + args->mode, 0)); } #ifdef LINUX_LEGACY_SYSCALLS int linux_mkdir(struct thread *td, struct linux_mkdir_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_mkdirat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->mode)); - } - LCONVPATHCREAT(args->path, &path); - error = kern_mkdirat(td, AT_FDCWD, path, UIO_SYSSPACE, args->mode); - LFREEPATH(path); - return (error); + return (kern_mkdirat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->mode)); } #endif int linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args) { - char *path; - int error, dfd; + int dfd; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - return (kern_mkdirat(td, dfd, args->pathname, UIO_USERSPACE, args->mode)); - } - LCONVPATHCREAT_AT(args->pathname, &path, dfd); - error = kern_mkdirat(td, dfd, path, UIO_SYSSPACE, args->mode); - LFREEPATH(path); - return (error); + return (kern_mkdirat(td, dfd, args->pathname, UIO_USERSPACE, args->mode)); } #ifdef LINUX_LEGACY_SYSCALLS int linux_rmdir(struct thread *td, struct linux_rmdir_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_frmdirat(td, AT_FDCWD, args->path, FD_NONE, - UIO_USERSPACE, 0)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_frmdirat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0); - LFREEPATH(path); - return (error); + return (kern_frmdirat(td, AT_FDCWD, args->path, FD_NONE, + UIO_USERSPACE, 0)); } int linux_rename(struct thread *td, struct linux_rename_args *args) { - char *from, *to; - int error; - if (!LUSECONVPATH(td)) { - return (kern_renameat(td, AT_FDCWD, args->from, AT_FDCWD, - args->to, UIO_USERSPACE)); - } - LCONVPATHEXIST(args->from, &from); - /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ - error = linux_emul_convpath(args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); - if (to == NULL) { - LFREEPATH(from); - return (error); - } - error = kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, UIO_SYSSPACE); - LFREEPATH(from); - LFREEPATH(to); - return (error); + return (kern_renameat(td, AT_FDCWD, args->from, AT_FDCWD, + args->to, UIO_USERSPACE)); } #endif @@ -934,8 +789,7 @@ int linux_renameat2(struct thread *td, struct linux_renameat2_args *args) { - char *from, *to; - int error, olddfd, newdfd; + int olddfd, newdfd; if (args->flags != 0) { if (args->flags & ~(LINUX_RENAME_EXCHANGE | @@ -960,137 +814,68 @@ olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; - if (!LUSECONVPATH(td)) { - return (kern_renameat(td, olddfd, args->oldname, newdfd, - args->newname, UIO_USERSPACE)); - } - LCONVPATHEXIST_AT(args->oldname, &from, olddfd); - /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ - error = linux_emul_convpath(args->newname, UIO_USERSPACE, &to, 1, newdfd); - if (to == NULL) { - LFREEPATH(from); - return (error); - } - error = kern_renameat(td, olddfd, from, newdfd, to, UIO_SYSSPACE); - LFREEPATH(from); - LFREEPATH(to); - return (error); + return (kern_renameat(td, olddfd, args->oldname, newdfd, + args->newname, UIO_USERSPACE)); } #ifdef LINUX_LEGACY_SYSCALLS int linux_symlink(struct thread *td, struct linux_symlink_args *args) { - char *path, *to; - int error; - if (!LUSECONVPATH(td)) { - return (kern_symlinkat(td, args->path, AT_FDCWD, args->to, - UIO_USERSPACE)); - } - LCONVPATHEXIST(args->path, &path); - /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ - error = linux_emul_convpath(args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); - if (to == NULL) { - LFREEPATH(path); - return (error); - } - error = kern_symlinkat(td, path, AT_FDCWD, to, UIO_SYSSPACE); - LFREEPATH(path); - LFREEPATH(to); - return (error); + return (kern_symlinkat(td, args->path, AT_FDCWD, args->to, + UIO_USERSPACE)); } #endif int linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args) { - char *path, *to; - int error, dfd; + int dfd; dfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; - if (!LUSECONVPATH(td)) { - return (kern_symlinkat(td, args->oldname, dfd, args->newname, - UIO_USERSPACE)); - } - LCONVPATHEXIST(args->oldname, &path); - /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ - error = linux_emul_convpath(args->newname, UIO_USERSPACE, &to, 1, dfd); - if (to == NULL) { - LFREEPATH(path); - return (error); - } - error = kern_symlinkat(td, path, dfd, to, UIO_SYSSPACE); - LFREEPATH(path); - LFREEPATH(to); - return (error); + return (kern_symlinkat(td, args->oldname, dfd, args->newname, + UIO_USERSPACE)); } #ifdef LINUX_LEGACY_SYSCALLS int linux_readlink(struct thread *td, struct linux_readlink_args *args) { - char *name; - int error; if (args->count <= 0) return (EINVAL); - if (!LUSECONVPATH(td)) { - return (kern_readlinkat(td, AT_FDCWD, args->name, UIO_USERSPACE, - args->buf, UIO_USERSPACE, args->count)); - } - LCONVPATHEXIST(args->name, &name); - error = kern_readlinkat(td, AT_FDCWD, name, UIO_SYSSPACE, - args->buf, UIO_USERSPACE, args->count); - LFREEPATH(name); - return (error); + return (kern_readlinkat(td, AT_FDCWD, args->name, UIO_USERSPACE, + args->buf, UIO_USERSPACE, args->count)); } #endif int linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args) { - char *name; - int error, dfd; + int dfd; if (args->bufsiz <= 0) return (EINVAL); dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - return (kern_readlinkat(td, dfd, args->path, UIO_USERSPACE, - args->buf, UIO_USERSPACE, args->bufsiz)); - } - LCONVPATHEXIST_AT(args->path, &name, dfd); - error = kern_readlinkat(td, dfd, name, UIO_SYSSPACE, args->buf, - UIO_USERSPACE, args->bufsiz); - LFREEPATH(name); - return (error); + return (kern_readlinkat(td, dfd, args->path, UIO_USERSPACE, + args->buf, UIO_USERSPACE, args->bufsiz)); } int linux_truncate(struct thread *td, struct linux_truncate_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_truncate(td, args->path, UIO_USERSPACE, args->length)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_truncate(td, path, UIO_SYSSPACE, args->length); - LFREEPATH(path); - return (error); + return (kern_truncate(td, args->path, UIO_USERSPACE, args->length)); } #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) int linux_truncate64(struct thread *td, struct linux_truncate64_args *args) { - char *path; off_t length; - int error; #if defined(__amd64__) && defined(COMPAT_LINUX32) length = PAIR32TO64(off_t, args->length); @@ -1098,13 +883,7 @@ length = args->length; #endif - if (!LUSECONVPATH(td)) { - return (kern_truncate(td, args->path, UIO_USERSPACE, length)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_truncate(td, path, UIO_SYSSPACE, length); - LFREEPATH(path); - return (error); + return (kern_truncate(td, args->path, UIO_USERSPACE, length)); } #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ @@ -1135,33 +914,16 @@ int linux_link(struct thread *td, struct linux_link_args *args) { - char *path, *to; - int error; - if (!LUSECONVPATH(td)) { - return (kern_linkat(td, AT_FDCWD, AT_FDCWD, args->path, args->to, - UIO_USERSPACE, AT_SYMLINK_FOLLOW)); - } - LCONVPATHEXIST(args->path, &path); - /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ - error = linux_emul_convpath(args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); - if (to == NULL) { - LFREEPATH(path); - return (error); - } - error = kern_linkat(td, AT_FDCWD, AT_FDCWD, path, to, UIO_SYSSPACE, - AT_SYMLINK_FOLLOW); - LFREEPATH(path); - LFREEPATH(to); - return (error); + return (kern_linkat(td, AT_FDCWD, AT_FDCWD, args->path, args->to, + UIO_USERSPACE, AT_SYMLINK_FOLLOW)); } #endif int linux_linkat(struct thread *td, struct linux_linkat_args *args) { - char *path, *to; - int error, olddfd, newdfd, flag; + int olddfd, newdfd, flag; if (args->flag & ~(LINUX_AT_SYMLINK_FOLLOW | LINUX_AT_EMPTY_PATH)) return (EINVAL); @@ -1172,21 +934,8 @@ olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; - if (!LUSECONVPATH(td)) { - return (kern_linkat(td, olddfd, newdfd, args->oldname, - args->newname, UIO_USERSPACE, flag)); - } - LCONVPATHEXIST_AT(args->oldname, &path, olddfd); - /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ - error = linux_emul_convpath(args->newname, UIO_USERSPACE, &to, 1, newdfd); - if (to == NULL) { - LFREEPATH(path); - return (error); - } - error = kern_linkat(td, olddfd, newdfd, path, to, UIO_SYSSPACE, flag); - LFREEPATH(path); - LFREEPATH(to); - return (error); + return (kern_linkat(td, olddfd, newdfd, args->oldname, + args->newname, UIO_USERSPACE, flag)); } int @@ -1772,26 +1521,16 @@ int linux_chown(struct thread *td, struct linux_chown_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, - args->uid, args->gid, 0)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid, - args->gid, 0); - LFREEPATH(path); - return (error); + return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, + args->uid, args->gid, 0)); } #endif int linux_fchownat(struct thread *td, struct linux_fchownat_args *args) { - char *path; - int error, dfd, flag, unsupported; + int dfd, flag, unsupported; unsupported = args->flag & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH); if (unsupported != 0) { @@ -1805,33 +1544,17 @@ AT_EMPTY_PATH; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - return (kern_fchownat(td, dfd, args->filename, UIO_USERSPACE, - args->uid, args->gid, flag)); - } - LCONVPATHEXIST_AT(args->filename, &path, dfd); - error = kern_fchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid, - flag); - LFREEPATH(path); - return (error); + return (kern_fchownat(td, dfd, args->filename, UIO_USERSPACE, + args->uid, args->gid, flag)); } #ifdef LINUX_LEGACY_SYSCALLS int linux_lchown(struct thread *td, struct linux_lchown_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td)) { - return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->uid, - args->gid, AT_SYMLINK_NOFOLLOW)); - } - LCONVPATHEXIST(args->path, &path); - error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid, args->gid, - AT_SYMLINK_NOFOLLOW); - LFREEPATH(path); - return (error); + return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->uid, + args->gid, AT_SYMLINK_NOFOLLOW)); } #endif diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c --- a/sys/compat/linux/linux_mib.c +++ b/sys/compat/linux/linux_mib.c @@ -91,10 +91,6 @@ &linux_map_sched_prio, 0, "Map scheduler priorities to Linux priorities " "(not POSIX compliant)"); -int linux_use_emul_path = 1; -SYSCTL_INT(_compat_linux, OID_AUTO, use_emul_path, CTLFLAG_RWTUN, - &linux_use_emul_path, 0, "Use linux.compat.emul_path"); - static bool linux_setid_allowed = true; SYSCTL_BOOL(_compat_linux, OID_AUTO, setid_allowed, CTLFLAG_RWTUN, &linux_setid_allowed, 0, diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -474,7 +474,6 @@ { struct timeval tv[2], *tvp; struct l_utimbuf lut; - char *fname; int error; if (args->times) { @@ -488,16 +487,8 @@ } else tvp = NULL; - if (!LUSECONVPATH(td)) { - error = kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, - tvp, UIO_SYSSPACE); - } else { - LCONVPATHEXIST(args->fname, &fname); - error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE, tvp, - UIO_SYSSPACE); - LFREEPATH(fname); - } - return (error); + return (kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, + tvp, UIO_SYSSPACE)); } #endif @@ -507,7 +498,6 @@ { l_timeval ltv[2]; struct timeval tv[2], *tvp = NULL; - char *fname; int error; if (args->tptr != NULL) { @@ -520,16 +510,8 @@ tvp = tv; } - if (!LUSECONVPATH(td)) { - error = kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, - tvp, UIO_SYSSPACE); - } else { - LCONVPATHEXIST(args->fname, &fname); - error = kern_utimesat(td, AT_FDCWD, fname, UIO_SYSSPACE, - tvp, UIO_SYSSPACE); - LFREEPATH(fname); - } - return (error); + return (kern_utimesat(td, AT_FDCWD, args->fname, UIO_USERSPACE, + tvp, UIO_SYSSPACE)); } #endif @@ -562,8 +544,7 @@ linux_common_utimensat(struct thread *td, int ldfd, const char *pathname, struct timespec *timesp, int lflags) { - char *path = NULL; - int error, dfd, flags = 0; + int dfd, flags = 0; dfd = (ldfd == LINUX_AT_FDCWD) ? AT_FDCWD : ldfd; @@ -584,27 +565,14 @@ if (lflags & LINUX_AT_EMPTY_PATH) flags |= AT_EMPTY_PATH; - if (!LUSECONVPATH(td)) { - if (pathname != NULL) { - return (kern_utimensat(td, dfd, pathname, - UIO_USERSPACE, timesp, UIO_SYSSPACE, flags)); - } - } - if (pathname != NULL) - LCONVPATHEXIST_AT(pathname, &path, dfd); - else if (lflags != 0) - return (EINVAL); + return (kern_utimensat(td, dfd, pathname, + UIO_USERSPACE, timesp, UIO_SYSSPACE, flags)); - if (path == NULL) - error = kern_futimens(td, dfd, timesp, UIO_SYSSPACE); - else { - error = kern_utimensat(td, dfd, path, UIO_SYSSPACE, timesp, - UIO_SYSSPACE, flags); - LFREEPATH(path); - } + if (lflags != 0) + return (EINVAL); - return (error); + return (kern_futimens(td, dfd, timesp, UIO_SYSSPACE)); } int @@ -695,7 +663,6 @@ { l_timeval ltv[2]; struct timeval tv[2], *tvp = NULL; - char *fname; int error, dfd; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; @@ -710,16 +677,8 @@ tvp = tv; } - if (!LUSECONVPATH(td)) { - error = kern_utimesat(td, dfd, args->filename, UIO_USERSPACE, - tvp, UIO_SYSSPACE); - } else { - LCONVPATHEXIST_AT(args->filename, &fname, dfd); - error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, - tvp, UIO_SYSSPACE); - LFREEPATH(fname); - } - return (error); + return (kern_utimesat(td, dfd, args->filename, UIO_USERSPACE, + tvp, UIO_SYSSPACE)); } #endif @@ -877,30 +836,18 @@ int linux_mknod(struct thread *td, struct linux_mknod_args *args) { - char *path; int error; - enum uio_seg seg; - bool convpath; - - convpath = LUSECONVPATH(td); - if (!convpath) { - path = args->path; - seg = UIO_USERSPACE; - } else { - LCONVPATHCREAT(args->path, &path); - seg = UIO_SYSSPACE; - } switch (args->mode & S_IFMT) { case S_IFIFO: case S_IFSOCK: - error = kern_mkfifoat(td, AT_FDCWD, path, seg, + error = kern_mkfifoat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->mode); break; case S_IFCHR: case S_IFBLK: - error = kern_mknodat(td, AT_FDCWD, path, seg, + error = kern_mknodat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->mode, args->dev); break; @@ -912,7 +859,7 @@ args->mode |= S_IFREG; /* FALLTHROUGH */ case S_IFREG: - error = kern_openat(td, AT_FDCWD, path, seg, + error = kern_openat(td, AT_FDCWD, args->path, UIO_USERSPACE, O_WRONLY | O_CREAT | O_TRUNC, args->mode); if (error == 0) kern_close(td, td->td_retval[0]); @@ -922,8 +869,6 @@ error = EINVAL; break; } - if (convpath) - LFREEPATH(path); return (error); } #endif @@ -931,32 +876,21 @@ int linux_mknodat(struct thread *td, struct linux_mknodat_args *args) { - char *path; int error, dfd; - enum uio_seg seg; - bool convpath; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - convpath = LUSECONVPATH(td); - if (!convpath) { - path = __DECONST(char *, args->filename); - seg = UIO_USERSPACE; - } else { - LCONVPATHCREAT_AT(args->filename, &path, dfd); - seg = UIO_SYSSPACE; - } - switch (args->mode & S_IFMT) { case S_IFIFO: case S_IFSOCK: - error = kern_mkfifoat(td, dfd, path, seg, args->mode); + error = kern_mkfifoat(td, dfd, args->filename, + UIO_USERSPACE, args->mode); break; case S_IFCHR: case S_IFBLK: - error = kern_mknodat(td, dfd, path, seg, args->mode, - args->dev); + error = kern_mknodat(td, dfd, args->filename, + UIO_USERSPACE, args->mode, args->dev); break; case S_IFDIR: @@ -967,7 +901,7 @@ args->mode |= S_IFREG; /* FALLTHROUGH */ case S_IFREG: - error = kern_openat(td, dfd, path, seg, + error = kern_openat(td, dfd, args->filename, UIO_USERSPACE, O_WRONLY | O_CREAT | O_TRUNC, args->mode); if (error == 0) kern_close(td, td->td_retval[0]); @@ -977,8 +911,6 @@ error = EINVAL; break; } - if (convpath) - LFREEPATH(path); return (error); } @@ -2628,20 +2560,12 @@ linux_execve(struct thread *td, struct linux_execve_args *args) { struct image_args eargs; - char *path; int error; LINUX_CTR(execve); - if (!LUSECONVPATH(td)) { - error = exec_copyin_args(&eargs, args->path, UIO_USERSPACE, - args->argp, args->envp); - } else { - LCONVPATHEXIST(args->path, &path); - error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp, - args->envp); - LFREEPATH(path); - } + error = exec_copyin_args(&eargs, args->path, UIO_USERSPACE, + args->argp, args->envp); if (error == 0) error = linux_common_execve(td, &eargs); AUDIT_SYSCALL_EXIT(error == EJUSTRETURN ? 0 : error, td); diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -228,16 +228,9 @@ linux_newstat(struct thread *td, struct linux_newstat_args *args) { struct stat buf; - char *path; int error; - if (!LUSECONVPATH(td)) { - error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf); - } else { - LCONVPATHEXIST(args->path, &path); - error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf); - LFREEPATH(path); - } + error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf); if (error) return (error); return (newstat_copyout(&buf, args->buf)); @@ -247,16 +240,9 @@ linux_newlstat(struct thread *td, struct linux_newlstat_args *args) { struct stat sb; - char *path; int error; - if (!LUSECONVPATH(td)) { - error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &sb); - } else { - LCONVPATHEXIST(args->path, &path); - error = linux_kern_lstat(td, path, UIO_SYSSPACE, &sb); - LFREEPATH(path); - } + error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &sb); if (error) return (error); return (newstat_copyout(&sb, args->buf)); @@ -310,16 +296,9 @@ linux_stat(struct thread *td, struct linux_stat_args *args) { struct stat buf; - char *path; int error; - if (!LUSECONVPATH(td)) { - error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf); - } else { - LCONVPATHEXIST(args->path, &path); - error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf); - LFREEPATH(path); - } + error = linux_kern_stat(td, args->path, UIO_USERSPACE, &buf); if (error) { return (error); } @@ -330,16 +309,9 @@ linux_lstat(struct thread *td, struct linux_lstat_args *args) { struct stat buf; - char *path; int error; - if (!LUSECONVPATH(td)) { - error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &buf); - } else { - LCONVPATHEXIST(args->path, &path); - error = linux_kern_lstat(td, path, UIO_SYSSPACE, &buf); - LFREEPATH(path); - } + error = linux_kern_lstat(td, args->path, UIO_USERSPACE, &buf); if (error) { return (error); } @@ -458,18 +430,10 @@ { struct l_statfs linux_statfs; struct statfs *bsd_statfs; - char *path; int error; - if (!LUSECONVPATH(td)) { - bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); - error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs); - } else { - LCONVPATHEXIST(args->path, &path); - bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); - error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs); - LFREEPATH(path); - } + bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); + error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs); if (error == 0) error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs); free(bsd_statfs, M_STATFS); @@ -503,21 +467,13 @@ { struct l_statfs64 linux_statfs; struct statfs *bsd_statfs; - char *path; int error; if (args->bufsize != sizeof(struct l_statfs64)) return (EINVAL); - if (!LUSECONVPATH(td)) { - bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); - error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs); - } else { - LCONVPATHEXIST(args->path, &path); - bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); - error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs); - LFREEPATH(path); - } + bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK); + error = kern_statfs(td, args->path, UIO_USERSPACE, bsd_statfs); if (error == 0) bsd_to_linux_statfs64(bsd_statfs, &linux_statfs); free(bsd_statfs, M_STATFS); @@ -621,16 +577,9 @@ linux_stat64(struct thread *td, struct linux_stat64_args *args) { struct stat buf; - char *filename; int error; - if (!LUSECONVPATH(td)) { - error = linux_kern_stat(td, args->filename, UIO_USERSPACE, &buf); - } else { - LCONVPATHEXIST(args->filename, &filename); - error = linux_kern_stat(td, filename, UIO_SYSSPACE, &buf); - LFREEPATH(filename); - } + error = linux_kern_stat(td, args->filename, UIO_USERSPACE, &buf); if (error) return (error); return (stat64_copyout(&buf, args->statbuf)); @@ -640,16 +589,9 @@ linux_lstat64(struct thread *td, struct linux_lstat64_args *args) { struct stat sb; - char *filename; int error; - if (!LUSECONVPATH(td)) { - error = linux_kern_lstat(td, args->filename, UIO_USERSPACE, &sb); - } else { - LCONVPATHEXIST(args->filename, &filename); - error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb); - LFREEPATH(filename); - } + error = linux_kern_lstat(td, args->filename, UIO_USERSPACE, &sb); if (error) return (error); return (stat64_copyout(&sb, args->statbuf)); @@ -672,7 +614,6 @@ int linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args) { - char *path; int error, dfd, flag, unsupported; struct stat buf; @@ -687,14 +628,8 @@ AT_EMPTY_PATH : 0; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - error = linux_kern_statat(td, flag, dfd, args->pathname, - UIO_USERSPACE, &buf); - } else { - LCONVPATHEXIST_AT(args->pathname, &path, dfd); - error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf); - LFREEPATH(path); - } + error = linux_kern_statat(td, flag, dfd, args->pathname, + UIO_USERSPACE, &buf); if (error == 0) error = stat64_copyout(&buf, args->statbuf); @@ -706,7 +641,6 @@ int linux_newfstatat(struct thread *td, struct linux_newfstatat_args *args) { - char *path; int error, dfd, flag, unsupported; struct stat buf; @@ -722,14 +656,8 @@ AT_EMPTY_PATH : 0; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; - if (!LUSECONVPATH(td)) { - error = linux_kern_statat(td, flag, dfd, args->pathname, - UIO_USERSPACE, &buf); - } else { - LCONVPATHEXIST_AT(args->pathname, &path, dfd); - error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf); - LFREEPATH(path); - } + error = linux_kern_statat(td, flag, dfd, args->pathname, + UIO_USERSPACE, &buf); if (error == 0) error = newstat_copyout(&buf, args->statbuf); @@ -780,7 +708,6 @@ int linux_statx(struct thread *td, struct linux_statx_args *args) { - char *path; int error, dirfd, flags, unsupported; struct stat buf; @@ -797,14 +724,8 @@ AT_EMPTY_PATH : 0; dirfd = (args->dirfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dirfd; - if (!LUSECONVPATH(td)) { - error = linux_kern_statat(td, flags, dirfd, args->pathname, - UIO_USERSPACE, &buf); - } else { - LCONVPATHEXIST_AT(args->pathname, &path, dirfd); - error = linux_kern_statat(td, flags, dirfd, path, UIO_SYSSPACE, &buf); - LFREEPATH(path); - } + error = linux_kern_statat(td, flags, dirfd, args->pathname, + UIO_USERSPACE, &buf); if (error == 0) error = statx_copyout(&buf, args->statxbuf); diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -72,52 +72,17 @@ int linux_chown16(struct thread *td, struct linux_chown16_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td) && !SDT_PROBES_ENABLED()) { - error = kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, - CAST_NOCHG(args->uid), CAST_NOCHG(args->gid), 0); - } else { - LCONVPATHEXIST(args->path, &path); - /* - * The DTrace probes have to be after the LCONVPATHEXIST, as - * LCONVPATHEXIST may return on its own and we do not want to - * have a stray entry without the corresponding return. - */ - LIN_SDT_PROBE1(uid16, linux_chown16, conv_path, path); - - error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, - CAST_NOCHG(args->uid), CAST_NOCHG(args->gid), 0); - LFREEPATH(path); - } - return (error); + return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, + CAST_NOCHG(args->uid), CAST_NOCHG(args->gid), 0)); } int linux_lchown16(struct thread *td, struct linux_lchown16_args *args) { - char *path; - int error; - if (!LUSECONVPATH(td) && !SDT_PROBES_ENABLED()) { - error = kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, - CAST_NOCHG(args->uid), CAST_NOCHG(args->gid), AT_SYMLINK_NOFOLLOW); - } else { - LCONVPATHEXIST(args->path, &path); - - /* - * The DTrace probes have to be after the LCONVPATHEXIST, as - * LCONVPATHEXIST may return on its own and we do not want to - * have a stray entry without the corresponding return. - */ - LIN_SDT_PROBE1(uid16, linux_lchown16, conv_path, path); - - error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, - CAST_NOCHG(args->uid), CAST_NOCHG(args->gid), AT_SYMLINK_NOFOLLOW); - LFREEPATH(path); - } - return (error); + return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, + CAST_NOCHG(args->uid), CAST_NOCHG(args->gid), AT_SYMLINK_NOFOLLOW)); } int diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h --- a/sys/compat/linux/linux_util.h +++ b/sys/compat/linux/linux_util.h @@ -42,30 +42,9 @@ MALLOC_DECLARE(M_EPOLL); extern char linux_emul_path[]; -extern int linux_use_emul_path; -int linux_emul_convpath(const char *, enum uio_seg, char **, int, int); - -#define LUSECONVPATH(td) atomic_load_int(&linux_use_emul_path) - -#define LCONVPATH_AT(upath, pathp, i, dfd) \ - do { \ - int _error; \ - \ - _error = linux_emul_convpath(upath, UIO_USERSPACE, \ - pathp, i, dfd); \ - if (*(pathp) == NULL) \ - return (_error); \ - } while (0) - -#define LCONVPATH(upath, pathp, i) \ - LCONVPATH_AT(upath, pathp, i, AT_FDCWD) - -#define LCONVPATHEXIST(upath, pathp) LCONVPATH(upath, pathp, 0) -#define LCONVPATHEXIST_AT(upath, pathp, dfd) LCONVPATH_AT(upath, pathp, 0, dfd) -#define LCONVPATHCREAT(upath, pathp) LCONVPATH(upath, pathp, 1) -#define LCONVPATHCREAT_AT(upath, pathp, dfd) LCONVPATH_AT(upath, pathp, 1, dfd) -#define LFREEPATH(path) free(path, M_TEMP) +int linux_pwd_onexec(struct thread *); +void linux_pwd_onexec_native(struct thread *); #define DUMMY(s) \ LIN_SDT_PROBE_DEFINE0(dummy, s, not_implemented); \ diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c --- a/sys/compat/linux/linux_util.c +++ b/sys/compat/linux/linux_util.c @@ -77,23 +77,38 @@ linux_emul_path, sizeof(linux_emul_path), "Linux runtime environment path"); -/* - * Search an alternate path before passing pathname arguments on to - * system calls. Useful for keeping a separate 'emulation tree'. - * - * If cflag is set, we check if an attempt can be made to create the - * named file, i.e. we check if the directory it should be in exists. - */ int -linux_emul_convpath(const char *path, enum uio_seg pathseg, - char **pbuf, int cflag, int dfd) +linux_pwd_onexec(struct thread *td) { - int retval; + struct nameidata nd; + struct pwd *pwd; + int error; - retval = kern_alternate_path(linux_emul_path, path, pathseg, pbuf, - cflag, dfd); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path); + error = namei(&nd); + if (error != 0) { + /* + * Do not bother if we are in chroot or jail. + */ + pwd = pwd_hold(td); + if (pwd->pwd_rdir != rootvnode) { + pwd_drop(pwd); + return (0); + } + pwd_drop(pwd); + return (error); + } + NDFREE_PNBUF(&nd); + pwd_exec(td, nd.ni_vp); + vrele(nd.ni_vp); + return (0); +} + +void +linux_pwd_onexec_native(struct thread *td) +{ - return (retval); + pwd_exec(td, NULL); } void diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c --- a/sys/i386/i386/elf_machdep.c +++ b/sys/i386/i386/elf_machdep.c @@ -64,7 +64,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -99,7 +98,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, @@ -115,7 +113,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/usr/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, @@ -131,7 +128,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_386, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/lib/ld.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -715,7 +715,6 @@ vm_offset_t vmaddr; unsigned long file_offset; unsigned long bss_size; - char *library; ssize_t aresid; int error; bool locked, opened, textset; @@ -726,17 +725,9 @@ textset = false; opened = false; - if (!LUSECONVPATH(td)) { - NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, - UIO_USERSPACE, args->library); - error = namei(&ni); - } else { - LCONVPATHEXIST(args->library, &library); - NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, - UIO_SYSSPACE, library); - error = namei(&ni); - LFREEPATH(library); - } + NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, + UIO_USERSPACE, args->library); + error = namei(&ni); if (error) goto cleanup; diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -584,7 +584,6 @@ .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux a.out", .sv_coredump = NULL, - .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -626,7 +625,6 @@ .sv_elf_core_osabi = ELFOSABI_NONE, .sv_elf_core_abi_vendor = LINUX_ABI_VENDOR, .sv_elf_core_prepare_notes = __linuxN(prepare_notes), - .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -667,7 +665,7 @@ error = linux_map_vdso(p, linux_vdso_obj, linux_vdso_base, LINUX_VDSOPAGE_SIZE, imgp); if (error == 0) - linux_on_exec(p, imgp); + error = linux_on_exec(p, imgp); return (error); } @@ -803,7 +801,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-linux.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -815,7 +812,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-linux.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -827,7 +823,6 @@ .brand = ELFOSABI_LINUX, .machine = EM_386, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-musl-i386.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -82,7 +82,6 @@ .sv_szsigcode = &szsigcode, .sv_name = "FreeBSD a.out", .sv_coredump = NULL, - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = AOUT32_USRSTACK, @@ -132,7 +131,6 @@ .sv_szsigcode = &aout_szsigcode, .sv_name = "FreeBSD a.out", .sv_coredump = NULL, - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = AOUT32_MINUSER, .sv_maxuser = AOUT32_USRSTACK, diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1069,20 +1069,8 @@ __elfN(load_interp)(struct image_params *imgp, const Elf_Brandinfo *brand_info, const char *interp, u_long *addr, u_long *entry) { - char *path; int error; - if (brand_info->emul_path != NULL && - brand_info->emul_path[0] != '\0') { - path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - snprintf(path, MAXPATHLEN, "%s%s", - brand_info->emul_path, interp); - error = __elfN(load_file)(imgp->proc, path, addr, entry); - free(path, M_TEMP); - if (error == 0) - return (0); - } - if (brand_info->interp_newpath != NULL && (brand_info->interp_path == NULL || strcmp(interp, brand_info->interp_path) == 0)) { diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -422,7 +422,6 @@ .sv_szsigcode = NULL, .sv_name = "null", .sv_coredump = NULL, - .sv_imgact_try = NULL, .sv_minsigstksz = 0, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -3839,6 +3839,11 @@ vrefact(oldpwd->pwd_jdir); newpwd->pwd_jdir = oldpwd->pwd_jdir; } + + if (newpwd->pwd_adir == NULL && oldpwd->pwd_adir != NULL) { + vrefact(oldpwd->pwd_adir); + newpwd->pwd_adir = oldpwd->pwd_adir; + } } struct pwd * @@ -3930,6 +3935,8 @@ vrele(pwd->pwd_rdir); if (pwd->pwd_jdir != NULL) vrele(pwd->pwd_jdir); + if (pwd->pwd_adir != NULL) + vrele(pwd->pwd_adir); uma_zfree_smr(pwd_zone, pwd); } @@ -3967,6 +3974,8 @@ vrefact(vp); newpwd->pwd_rdir = vp; + vrefact(vp); + newpwd->pwd_adir = vp; if (oldpwd->pwd_jdir == NULL) { vrefact(vp); newpwd->pwd_jdir = vp; @@ -3997,6 +4006,40 @@ pwd_drop(oldpwd); } +/* + * Process is transitioning to/from a non-native ABI. + */ +void +pwd_exec(struct thread *td, struct vnode *vp) +{ + struct pwddesc *pdp; + struct pwd *newpwd, *oldpwd; + + newpwd = pwd_alloc(); + pdp = td->td_proc->p_pd; + PWDDESC_XLOCK(pdp); + oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp); + if (vp != NULL) { + /* + * Native process to a non-native ABI. + */ + + vrefact(vp); + newpwd->pwd_adir = vp; + } else { + /* + * Non-native process to the native ABI. + */ + + vrefact(oldpwd->pwd_rdir); + newpwd->pwd_adir = oldpwd->pwd_rdir; + } + pwd_fill(oldpwd, newpwd); + pwd_set(pdp, newpwd); + PWDDESC_XUNLOCK(pdp); + pwd_drop(oldpwd); +} + /* * jail_attach(2) changes both root and working directories. */ @@ -4030,6 +4073,8 @@ vrefact(vp); newpwd->pwd_jdir = vp; } + vrefact(vp); + newpwd->pwd_adir = vp; pwd_fill(oldpwd, newpwd); pwd_set(pdp, newpwd); PWDDESC_XUNLOCK(pdp); @@ -4046,7 +4091,8 @@ pdp = curproc->p_pd; PWDDESC_XLOCK(pdp); oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp); - if (oldpwd->pwd_cdir != NULL && oldpwd->pwd_rdir != NULL) { + if (oldpwd->pwd_cdir != NULL && oldpwd->pwd_rdir != NULL && + oldpwd->pwd_adir != NULL) { PWDDESC_XUNLOCK(pdp); return; } @@ -4064,6 +4110,10 @@ vrefact(rootvnode); newpwd->pwd_rdir = rootvnode; } + if (newpwd->pwd_adir == NULL) { + vrefact(rootvnode); + newpwd->pwd_adir = rootvnode; + } pwd_set(pdp, newpwd); PWDDESC_XUNLOCK(pdp); pwd_drop(oldpwd); @@ -4084,6 +4134,8 @@ newpwd->pwd_cdir = rootvnode; vrefact(rootvnode); newpwd->pwd_rdir = rootvnode; + vrefact(rootvnode); + newpwd->pwd_adir = rootvnode; pwd_fill(oldpwd, newpwd); pwd_set(pdp, newpwd); PWDDESC_XUNLOCK(pdp); @@ -4119,7 +4171,8 @@ if (oldpwd == NULL || (oldpwd->pwd_cdir != olddp && oldpwd->pwd_rdir != olddp && - oldpwd->pwd_jdir != olddp)) { + oldpwd->pwd_jdir != olddp && + oldpwd->pwd_adir != olddp)) { PWDDESC_XUNLOCK(pdp); pddrop(pdp); continue; @@ -4136,6 +4189,10 @@ vrefact(newdp); newpwd->pwd_jdir = newdp; } + if (oldpwd->pwd_adir == olddp) { + vrefact(newdp); + newpwd->pwd_adir = newdp; + } pwd_fill(oldpwd, newpwd); pwd_set(pdp, newpwd); PWDDESC_XUNLOCK(pdp); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -390,7 +390,6 @@ uintptr_t stack_base; struct image_params image_params, *imgp; struct vattr attr; - int (*img_first)(struct image_params *); struct pargs *oldargs = NULL, *newargs = NULL; struct sigacts *oldsigacts = NULL, *newsigacts = NULL; #ifdef KTRACE @@ -644,25 +643,15 @@ } /* The new credentials are installed into the process later. */ - /* - * If the current process has a special image activator it - * wants to try first, call it. For example, emulating shell - * scripts differently. - */ - error = -1; - if ((img_first = imgp->proc->p_sysent->sv_imgact_try) != NULL) - error = img_first(imgp); - /* * Loop through the list of image activators, calling each one. * An activator returns -1 if there is no match, 0 on success, * and an error otherwise. */ + error = -1; for (i = 0; error == -1 && execsw[i]; ++i) { - if (execsw[i]->ex_imgact == NULL || - execsw[i]->ex_imgact == img_first) { + if (execsw[i]->ex_imgact == NULL) continue; - } error = (*execsw[i]->ex_imgact)(imgp); } diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -4349,7 +4349,7 @@ (NC_NOMAKEENTRY | NC_KEEPPOSENTRY | LOCKLEAF | LOCKPARENT | WANTPARENT | \ FAILIFEXISTS | FOLLOW | EMPTYPATH | LOCKSHARED | WILLBEDIR | \ ISOPEN | NOMACCHECK | AUDITVNODE1 | AUDITVNODE2 | NOCAPCHECK | OPENREAD | \ - OPENWRITE | WANTIOCTLCAPS) + OPENWRITE | WANTIOCTLCAPS | ISRESTARTED) #define CACHE_FPL_INTERNAL_CN_FLAGS \ (ISDOTDOT | MAKEENTRY | ISLASTCN) @@ -6238,7 +6238,7 @@ fpl.pwd = pwdp; pwd = pwd_get_smr(); *(fpl.pwd) = pwd; - ndp->ni_rootdir = pwd->pwd_rdir; + namei_setup_rootdir(ndp, cnp, pwd); ndp->ni_topdir = pwd->pwd_jdir; if (cnp->cn_pnbuf[0] == '/') { diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -81,6 +81,13 @@ #define NDVALIDATE(ndp) #endif +#define NDRESTART(ndp) do { \ + NDREINIT_DBG(ndp); \ + ndp->ni_resflags = 0; \ + ndp->ni_cnd.cn_flags &= ~NAMEI_INTERNAL_FLAGS; \ + ndp->ni_cnd.cn_flags |= ISRESTARTED; \ +} while (0) + SDT_PROVIDER_DEFINE(vfs); SDT_PROBE_DEFINE4(vfs, namei, lookup, entry, "struct vnode *", "char *", "unsigned long", "bool"); @@ -334,7 +341,7 @@ * The reference on ni_rootdir is acquired in the block below to avoid * back-to-back atomics for absolute lookups. */ - ndp->ni_rootdir = pwd->pwd_rdir; + namei_setup_rootdir(ndp, cnp, pwd); ndp->ni_topdir = pwd->pwd_jdir; if (cnp->cn_pnbuf[0] == '/') { @@ -592,6 +599,7 @@ MPASS(ndp->ni_startdir == NULL || ndp->ni_startdir->v_type == VDIR || ndp->ni_startdir->v_type == VBAD); +restart: ndp->ni_lcf = 0; ndp->ni_loopcnt = 0; ndp->ni_vp = NULL; @@ -626,6 +634,12 @@ case CACHE_FPL_STATUS_HANDLED: if (error == 0) NDVALIDATE(ndp); + else if (__predict_false(pwd->pwd_adir != pwd->pwd_rdir && + (cnp->cn_flags & ISRESTARTED) == 0)) { + namei_cleanup_cnp(cnp); + NDRESTART(ndp); + goto restart; + } return (error); case CACHE_FPL_STATUS_PARTIAL: TAILQ_INIT(&ndp->ni_cap_tracker); @@ -666,8 +680,18 @@ for (;;) { ndp->ni_startdir = dp; error = vfs_lookup(ndp); - if (error != 0) - goto out; + if (error != 0) { + if (__predict_false(pwd->pwd_adir != pwd->pwd_rdir && + error == ENOENT && + (cnp->cn_flags & ISRESTARTED) == 0)) { + nameicap_cleanup(ndp); + pwd_drop(pwd); + namei_cleanup_cnp(cnp); + NDRESTART(ndp); + goto restart; + } else + goto out; + } /* * If not a symbolic link, we're done. diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf32_machdep.c --- a/sys/powerpc/powerpc/elf32_machdep.c +++ b/sys/powerpc/powerpc/elf32_machdep.c @@ -102,7 +102,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_stackprot = VM_PROT_ALL, @@ -148,7 +147,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_PPC, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, #ifdef __powerpc64__ @@ -168,7 +166,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_PPC, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/usr/libexec/ld-elf.so.1", .sysvec = &elf32_freebsd_sysvec, .interp_newpath = NULL, diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf64_machdep.c --- a/sys/powerpc/powerpc/elf64_machdep.c +++ b/sys/powerpc/powerpc/elf64_machdep.c @@ -75,7 +75,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -118,7 +117,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, @@ -158,7 +156,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_PPC64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec_v1, .interp_newpath = NULL, @@ -175,7 +172,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_PPC64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec_v2, .interp_newpath = NULL, @@ -192,7 +188,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_PPC64, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/usr/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec_v1, .interp_newpath = NULL, diff --git a/sys/riscv/riscv/elf_machdep.c b/sys/riscv/riscv/elf_machdep.c --- a/sys/riscv/riscv/elf_machdep.c +++ b/sys/riscv/riscv/elf_machdep.c @@ -75,7 +75,6 @@ .sv_elf_core_osabi = ELFOSABI_FREEBSD, .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, .sv_elf_core_prepare_notes = __elfN(prepare_notes), - .sv_imgact_try = NULL, .sv_minsigstksz = MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = 0, /* Filled in during boot. */ @@ -121,7 +120,6 @@ .brand = ELFOSABI_FREEBSD, .machine = EM_RISCV, .compat_3_brand = "FreeBSD", - .emul_path = NULL, .interp_path = "/libexec/ld-elf.so.1", .sysvec = &elf64_freebsd_sysvec, .interp_newpath = NULL, diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -89,6 +89,8 @@ /* * This struct is copy-on-write and allocated from an SMR zone. * All fields are constant after initialization apart from the reference count. + * The ABI root directory is initialized as the root directory and changed + * during process transiting to or from non-native ABI. * * Check pwd_* routines for usage. */ @@ -97,6 +99,7 @@ struct vnode *pwd_cdir; /* current directory */ struct vnode *pwd_rdir; /* root directory */ struct vnode *pwd_jdir; /* jail root directory */ + struct vnode *pwd_adir; /* abi root directory */ }; typedef SMR_POINTER(struct pwd *) smrpwd_t; @@ -345,6 +348,7 @@ void pwd_chdir(struct thread *td, struct vnode *vp); int pwd_chroot(struct thread *td, struct vnode *vp); int pwd_chroot_chdir(struct thread *td, struct vnode *vp); +void pwd_exec(struct thread *td, struct vnode *vp); void pwd_ensure_dirs(void); void pwd_set_rootvnode(void); diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h --- a/sys/sys/imgact_elf.h +++ b/sys/sys/imgact_elf.h @@ -83,7 +83,6 @@ int brand; int machine; const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */ - const char *emul_path; const char *interp_path; struct sysentvec *sysvec; const char *interp_newpath; diff --git a/sys/sys/namei.h b/sys/sys/namei.h --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -159,7 +159,7 @@ * Namei parameter descriptors. */ #define RDONLY 0x00000200 /* lookup with read-only semantics */ -/* UNUSED 0x00000400 */ +#define ISRESTARTED 0x00000400 /* restarted namei */ /* UNUSED 0x00000800 */ #define ISWHITEOUT 0x00001000 /* found whiteout */ #define DOWHITEOUT 0x00002000 /* do whiteouts */ @@ -187,7 +187,7 @@ */ #define NAMEI_INTERNAL_FLAGS \ (NOEXECCHECK | MAKEENTRY | ISSYMLINK | ISLASTCN | ISDOTDOT | \ - TRAILINGSLASH) + TRAILINGSLASH | ISRESTARTED) /* * Namei results flags @@ -293,6 +293,13 @@ int vfs_lookup(struct nameidata *ndp); int vfs_relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, bool refstart); + +#define namei_setup_rootdir(ndp, cnp, pwd) do { \ + if (__predict_true((cnp->cn_flags & ISRESTARTED) == 0)) \ + ndp->ni_rootdir = pwd->pwd_adir; \ + else \ + ndp->ni_rootdir = pwd->pwd_rdir; \ +} while (0) #endif /* diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -117,7 +117,6 @@ const char *sv_elf_core_abi_vendor; void (*sv_elf_core_prepare_notes)(struct thread *, struct note_info_list *, size_t *); - int (*sv_imgact_try)(struct image_params *); int (*sv_copyout_auxargs)(struct image_params *, uintptr_t); int sv_minsigstksz; /* minimum signal stack size */