From nobody Tue Feb 14 14:47:16 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 4PGPF13fD4z3s2fL; Tue, 14 Feb 2023 14:47:17 +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 4PGPF10kfNz46cH; Tue, 14 Feb 2023 14:47:17 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1676386037; 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=NjMq309bp9NpfOw0oSm/rHlF2rPDGkeZqjb1/NeH6H0=; b=CosEZjtdX9R0RkAwSRP+dDYTx4ZfoMr7i4POC9MCx+Uo1cE7tDSw4W+dCZ1kECrvZC6BSc cS6G5fOzHcDJR08M2MRLZJlNf+rKRYRjaeU2MWy2ABd1M/R5LFkvOgIaR4prMrpaDb4GD3 I8diibX6Yv4w+ni61D1MYBEdkvFD9as+lT9yxh0TJNo7TozskBvaTuC4aPjK/nIHDxSAnI Ohiqy5SlUKy1fGo1rdAocXyWLmoP5znljrKCR5oh2w7XbEFevjMOWuw8KlzkX1W6uWwON1 EEtryVtTCGNcGj4afPnZzoFwTig+l57DZV2T+zdYZNpTniPcpTGN0cWSfSIQ2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1676386037; 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=NjMq309bp9NpfOw0oSm/rHlF2rPDGkeZqjb1/NeH6H0=; b=adQZPSRANvNi05Ey+xsG3Qoy3sOmkq7nSSB8NyTbkIz5qTWrqsp23YuBhtStZr2bfqPxv2 jV3e3z9QP2I7ARWwjtybWPyUhYh2mtzV4/mKIbUTFvg3KBpIcatb3EoqG6JxTggEzeptUs v8tsAk6aMAiCqs2rCVd2J1X2RA7TIIvR70+i9R3sI5PQwTZNQ8AYdntQIKRUgk9nj7KlAu 10jugXYf1G6zXtqv1C/2TJItfNY9GIE8wcb1LOWDE7R9fm5YfqV08lH0nz7V/4bR8TwX7a JZdC16SfjyuHfwWWzLssHXuwxNNk66if0ZCwkwQqKuzLESe4Q1z2gyttwJsnrA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1676386037; a=rsa-sha256; cv=none; b=PQmTdedT5Zj3GUEgEe9CtNx6VTIH3zZdRIcQ3LiTaR7cp2jm22wmDtlMEKiqgdPO+LWfs7 drm0wRsBN2+wIpIQFU7b9WatXUPbtApzNzqkSx898JH3IG6bIqqgWa0fX0MKrZKtz/YIfm zmnEdn7kl4EfpIDhldWNjzCNf7PrI0QxKnVAfvRrY+zLSq9yOIOE0TLwWLyNDw2vOx7b1l zVzl6yj4kIKkjBm5EXVItple8JMNlXtyOZvnpvbE/huccXA5uxJ/QlvvtuqTDGscfHaIjY nqvyoMSvws0RtnwHEOKeYIzxhATH1/9l7Z+gg/JM9VR4NycrPL287svtGOOb/A== 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 4PGPF06xnzz12kS; Tue, 14 Feb 2023 14:47:16 +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 31EElGpT072381; Tue, 14 Feb 2023 14:47:16 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 31EElGMl072380; Tue, 14 Feb 2023 14:47:16 GMT (envelope-from git) Date: Tue, 14 Feb 2023 14:47:16 GMT Message-Id: <202302141447.31EElGMl072380@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dmitry Chagin Subject: git: 50c85a32d9c6 - main - 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/main X-Git-Reftype: branch X-Git-Commit: 50c85a32d9c667779494850b6238b8d7ec13da75 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=50c85a32d9c667779494850b6238b8d7ec13da75 commit 50c85a32d9c667779494850b6238b8d7ec13da75 Author: Dmitry Chagin AuthorDate: 2023-02-14 14:46:31 +0000 Commit: Dmitry Chagin CommitDate: 2023-02-14 14:46:31 +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 --- 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 b20a1b3597e5..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); - error = namei(&ni); - } else { - LCONVPATHEXIST(args->library, &library); - NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, - UIO_SYSSPACE, library); - error = namei(&ni); - LFREEPATH(library); - } - if (error) - goto cleanup; - - vp = ni.ni_vp; - NDFREE_PNBUF(&ni); - - /* - * 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..148258ac049c 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); + error = namei(&ni); + } else { + LCONVPATHEXIST(args->library, &library); + NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1, + UIO_SYSSPACE, library); + error = namei(&ni); + LFREEPATH(library); + } + if (error) + goto cleanup; + + vp = ni.ni_vp; + NDFREE_PNBUF(&ni); + + /* + * 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); +}