From dfb33b8bc203aa9044fff6b7e0636b5254e63b90 Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Wed, 19 Nov 2025 14:23:42 +0100 Subject: [PATCH 1/4] rework args/env setup to add aux values --- so3/arch/arm32/include/asm/hwcap.h | 64 ++++++++ so3/arch/arm64/include/asm/hwcap.h | 26 ++++ so3/include/elf.h | 4 + so3/include/uapi/linux/auxvec.h | 48 ++++++ so3/kernel/process.c | 237 +++++++++++++++-------------- 5 files changed, 268 insertions(+), 111 deletions(-) create mode 100644 so3/arch/arm32/include/asm/hwcap.h create mode 100644 so3/arch/arm64/include/asm/hwcap.h create mode 100644 so3/include/uapi/linux/auxvec.h diff --git a/so3/arch/arm32/include/asm/hwcap.h b/so3/arch/arm32/include/asm/hwcap.h new file mode 100644 index 000000000..0a19d90c1 --- /dev/null +++ b/so3/arch/arm32/include/asm/hwcap.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2025 Clément Dieperink + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef ASM_ARM_HWCAP_H +#define ASM_ARM_HWCAP_H + +/* + * Hardware capabilities flags - for AT_HWCAP + * Copied from Linux arch/arm/include/asm/procinfo.h + */ +#define HWCAP_SWP (1 << 0) +#define HWCAP_HALF (1 << 1) +#define HWCAP_THUMB (1 << 2) +#define HWCAP_26BIT (1 << 3) /* Play it safe */ +#define HWCAP_FAST_MULT (1 << 4) +#define HWCAP_FPA (1 << 5) +#define HWCAP_VFP (1 << 6) +#define HWCAP_EDSP (1 << 7) +#define HWCAP_JAVA (1 << 8) +#define HWCAP_IWMMXT (1 << 9) +#define HWCAP_CRUNCH (1 << 10) /* Obsolete */ +#define HWCAP_THUMBEE (1 << 11) +#define HWCAP_NEON (1 << 12) +#define HWCAP_VFPv3 (1 << 13) +#define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */ +#define HWCAP_TLS (1 << 15) +#define HWCAP_VFPv4 (1 << 16) +#define HWCAP_IDIVA (1 << 17) +#define HWCAP_IDIVT (1 << 18) +#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ +#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) +#define HWCAP_LPAE (1 << 20) +#define HWCAP_EVTSTRM (1 << 21) +#define HWCAP_FPHP (1 << 22) +#define HWCAP_ASIMDHP (1 << 23) +#define HWCAP_ASIMDDP (1 << 24) +#define HWCAP_ASIMDFHM (1 << 25) +#define HWCAP_ASIMDBF16 (1 << 26) +#define HWCAP_I8MM (1 << 27) + +/* + * ARMv7 flags used by Linux, see arch/arm/mm/proc-v7.S, macro __v7_proc + */ +#define HWCAP_ELF (HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_EDSP | HWCAP_TLS) + +#endif /* ASM_ARM_HWCAP */ diff --git a/so3/arch/arm64/include/asm/hwcap.h b/so3/arch/arm64/include/asm/hwcap.h new file mode 100644 index 000000000..75e034c73 --- /dev/null +++ b/so3/arch/arm64/include/asm/hwcap.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2025 Clément Dieperink + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef ASM_ARM_HWCAP_H +#define ASM_ARM_HWCAP_H + +/* + * This isn't used be MUSL on AArch64, so simply let it to 0 for now. + */ +#define HWCAP_ELF 0 + +#endif /* ASM_ARM_HWCAP */ diff --git a/so3/include/elf.h b/so3/include/elf.h index 767ca1155..688bbb678 100644 --- a/so3/include/elf.h +++ b/so3/include/elf.h @@ -36,6 +36,8 @@ struct elf_img_info { uint32_t segment_page_count; }; +typedef Elf32_Off elf_addr_t; + #else struct elf_img_info { @@ -47,6 +49,8 @@ struct elf_img_info { uint64_t segment_page_count; }; +typedef Elf64_Off elf_addr_t; + #endif typedef struct elf_img_info elf_img_info_t; diff --git a/so3/include/uapi/linux/auxvec.h b/so3/include/uapi/linux/auxvec.h new file mode 100644 index 000000000..6e7a3f5eb --- /dev/null +++ b/so3/include/uapi/linux/auxvec.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_AUXVEC_H +#define _UAPI_LINUX_AUXVEC_H + +/* Maximum count of auxiliary values */ +#define AUX_CNT 38 + +/* Symbolic values for the entries in the auxiliary table + put on the initial stack */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ +#define AT_PLATFORM 15 /* string identifying CPU for optimizations */ +#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define AT_CLKTCK 17 /* frequency at which times() increments */ +/* AT_* values 18 through 22 are reserved */ +#define AT_SECURE 23 /* secure mode boolean */ +#define AT_BASE_PLATFORM 24 /* string identifying real platform, may + * differ from AT_PLATFORM. */ +#define AT_RANDOM 25 /* address of 16 random bytes */ +#define AT_HWCAP2 26 /* extension of AT_HWCAP */ +#define AT_RSEQ_FEATURE_SIZE 27 /* rseq supported feature size */ +#define AT_RSEQ_ALIGN 28 /* rseq allocation alignment */ +#define AT_HWCAP3 29 /* extension of AT_HWCAP */ +#define AT_HWCAP4 30 /* extension of AT_HWCAP */ + +#define AT_EXECFN 31 /* filename of program */ + +#ifndef AT_MINSIGSTKSZ +#define AT_MINSIGSTKSZ 51 /* minimal stack size for signal delivery */ +#endif + +/* Common from asm/auxvec.h of arm and arm64 */ +#define AT_SYSINFO_EHDR 33 + +#endif /* _UAPI_LINUX_AUXVEC_H */ diff --git a/so3/kernel/process.c b/so3/kernel/process.c index 0caa26cf0..1b915e462 100644 --- a/so3/kernel/process.c +++ b/so3/kernel/process.c @@ -32,6 +32,9 @@ #include #include #include +#include + +#include #include @@ -39,10 +42,19 @@ #include #include #include +#include #ifndef CONFIG_ARCH_ARM32 #include #endif +/* Structure to temporary save exec args/env */ +typedef struct { + int argc; + int envc; + size_t strings_size; + char arg_env[PAGE_SIZE]; +} args_env_t; + static char *proc_state_strings[5] = { [PROC_STATE_NEW] = "NEW", [PROC_STATE_READY] = "READY", [PROC_STATE_RUNNING] = "RUNNING", [PROC_STATE_WAITING] = "WAITING", [PROC_STATE_ZOMBIE] = "ZOMBIE", @@ -390,150 +402,153 @@ static void release_proc_pages(pcb_t *pcb) */ addr_t preserve_args_and_env(int argc, char **argv, char **envp) { - char *args_p, *args_str_p; - void *args; - char **__args; + char *args_str_p; + size_t str_len; + args_env_t *saved; int i; if ((argc > 0) && (argv == NULL)) { return -EINVAL; } - /* Page storing the args & env strings - keeps a reference to it. - */ - args = malloc(PAGE_SIZE); - BUG_ON(args == NULL); - - memset(args, 0, PAGE_SIZE); - - args_p = (char *) args; - if (!argc) - i = 1; - else - i = argc; - - memcpy(args_p, &i, sizeof(int)); - - /* Number of args */ - args_p += sizeof(int); - - /* Store the array of strings for args & env */ - - /* The array starts right after argc (stored on 4 bytes). - * We find the addresses of the var strings followed by the addresses of - * env strings. The var strings come after followed by the env strings. - */ - - /* Manage the addresses of strings; determine the start of the first arg - * string. */ - - if (!argc) /* At least one arg containing the process name */ - args_p += sizeof(char *); - else - args_p += sizeof(char *) * argc; - - /* Environment string addresses */ - if (!envp) { - *((addr_t *) args_p) = 0; /* Keep array-end with NULL */ - args_p += sizeof(char *); - - } else { - i = 0; - do { - args_p = args_p + sizeof(char *); - } while (envp[i++] != NULL); - } + /* Allocate kernel memory to preserve the args/env */ + saved = malloc(sizeof(args_env_t)); + BUG_ON(saved == NULL); - /* Manage the arg strings */ + memset(saved->arg_env, 0, PAGE_SIZE); - args_str_p = args_p; - __args = (char **) (args + sizeof(int)); + args_str_p = (char *) saved->arg_env; - /* As said before, if argc is 0 (argv NULL), we put the process name (a - * kind of by-default argument) */ + /* Save args strings */ if (!argc) { - __args[0] = args_str_p; - strcpy(__args[0], current()->pcb->name); - - args_str_p += strlen(current()->pcb->name) + 1; - } - - /* Place the strings with their addresses - is the new address - * (definitive location). */ - - for (i = 0; i < argc; i++) { - __args[i] = args_str_p; - strcpy(__args[i], argv[i]); + /* If no arguments, add one with process name */ + saved->argc = 1; + strcpy(args_str_p, current()->pcb->name); + args_str_p += strlen(args_str_p) + 1; + } else { + /* Copy all arguments strings */ + saved->argc = argc; + for (i = 0; i < argc; i++) { + str_len = strlen(argv[i]) + 1; - args_str_p += strlen(argv[i]) + 1; + /* Ensure the newly copied string will not exceed the buffer size. */ + if ((addr_t) args_str_p - (addr_t) saved->arg_env + str_len > PAGE_SIZE) { + LOG_CRITICAL("Not enougth memory allocated\n"); - /* We check if the pointer do not exceed the page we - * allocated before */ - if (((addr_t) args_str_p - (addr_t) args) > PAGE_SIZE) { - LOG_CRITICAL("Not enougth memory allocated\n"); + free(saved); + return -ENOMEM; + } - free(args); - return -ENOMEM; + strcpy(args_str_p, argv[i]); + args_str_p += str_len; } } - /* Environment strings */ - - /* First env. variable */ - __args = (char **) (args + sizeof(int) + sizeof(char *) * (*((int *) args))); - - /* If the environment was passed */ + /* Save env strings and count how many there are */ + saved->envc = 0; if (envp) { - i = 0; - while (envp[i] != NULL) { - __args[i] = args_str_p; - strcpy(__args[i], envp[i]); - - args_str_p += strlen(envp[i]) + 1; + do { + str_len = strlen(envp[saved->envc]) + 1; - /* We check if pointer do not exceed the page we - * allocated before. */ - if (((addr_t) args_str_p - (addr_t) args) > PAGE_SIZE) { - LOG_ERROR("Not enough memory allocated\n"); + /* Ensure the newly copied string will not exceed the buffer size. */ + if ((addr_t) args_str_p - (addr_t) saved->arg_env + str_len > PAGE_SIZE) { + LOG_CRITICAL("Not enougth memory allocated\n"); - free(args); + free(saved); return -ENOMEM; } - i++; - } + + strcpy(args_str_p, envp[saved->envc]); + args_str_p += strlen(args_str_p) + 1; + } while (envp[saved->envc++]); } - return (addr_t) args; + /* Save total string size for easier copy to user. */ + saved->strings_size = (addr_t) args_str_p - (addr_t) saved->arg_env; + + return (addr_t) saved; } -void post_setup_image(void *args_env) +void post_setup_image(args_env_t *args_env, elf_img_info_t *elf_img_info) { - char **__args; + char **argv_p_base; + char *str_p; + char **env_p_base; char *args_base; - int argc, i; + int i; + elf_addr_t *aux_elf; args_base = (char *) arch_get_args_base(); - memcpy(args_base, args_env, PAGE_SIZE); + /* Save argc as first arguments */ + *((int *) args_base) = args_env->argc; + + /* Get the base address for the array of pointer for args, env and aux */ + argv_p_base = (char **) (args_base + sizeof(int)); + env_p_base = (char **) ((addr_t) argv_p_base + args_env->argc * sizeof(char *)); + /* Add one to account for the null termination of env */ + aux_elf = (elf_addr_t *) ((addr_t) env_p_base + (args_env->envc + 1) * sizeof(char *)); + + /* Adds auxiliary before args and env to get the starting address for the strings. + * Each auxiliary entry have an id and a value, the following temporary helper allows + * to easily add an entry without missing something, or adding unecessary functions. + * This is copied from linux/fs/binfmt_elf.c */ +#define NEW_AUX_ENT(id, val) \ + do { \ + *aux_elf++ = id; \ + *aux_elf++ = val; \ + } while (0) + + /* Adds up auxiliary array. */ + NEW_AUX_ENT(AT_PAGESZ, PAGE_SIZE); + NEW_AUX_ENT(AT_CLKTCK, clocksource_timer.rate); + NEW_AUX_ENT(AT_ENTRY, elf_img_info->header->e_entry); + + /* By default, MUSL will use argv[0], so this isn't required as it con */ + NEW_AUX_ENT(AT_EXECFN, 0); + + /* This should contains a bitmask of hardware capabilities */ + NEW_AUX_ENT(AT_HWCAP, HWCAP_ELF); + + /* Those value should come from elf_img_info->header, but as user application + * are compiled with linker option -N, the program header (PHDR) isn't in a PT_LOAD + * segment meaning it will not be copied in userspace. + * The main effect of this is that variable in thread local storage will not be possible. + * Those variable are *flaged* with __thread (i.e `__thread int n;`) and aren't used for now. + * This header is also used for dynamically linking, which isn't supported by SO3 anyway. + */ + NEW_AUX_ENT(AT_PHDR, 0); + NEW_AUX_ENT(AT_PHENT, 0); + NEW_AUX_ENT(AT_PHNUM, 0); - free(args_env); + /* NULL termination */ + NEW_AUX_ENT(AT_NULL, 0); - /* Now, readjust the address of the var and env strings */ + /* Remove the temporary helper. */ +#undef NEW_AUX_ENT - argc = *((int *) args_base); - __args = (char **) (args_base + sizeof(int)); + /* Copy all strings into their final destination and set pointers to them */ - /* We get the offset based on the current location and the start of the - * args_env page, then we adjust it to match our final destination. - */ - for (i = 0; i < argc; i++) - __args[i] = ((addr_t) __args[i] - (addr_t) args_env) + args_base; + /* Strings will be put just after aux */ + str_p = (char *) aux_elf; - /* Focus on the env addresses now */ - __args = (char **) (args_base + sizeof(int) + argc * sizeof(char *)); + memcpy(str_p, args_env->arg_env, args_env->strings_size); - for (i = 0; __args[i] != NULL; i++) - __args[i] = ((addr_t) __args[i] - (addr_t) args_env) + args_base; + /* Set the correct addresses into argv array */ + for (i = 0; i < args_env->argc; i++) { + argv_p_base[i] = str_p; + str_p += strlen(str_p) + 1; + } + + /* Set the correct addresses into env array */ + for (i = 0; i < args_env->envc; i++) { + env_p_base[i] = str_p; + str_p += strlen(str_p) + 1; + } + /* Ensure the NULL terminated list */ + env_p_base[args_env->envc] = NULL; + + free(args_env); } /* @@ -543,7 +558,7 @@ int setup_proc_image_replace(elf_img_info_t *elf_img_info, pcb_t *pcb, int argc, { uint32_t page_count; addr_t ret; - void *__args_env; + args_env_t *__args_env; /* FIXME: detect fragmented executable (error)? */ /* @@ -558,7 +573,7 @@ int setup_proc_image_replace(elf_img_info_t *elf_img_info, pcb_t *pcb, int argc, if (ret < 0) return ret; - __args_env = (void *) ret; + __args_env = (args_env_t *) ret; /* Reset the process stack and page count */ reset_process_stack(pcb); @@ -618,7 +633,7 @@ int setup_proc_image_replace(elf_img_info_t *elf_img_info, pcb_t *pcb, int argc, /* Prepare the arguments within the page reserved for this purpose. */ if (__args_env) - post_setup_image(__args_env); + post_setup_image(__args_env, elf_img_info); return 0; } From 3d0c2a760174c37bef0594bac3cff0a85c404c2a Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Wed, 19 Nov 2025 14:26:05 +0100 Subject: [PATCH 2/4] fix futex miss call --- so3/kernel/thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/so3/kernel/thread.c b/so3/kernel/thread.c index 2f4208b52..14873b6ff 100644 --- a/so3/kernel/thread.c +++ b/so3/kernel/thread.c @@ -270,7 +270,7 @@ void thread_exit(int exit_status) if (pcb && current() != pcb->main_thread) { if (current()->clear_child_tid) { *(current()->clear_child_tid) = 0; - do_futex(current()->clear_child_tid, FUTEX_WAKE, 1, NULL, NULL, 0, 0); + sys_do_futex(current()->clear_child_tid, FUTEX_WAKE, 1, NULL, NULL, 0); } } From 6749de8f0c6411f151d95e514d19040a0c37f326 Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Wed, 19 Nov 2025 14:47:51 +0100 Subject: [PATCH 3/4] small improvement --- so3/arch/arm32/include/asm/hwcap.h | 1 - so3/arch/arm64/include/asm/hwcap.h | 3 +-- so3/include/uapi/linux/auxvec.h | 26 ++++++++++++++++++++------ so3/kernel/process.c | 25 ++++++++++++------------- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/so3/arch/arm32/include/asm/hwcap.h b/so3/arch/arm32/include/asm/hwcap.h index 0a19d90c1..43781a0d2 100644 --- a/so3/arch/arm32/include/asm/hwcap.h +++ b/so3/arch/arm32/include/asm/hwcap.h @@ -18,7 +18,6 @@ * along with this program. If not, see . */ - #ifndef ASM_ARM_HWCAP_H #define ASM_ARM_HWCAP_H diff --git a/so3/arch/arm64/include/asm/hwcap.h b/so3/arch/arm64/include/asm/hwcap.h index 75e034c73..0364a207f 100644 --- a/so3/arch/arm64/include/asm/hwcap.h +++ b/so3/arch/arm64/include/asm/hwcap.h @@ -14,12 +14,11 @@ * along with this program. If not, see . */ - #ifndef ASM_ARM_HWCAP_H #define ASM_ARM_HWCAP_H /* - * This isn't used be MUSL on AArch64, so simply let it to 0 for now. + * This isn't used by MUSL on AArch64, so simply let it to 0 for now. */ #define HWCAP_ELF 0 diff --git a/so3/include/uapi/linux/auxvec.h b/so3/include/uapi/linux/auxvec.h index 6e7a3f5eb..bf34d20f5 100644 --- a/so3/include/uapi/linux/auxvec.h +++ b/so3/include/uapi/linux/auxvec.h @@ -1,9 +1,23 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_LINUX_AUXVEC_H -#define _UAPI_LINUX_AUXVEC_H +/* + * Copyright (C) 2025 Clément Dieperink + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ -/* Maximum count of auxiliary values */ -#define AUX_CNT 38 +#ifndef UAPI_LINUX_AUXVEC_H +#define UAPI_LINUX_AUXVEC_H + +/* Copied from linux/include/uapi/linux/auxvec.h */ /* Symbolic values for the entries in the auxiliary table put on the initial stack */ @@ -42,7 +56,7 @@ #define AT_MINSIGSTKSZ 51 /* minimal stack size for signal delivery */ #endif -/* Common from asm/auxvec.h of arm and arm64 */ +/* Common in asm/auxvec.h of arm and arm64 */ #define AT_SYSINFO_EHDR 33 #endif /* _UAPI_LINUX_AUXVEC_H */ diff --git a/so3/kernel/process.c b/so3/kernel/process.c index 1b915e462..4cfac83bb 100644 --- a/so3/kernel/process.c +++ b/so3/kernel/process.c @@ -402,7 +402,6 @@ static void release_proc_pages(pcb_t *pcb) */ addr_t preserve_args_and_env(int argc, char **argv, char **envp) { - char *args_str_p; size_t str_len; args_env_t *saved; int i; @@ -417,14 +416,14 @@ addr_t preserve_args_and_env(int argc, char **argv, char **envp) memset(saved->arg_env, 0, PAGE_SIZE); - args_str_p = (char *) saved->arg_env; + saved->strings_size = 0; /* Save args strings */ if (!argc) { /* If no arguments, add one with process name */ saved->argc = 1; - strcpy(args_str_p, current()->pcb->name); - args_str_p += strlen(args_str_p) + 1; + strcpy(&saved->arg_env[saved->strings_size], current()->pcb->name); + saved->strings_size += strlen(current()->pcb->name) + 1; } else { /* Copy all arguments strings */ saved->argc = argc; @@ -432,15 +431,15 @@ addr_t preserve_args_and_env(int argc, char **argv, char **envp) str_len = strlen(argv[i]) + 1; /* Ensure the newly copied string will not exceed the buffer size. */ - if ((addr_t) args_str_p - (addr_t) saved->arg_env + str_len > PAGE_SIZE) { + if (saved->strings_size + str_len > PAGE_SIZE) { LOG_CRITICAL("Not enougth memory allocated\n"); free(saved); return -ENOMEM; } - strcpy(args_str_p, argv[i]); - args_str_p += str_len; + strcpy(&saved->arg_env[saved->strings_size], argv[i]); + saved->strings_size += str_len; } } @@ -451,21 +450,18 @@ addr_t preserve_args_and_env(int argc, char **argv, char **envp) str_len = strlen(envp[saved->envc]) + 1; /* Ensure the newly copied string will not exceed the buffer size. */ - if ((addr_t) args_str_p - (addr_t) saved->arg_env + str_len > PAGE_SIZE) { + if (saved->strings_size + str_len > PAGE_SIZE) { LOG_CRITICAL("Not enougth memory allocated\n"); free(saved); return -ENOMEM; } - strcpy(args_str_p, envp[saved->envc]); - args_str_p += strlen(args_str_p) + 1; + strcpy(&saved->arg_env[saved->strings_size], envp[saved->envc]); + saved->strings_size += str_len; } while (envp[saved->envc++]); } - /* Save total string size for easier copy to user. */ - saved->strings_size = (addr_t) args_str_p - (addr_t) saved->arg_env; - return (addr_t) saved; } @@ -532,6 +528,9 @@ void post_setup_image(args_env_t *args_env, elf_img_info_t *elf_img_info) /* Strings will be put just after aux */ str_p = (char *) aux_elf; + /* Ensure that the strings will not overflow */ + BUG_ON(args_env->strings_size + ((addr_t) str_p - (addr_t) args_base) > PAGE_SIZE); + memcpy(str_p, args_env->arg_env, args_env->strings_size); /* Set the correct addresses into argv array */ From 2fb170763280abb326f7275537f93b63ec67538b Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Wed, 19 Nov 2025 14:54:42 +0100 Subject: [PATCH 4/4] fix clang-format from copied files --- so3/arch/arm32/include/asm/hwcap.h | 4 ++++ so3/include/uapi/linux/auxvec.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/so3/arch/arm32/include/asm/hwcap.h b/so3/arch/arm32/include/asm/hwcap.h index 43781a0d2..cf63eb016 100644 --- a/so3/arch/arm32/include/asm/hwcap.h +++ b/so3/arch/arm32/include/asm/hwcap.h @@ -21,6 +21,8 @@ #ifndef ASM_ARM_HWCAP_H #define ASM_ARM_HWCAP_H +/* clang-format off */ + /* * Hardware capabilities flags - for AT_HWCAP * Copied from Linux arch/arm/include/asm/procinfo.h @@ -60,4 +62,6 @@ */ #define HWCAP_ELF (HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_EDSP | HWCAP_TLS) +/* clang-format on */ + #endif /* ASM_ARM_HWCAP */ diff --git a/so3/include/uapi/linux/auxvec.h b/so3/include/uapi/linux/auxvec.h index bf34d20f5..e23fed76e 100644 --- a/so3/include/uapi/linux/auxvec.h +++ b/so3/include/uapi/linux/auxvec.h @@ -17,6 +17,8 @@ #ifndef UAPI_LINUX_AUXVEC_H #define UAPI_LINUX_AUXVEC_H +/* clang-format off */ + /* Copied from linux/include/uapi/linux/auxvec.h */ /* Symbolic values for the entries in the auxiliary table @@ -59,4 +61,6 @@ /* Common in asm/auxvec.h of arm and arm64 */ #define AT_SYSINFO_EHDR 33 +/* clang-format on */ + #endif /* _UAPI_LINUX_AUXVEC_H */