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
This commit is contained in:
Dmitry Chagin 2023-05-29 12:18:16 +03:00
parent 07c0b6e535
commit 8340b03425
6 changed files with 92 additions and 25 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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 {