diff options
-rw-r--r-- | nuttx/Documentation/NuttxUserGuide.html | 3 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_exec.c | 47 | ||||
-rw-r--r-- | nuttx/binfmt/binfmt_unloadmodule.c | 8 |
3 files changed, 43 insertions, 15 deletions
diff --git a/nuttx/Documentation/NuttxUserGuide.html b/nuttx/Documentation/NuttxUserGuide.html index 44445e8ce..eb5a27f53 100644 --- a/nuttx/Documentation/NuttxUserGuide.html +++ b/nuttx/Documentation/NuttxUserGuide.html @@ -271,8 +271,7 @@ int task_create(char *name, int priority, int stack_size, main_t entry, char * c </P> <p> Note that an arbitrary number of arguments may be passed to the - spawned functions. The maximum umber of arguments is an OS - configuration parameter (<code>CONFIG_MAX_TASK_ARGS</code>). + spawned functions. </p> <p> The arguments are copied (via <code>strdup</code>) so that the diff --git a/nuttx/binfmt/binfmt_exec.c b/nuttx/binfmt/binfmt_exec.c index a250b2269..0dbd13b0e 100644 --- a/nuttx/binfmt/binfmt_exec.c +++ b/nuttx/binfmt/binfmt_exec.c @@ -53,6 +53,11 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* This is an artificial limit to detect error conditions where an argv[] + * list is not properly terminated. + */ + +#define MAX_EXEC_ARGS 256 /**************************************************************************** * Private Function Prototypes @@ -80,31 +85,51 @@ static inline int binfmt_copyargv(FAR struct binary_s *bin, FAR char * const *ar { #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) FAR char *ptr; + size_t argvsize; size_t argsize; + int nargs; int i; - /* Get the size of the argument list */ + /* Get the number of arguments and the size of the argument list */ + bin->argv = (FAR char **)NULL; bin->argbuffer = (FAR char *)NULL; i = 0; if (argv) { argsize = 0; - for (i = 0; i < CONFIG_MAX_TASK_ARGS && argv[i]; i++) + nargs = 0; + + for (i = 0; argv[i]; i++) { + /* Increment the size of the allocation with the size of the next string */ + argsize += (strlen(argv[i]) + 1); + nargs++; + + /* This is a sanity check to prevent running away with an unterminated + * argv[] list. MAX_EXEC_ARGS should be sufficiently large that this + * never happens in normal usage. + */ + + if (nargs > MAX_EXEC_ARGS) + { + bdbg("ERROR: Too many arguments: %lu\n", (unsigned long)argvsize); + return -E2BIG; + } } bvdbg("args=%d argsize=%lu\n", i, (unsigned long)argsize); - /* Allocate a temporary argument buffer */ + /* Allocate the argv array and an argument buffer */ i = 0; if (argsize > 0) { - bin->argbuffer = (FAR char *)kmm_malloc(argsize); + argvsize = (nargs + 1) * sizeof(FAR char *); + bin->argbuffer = (FAR char *)kmm_malloc(argvsize + argsize); if (!bin->argbuffer) { bdbg("ERROR: Failed to allocate the argument buffer\n"); @@ -113,22 +138,20 @@ static inline int binfmt_copyargv(FAR struct binary_s *bin, FAR char * const *ar /* Copy the argv list */ - ptr = bin->argbuffer; - for (; i < CONFIG_MAX_TASK_ARGS && argv[i]; i++) + binp->argv = (FAR char **)bin->argbuffer; + ptr = bin->argbuffer + argvsize; + for (; i < argv[i]; i++) { bin->argv[i] = ptr; argsize = strlen(argv[i]) + 1; memcpy(ptr, argv[i], argsize); ptr += argsize; } - } - } - /* Nullify the remainder of the list */ + /* Terminate the argv[] list */ - for (; i <= CONFIG_MAX_TASK_ARGS; i++) - { - bin->argv[i] = NULL; + bin->argv[i] = (FAR char *)NULL; + } } return OK; diff --git a/nuttx/binfmt/binfmt_unloadmodule.c b/nuttx/binfmt/binfmt_unloadmodule.c index ce1b0e53d..535942b0f 100644 --- a/nuttx/binfmt/binfmt_unloadmodule.c +++ b/nuttx/binfmt/binfmt_unloadmodule.c @@ -228,13 +228,19 @@ int unload_module(FAR struct binary_s *binp) #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) void binfmt_freeargv(FAR struct binary_s *binp) { + /* Is there an allocated argument buffer */ + if (binp->argbuffer) { /* Free the argument buffer */ kmm_free(binp->argbuffer); - binp->argbuffer = NULL; } + + /* Nullify the allocated argv[] array and the argument buffer pointers */ + + binp->argbuffer = (FAR char *)NULL; + binp->argv = (FAR char **)NULL; } #endif |