Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 May 2023 09:18:44 GMT
From:      Dmitry Chagin <dchagin@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 8340b03425cf - main - linux(4): Add a dedicated linux_exec_copyin_args()
Message-ID:  <202305290918.34T9Iisq063370@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=8340b03425cfa61ec17ad6a9b576590df3afd509

commit 8340b03425cfa61ec17ad6a9b576590df3afd509
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2023-05-29 09:18:16 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2023-05-29 09:18:16 +0000

    linux(4): Add a dedicated linux_exec_copyin_args()
    
    Because Linux allows to exec binaries with 0 argc.
    
    Reviewed by:            brooks
    Differential Revision:  https://reviews.freebsd.org/D40148
    MFC after:              2 month
---
 sys/amd64/linux/syscalls.master     |  4 +-
 sys/amd64/linux32/linux32_machdep.c | 14 ------
 sys/amd64/linux32/syscalls.master   |  4 +-
 sys/arm64/linux/syscalls.master     |  4 +-
 sys/compat/linux/linux_misc.c       | 87 +++++++++++++++++++++++++++++++++++--
 sys/i386/linux/syscalls.master      |  4 +-
 6 files changed, 92 insertions(+), 25 deletions(-)

diff --git a/sys/amd64/linux/syscalls.master b/sys/amd64/linux/syscalls.master
index 420c029fa892..e4ac2ef99edf 100644
--- a/sys/amd64/linux/syscalls.master
+++ b/sys/amd64/linux/syscalls.master
@@ -439,8 +439,8 @@
 59	AUE_EXECVE	STD {
 		int linux_execve(
 		    char *path,
-		    char **argp,
-		    char **envp
+		    l_uintptr_t *argp,
+		    l_uintptr_t *envp
 		);
 	}
 60	AUE_EXIT	STD {
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index 4e5d6eb55fc6..bcbf51082c64 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -114,20 +114,6 @@ linux_copyout_rusage(struct rusage *ru, void *uaddr)
 	return (copyout(&lru, uaddr, sizeof(struct l_rusage)));
 }
 
-int
-linux_execve(struct thread *td, struct linux_execve_args *args)
-{
-	struct image_args eargs;
-	int error;
-
-	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);
-	return (error);
-}
-
 CTASSERT(sizeof(struct l_iovec32) == 8);
 
 int
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
index 777ffd865b8b..382b681fdde1 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -102,8 +102,8 @@
 11	AUE_EXECVE	STD {
 		int linux_execve(
 		    char *path,
-		    uint32_t *argp,
-		    uint32_t *envp
+		    l_uintptr_t *argp,
+		    l_uintptr_t *envp
 		);
 	}
 12	AUE_CHDIR	STD {
diff --git a/sys/arm64/linux/syscalls.master b/sys/arm64/linux/syscalls.master
index 2a564f0e3c5d..b9dda787389c 100644
--- a/sys/arm64/linux/syscalls.master
+++ b/sys/arm64/linux/syscalls.master
@@ -1357,8 +1357,8 @@
 221	AUE_EXECVE	STD	{
 		int linux_execve(
 		    char *path,
-		    char **argp,
-		    char **envp
+		    l_uintptr_t *argp,
+		    l_uintptr_t *envp
 		);
 	}
 222	AUE_MMAP	STD	{
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index b5d48d106be6..583cc25f1c43 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -2555,7 +2555,89 @@ linux_seccomp(struct thread *td, struct linux_seccomp_args *args)
 	}
 }
 
-#ifndef COMPAT_LINUX32
+/*
+ * Custom version of exec_copyin_args(), to copy out argument and environment
+ * strings from the old process address space into the temporary string buffer.
+ * Based on freebsd32_exec_copyin_args.
+ */
+static int
+linux_exec_copyin_args(struct image_args *args, const char *fname,
+    enum uio_seg segflg, l_uintptr_t *argv, l_uintptr_t *envv)
+{
+	char *argp, *envp;
+	l_uintptr_t *ptr, arg;
+	int error;
+
+	bzero(args, sizeof(*args));
+	if (argv == NULL)
+		return (EFAULT);
+
+	/*
+	 * Allocate demand-paged memory for the file name, argument, and
+	 * environment strings.
+	 */
+	error = exec_alloc_args(args);
+	if (error != 0)
+		return (error);
+
+	/*
+	 * Copy the file name.
+	 */
+	error = exec_args_add_fname(args, fname, segflg);
+	if (error != 0)
+		goto err_exit;
+
+	/*
+	 * extract arguments first
+	 */
+	ptr = argv;
+	for (;;) {
+		error = copyin(ptr++, &arg, sizeof(arg));
+		if (error)
+			goto err_exit;
+		if (arg == 0)
+			break;
+		argp = PTRIN(arg);
+		error = exec_args_add_arg(args, argp, UIO_USERSPACE);
+		if (error != 0)
+			goto err_exit;
+	}
+
+	/*
+	 * This comment is from Linux do_execveat_common:
+	 * When argv is empty, add an empty string ("") as argv[0] to
+	 * ensure confused userspace programs that start processing
+	 * from argv[1] won't end up walking envp.
+	 */
+	if (args->argc == 0 &&
+	    (error = exec_args_add_arg(args, "", UIO_SYSSPACE) != 0))
+		goto err_exit;
+
+	/*
+	 * extract environment strings
+	 */
+	if (envv) {
+		ptr = envv;
+		for (;;) {
+			error = copyin(ptr++, &arg, sizeof(arg));
+			if (error)
+				goto err_exit;
+			if (arg == 0)
+				break;
+			envp = PTRIN(arg);
+			error = exec_args_add_env(args, envp, UIO_USERSPACE);
+			if (error != 0)
+				goto err_exit;
+		}
+	}
+
+	return (0);
+
+err_exit:
+	exec_free_args(args);
+	return (error);
+}
+
 int
 linux_execve(struct thread *td, struct linux_execve_args *args)
 {
@@ -2564,11 +2646,10 @@ linux_execve(struct thread *td, struct linux_execve_args *args)
 
 	LINUX_CTR(execve);
 
-	error = exec_copyin_args(&eargs, args->path, UIO_USERSPACE,
+	error = linux_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);
 	return (error);
 }
-#endif
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index 9175bcd45dcf..c7168f7da80e 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -102,8 +102,8 @@
 11	AUE_EXECVE	STD {
 		int linux_execve(
 		    char *path,
-		    char **argp,
-		    char **envp
+		    l_uintptr_t *argp,
+		    l_uintptr_t *envp
 		);
 	}
 12	AUE_CHDIR	STD {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202305290918.34T9Iisq063370>