From nobody Wed Mar 1 08:43:07 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4PRSRv3Fmjz3vbjx; Wed, 1 Mar 2023 08:43:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4PRSRv2qR1z45pt; Wed, 1 Mar 2023 08:43:07 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677660187; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QaKBEgM45Cu5iR1ToFp4d7tGDMubpUv7hDvnV6++/lk=; b=kzjC/8PvbrTtPwUGnEq6rUjDHUKz0T9QAy8NjRtnL1MD0YYy6ykjTaaWNEXCArh8AjjyVL hzjyBr1AezFmCuM8w5rpyqChn6dpOhZoHNDJU2rjSt14cJsuflr+bnCANsOMceJoWA15bb Ks/UXBdsPyobtuanycAjRcJ6cbf0qJRDSDZmIBYDCGCPo4IUqqC/V97Vs1fx3CUwmJx9wM eI2xkvvI/4duqSnqKOry/nRU8uhztN5Pqqea5vdb3Fn8OL3/RkmwMe1d+sFacFQGmqDqnk wEjlZy9i5VGNdw1omAItMtJcFoG8HDSE4sJ3nicHVz3mNeCqnnRQLG+knS2+eg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1677660187; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QaKBEgM45Cu5iR1ToFp4d7tGDMubpUv7hDvnV6++/lk=; b=JWl5FrWg0PN6+qLAY0wZr0Og7H9ZsTdZvQacM6Ll8sAVQiHxC/GdvFCbyDX/Dgf2dZdkD3 Pru+L1b6SqluW9s13dLW5ETjJmDqZI+tvx2h6p9StDhgDuBXvKYy3iLu4yhv96WbSu6jlQ H0TGZM9BuCzicZVqZS3O27oBKqFaZlpci0ymjDi9kxluTZ4fQiYbYymKyBYyWu7gLFZdF5 xemWUHRoavCQlorK5PHjhOCAMw28DEAz0vYDGjQNpJjnUYv7pg5AKz9Dz6cRFDwbLe9RKX xvjpUYent1rpnh/+WkGwrzaOYMglnYcT1MGE2pMcwOzAjDXPTvFjC3JCoUxhtw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1677660187; a=rsa-sha256; cv=none; b=oevlnCQEhpqI0U4YoX0RqltFwQ89aviiQvWtHbu4Kin9yW7ePrMWedUcq3K++L924kVadz Nuvw3pMkDJur5JRNpF3cAylLwfwpFLTehFAv8JWT064xMxalFQ3fcFtJM4UPEeNRIwO7fi cCBA0Q9hiDFvhBo3v1Y84IMocOJwMjg8/OdroCPwfgzbONIaQXT98knCNwELI5/6hZaG4K xdm+DFntBHGsWnHbxJf2yvT6XYSLxz6RezRd4qjCEdg6ptEpOwlTm/sbPO1bgoXvZkfUXu ed9JH1fH9R9BoTg9w8XLbGIRcEUO7ZaUsdfZgKg1FpUuJHLOV9UWSTASfz4Ezg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4PRSRv1wsBzSdj; Wed, 1 Mar 2023 08:43:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 3218h7oj028448; Wed, 1 Mar 2023 08:43:07 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 3218h7Jf028447; Wed, 1 Mar 2023 08:43:07 GMT (envelope-from git) Date: Wed, 1 Mar 2023 08:43:07 GMT Message-Id: <202303010843.3218h7Jf028447@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dmitry Chagin Subject: git: 28b647373119 - stable/13 - linux(4): Move uselib() to i386 List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dchagin X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 28b6473731192395d1da81789f1ffa7c786d2b09 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=28b6473731192395d1da81789f1ffa7c786d2b09 commit 28b6473731192395d1da81789f1ffa7c786d2b09 Author: Dmitry Chagin AuthorDate: 2023-02-14 14:46:31 +0000 Commit: Dmitry Chagin CommitDate: 2023-03-01 08:42:32 +0000 linux(4): Move uselib() to i386 This obsolete system call is not supported by glibc. In ancient libc versions (before glibc 2.0), uselib() was used to load the shared libraries with names found in an array of names in the binary. On Linux, since 3.15, this system call is available only when the kernel is configured with the CONFIG_USELIB option. It doesn't look like anyone needs this syscall for others Linuxulators, so move it to the corresponding MD Linuxulator. MFC after: 2 weeks (cherry picked from commit 50c85a32d9c667779494850b6238b8d7ec13da75) --- sys/compat/linux/linux_misc.c | 264 ----------------------------------------- sys/i386/linux/linux_machdep.c | 260 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+), 264 deletions(-) diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 823b79cc373d..4dba124a918f 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -35,9 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#if defined(__i386__) -#include -#endif #include #include #include @@ -48,13 +45,11 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -77,12 +72,8 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include -#include #include -#include -#include #include #ifdef COMPAT_LINUX32 @@ -251,261 +242,6 @@ linux_brk(struct thread *td, struct linux_brk_args *args) return (0); } -#if defined(__i386__) -/* XXX: what about amd64/linux32? */ - -int -linux_uselib(struct thread *td, struct linux_uselib_args *args) -{ - struct nameidata ni; - struct vnode *vp; - struct exec *a_out; - vm_map_t map; - vm_map_entry_t entry; - struct vattr attr; - vm_offset_t vmaddr; - unsigned long file_offset; - unsigned long bss_size; - char *library; - ssize_t aresid; - int error; - bool locked, opened, textset; - - a_out = NULL; - vp = NULL; - locked = false; - textset = false; - opened = false; - - if (!LUSECONVPATH(td)) { - NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, - UIO_USERSPACE, args->library, td); - error = namei(&ni); - } else { - LCONVPATHEXIST(args->library, &library); - NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, - UIO_SYSSPACE, library, td); - error = namei(&ni); - LFREEPATH(library); - } - if (error) - goto cleanup; - - vp = ni.ni_vp; - NDFREE(&ni, NDF_ONLY_PNBUF); - - /* - * From here on down, we have a locked vnode that must be unlocked. - * XXX: The code below largely duplicates exec_check_permissions(). - */ - locked = true; - - /* Executable? */ - error = VOP_GETATTR(vp, &attr, td->td_ucred); - if (error) - goto cleanup; - - if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || - ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { - /* EACCESS is what exec(2) returns. */ - error = ENOEXEC; - goto cleanup; - } - - /* Sensible size? */ - if (attr.va_size == 0) { - error = ENOEXEC; - goto cleanup; - } - - /* Can we access it? */ - error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); - if (error) - goto cleanup; - - /* - * XXX: This should use vn_open() so that it is properly authorized, - * and to reduce code redundancy all over the place here. - * XXX: Not really, it duplicates far more of exec_check_permissions() - * than vn_open(). - */ -#ifdef MAC - error = mac_vnode_check_open(td->td_ucred, vp, VREAD); - if (error) - goto cleanup; -#endif - error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL); - if (error) - goto cleanup; - opened = true; - - /* Pull in executable header into exec_map */ - error = vm_mmap(exec_map, (vm_offset_t *)&a_out, PAGE_SIZE, - VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); - if (error) - goto cleanup; - - /* Is it a Linux binary ? */ - if (((a_out->a_magic >> 16) & 0xff) != 0x64) { - error = ENOEXEC; - goto cleanup; - } - - /* - * While we are here, we should REALLY do some more checks - */ - - /* Set file/virtual offset based on a.out variant. */ - switch ((int)(a_out->a_magic & 0xffff)) { - case 0413: /* ZMAGIC */ - file_offset = 1024; - break; - case 0314: /* QMAGIC */ - file_offset = 0; - break; - default: - error = ENOEXEC; - goto cleanup; - } - - bss_size = round_page(a_out->a_bss); - - /* Check various fields in header for validity/bounds. */ - if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { - error = ENOEXEC; - goto cleanup; - } - - /* text + data can't exceed file size */ - if (a_out->a_data + a_out->a_text > attr.va_size) { - error = EFAULT; - goto cleanup; - } - - /* - * text/data/bss must not exceed limits - * XXX - this is not complete. it should check current usage PLUS - * the resources needed by this library. - */ - PROC_LOCK(td->td_proc); - if (a_out->a_text > maxtsiz || - a_out->a_data + bss_size > lim_cur_proc(td->td_proc, RLIMIT_DATA) || - racct_set(td->td_proc, RACCT_DATA, a_out->a_data + - bss_size) != 0) { - PROC_UNLOCK(td->td_proc); - error = ENOMEM; - goto cleanup; - } - PROC_UNLOCK(td->td_proc); - - /* - * Prevent more writers. - */ - error = VOP_SET_TEXT(vp); - if (error != 0) - goto cleanup; - textset = true; - - /* - * Lock no longer needed - */ - locked = false; - VOP_UNLOCK(vp); - - /* - * Check if file_offset page aligned. Currently we cannot handle - * misalinged file offsets, and so we read in the entire image - * (what a waste). - */ - if (file_offset & PAGE_MASK) { - /* Map text+data read/write/execute */ - - /* a_entry is the load address and is page aligned */ - vmaddr = trunc_page(a_out->a_entry); - - /* get anon user mapping, read+write+execute */ - error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, - &vmaddr, a_out->a_text + a_out->a_data, 0, VMFS_NO_SPACE, - VM_PROT_ALL, VM_PROT_ALL, 0); - if (error) - goto cleanup; - - error = vn_rdwr(UIO_READ, vp, (void *)vmaddr, file_offset, - a_out->a_text + a_out->a_data, UIO_USERSPACE, 0, - td->td_ucred, NOCRED, &aresid, td); - if (error != 0) - goto cleanup; - if (aresid != 0) { - error = ENOEXEC; - goto cleanup; - } - } else { - /* - * for QMAGIC, a_entry is 20 bytes beyond the load address - * to skip the executable header - */ - vmaddr = trunc_page(a_out->a_entry); - - /* - * Map it all into the process's space as a single - * copy-on-write "data" segment. - */ - map = &td->td_proc->p_vmspace->vm_map; - error = vm_mmap(map, &vmaddr, - a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, - MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset); - if (error) - goto cleanup; - vm_map_lock(map); - if (!vm_map_lookup_entry(map, vmaddr, &entry)) { - vm_map_unlock(map); - error = EDOOFUS; - goto cleanup; - } - entry->eflags |= MAP_ENTRY_VN_EXEC; - vm_map_unlock(map); - textset = false; - } - - if (bss_size != 0) { - /* Calculate BSS start address */ - vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + - a_out->a_data; - - /* allocate some 'anon' space */ - error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, - &vmaddr, bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, - VM_PROT_ALL, 0); - if (error) - goto cleanup; - } - -cleanup: - if (opened) { - if (locked) - VOP_UNLOCK(vp); - locked = false; - VOP_CLOSE(vp, FREAD, td->td_ucred, td); - } - if (textset) { - if (!locked) { - locked = true; - VOP_LOCK(vp, LK_SHARED | LK_RETRY); - } - VOP_UNSET_TEXT_CHECKED(vp); - } - if (locked) - VOP_UNLOCK(vp); - - /* Release the temporary mapping. */ - if (a_out) - kmap_free_wakeup(exec_map, (vm_offset_t)a_out, PAGE_SIZE); - - return (error); -} - -#endif /* __i386__ */ - #ifdef LINUX_LEGACY_SYSCALLS int linux_select(struct thread *td, struct linux_select_args *args) diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index fb42c3e9df84..45aad4935613 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -31,15 +31,18 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -49,8 +52,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include +#include + #include #include #include @@ -58,7 +65,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include +#include #include @@ -701,3 +711,253 @@ bsd_to_linux_regset(const struct reg *b_reg, l_regset->esp = b_reg->r_esp; l_regset->ss = b_reg->r_ss; } + +int +linux_uselib(struct thread *td, struct linux_uselib_args *args) +{ + struct nameidata ni; + struct vnode *vp; + struct exec *a_out; + vm_map_t map; + vm_map_entry_t entry; + struct vattr attr; + vm_offset_t vmaddr; + unsigned long file_offset; + unsigned long bss_size; + char *library; + ssize_t aresid; + int error; + bool locked, opened, textset; + + a_out = NULL; + vp = NULL; + locked = false; + textset = false; + opened = false; + + if (!LUSECONVPATH(td)) { + NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, + UIO_USERSPACE, args->library, td); + error = namei(&ni); + } else { + LCONVPATHEXIST(args->library, &library); + NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, + UIO_SYSSPACE, library, td); + error = namei(&ni); + LFREEPATH(library); + } + if (error) + goto cleanup; + + vp = ni.ni_vp; + NDFREE(&ni, NDF_ONLY_PNBUF); + + /* + * From here on down, we have a locked vnode that must be unlocked. + * XXX: The code below largely duplicates exec_check_permissions(). + */ + locked = true; + + /* Executable? */ + error = VOP_GETATTR(vp, &attr, td->td_ucred); + if (error) + goto cleanup; + + if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || + ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { + /* EACCESS is what exec(2) returns. */ + error = ENOEXEC; + goto cleanup; + } + + /* Sensible size? */ + if (attr.va_size == 0) { + error = ENOEXEC; + goto cleanup; + } + + /* Can we access it? */ + error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); + if (error) + goto cleanup; + + /* + * XXX: This should use vn_open() so that it is properly authorized, + * and to reduce code redundancy all over the place here. + * XXX: Not really, it duplicates far more of exec_check_permissions() + * than vn_open(). + */ +#ifdef MAC + error = mac_vnode_check_open(td->td_ucred, vp, VREAD); + if (error) + goto cleanup; +#endif + error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL); + if (error) + goto cleanup; + opened = true; + + /* Pull in executable header into exec_map */ + error = vm_mmap(exec_map, (vm_offset_t *)&a_out, PAGE_SIZE, + VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); + if (error) + goto cleanup; + + /* Is it a Linux binary ? */ + if (((a_out->a_magic >> 16) & 0xff) != 0x64) { + error = ENOEXEC; + goto cleanup; + } + + /* + * While we are here, we should REALLY do some more checks + */ + + /* Set file/virtual offset based on a.out variant. */ + switch ((int)(a_out->a_magic & 0xffff)) { + case 0413: /* ZMAGIC */ + file_offset = 1024; + break; + case 0314: /* QMAGIC */ + file_offset = 0; + break; + default: + error = ENOEXEC; + goto cleanup; + } + + bss_size = round_page(a_out->a_bss); + + /* Check various fields in header for validity/bounds. */ + if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { + error = ENOEXEC; + goto cleanup; + } + + /* text + data can't exceed file size */ + if (a_out->a_data + a_out->a_text > attr.va_size) { + error = EFAULT; + goto cleanup; + } + + /* + * text/data/bss must not exceed limits + * XXX - this is not complete. it should check current usage PLUS + * the resources needed by this library. + */ + PROC_LOCK(td->td_proc); + if (a_out->a_text > maxtsiz || + a_out->a_data + bss_size > lim_cur_proc(td->td_proc, RLIMIT_DATA) || + racct_set(td->td_proc, RACCT_DATA, a_out->a_data + + bss_size) != 0) { + PROC_UNLOCK(td->td_proc); + error = ENOMEM; + goto cleanup; + } + PROC_UNLOCK(td->td_proc); + + /* + * Prevent more writers. + */ + error = VOP_SET_TEXT(vp); + if (error != 0) + goto cleanup; + textset = true; + + /* + * Lock no longer needed + */ + locked = false; + VOP_UNLOCK(vp); + + /* + * Check if file_offset page aligned. Currently we cannot handle + * misalinged file offsets, and so we read in the entire image + * (what a waste). + */ + if (file_offset & PAGE_MASK) { + /* Map text+data read/write/execute */ + + /* a_entry is the load address and is page aligned */ + vmaddr = trunc_page(a_out->a_entry); + + /* get anon user mapping, read+write+execute */ + error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, + &vmaddr, a_out->a_text + a_out->a_data, 0, VMFS_NO_SPACE, + VM_PROT_ALL, VM_PROT_ALL, 0); + if (error) + goto cleanup; + + error = vn_rdwr(UIO_READ, vp, (void *)vmaddr, file_offset, + a_out->a_text + a_out->a_data, UIO_USERSPACE, 0, + td->td_ucred, NOCRED, &aresid, td); + if (error != 0) + goto cleanup; + if (aresid != 0) { + error = ENOEXEC; + goto cleanup; + } + } else { + /* + * for QMAGIC, a_entry is 20 bytes beyond the load address + * to skip the executable header + */ + vmaddr = trunc_page(a_out->a_entry); + + /* + * Map it all into the process's space as a single + * copy-on-write "data" segment. + */ + map = &td->td_proc->p_vmspace->vm_map; + error = vm_mmap(map, &vmaddr, + a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, + MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset); + if (error) + goto cleanup; + vm_map_lock(map); + if (!vm_map_lookup_entry(map, vmaddr, &entry)) { + vm_map_unlock(map); + error = EDOOFUS; + goto cleanup; + } + entry->eflags |= MAP_ENTRY_VN_EXEC; + vm_map_unlock(map); + textset = false; + } + + if (bss_size != 0) { + /* Calculate BSS start address */ + vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + + a_out->a_data; + + /* allocate some 'anon' space */ + error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, + &vmaddr, bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, + VM_PROT_ALL, 0); + if (error) + goto cleanup; + } + +cleanup: + if (opened) { + if (locked) + VOP_UNLOCK(vp); + locked = false; + VOP_CLOSE(vp, FREAD, td->td_ucred, td); + } + if (textset) { + if (!locked) { + locked = true; + VOP_LOCK(vp, LK_SHARED | LK_RETRY); + } + VOP_UNSET_TEXT_CHECKED(vp); + } + if (locked) + VOP_UNLOCK(vp); + + /* Release the temporary mapping. */ + if (a_out) + kmap_free_wakeup(exec_map, (vm_offset_t)a_out, PAGE_SIZE); + + return (error); +}