The branch main has been updated by dchagin:

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

commit 8340b03425cfa61ec17ad6a9b576590df3afd509
Author:     Dmitry Chagin <[email protected]>
AuthorDate: 2023-05-29 09:18:16 +0000
Commit:     Dmitry Chagin <[email protected]>
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 {

Reply via email to