Skip to content

init: Fix args processing#599

Merged
slp merged 3 commits intocontainers:mainfrom
mz-pdm:pdm-init-args
Mar 27, 2026
Merged

init: Fix args processing#599
slp merged 3 commits intocontainers:mainfrom
mz-pdm:pdm-init-args

Conversation

@mz-pdm
Copy link
Copy Markdown
Collaborator

@mz-pdm mz-pdm commented Mar 23, 2026

The command line argument processing in init.c writes outside allocated memory and silently drops command line arguments when there are many. This PR fixes these problems and #323.

@mz-pdm
Copy link
Copy Markdown
Collaborator Author

mz-pdm commented Mar 23, 2026

I don't know how to get "entrypoint" entry in .krun_config.json so I couldn't test the corresponding part of the fix.

@slp
Copy link
Copy Markdown
Collaborator

slp commented Mar 24, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an important issue of buffer overflows and silent argument dropping by replacing the fixed-size MAX_ARGS with dynamic memory allocation based on the actual number of arguments. The changes in config_parse_args correctly implement this. However, the changes in concat_entrypoint_argv introduce a critical bug by using an uninitialized variable n_args to calculate the allocation size, which will lead to undefined behavior. This must be fixed before merging.

@slp
Copy link
Copy Markdown
Collaborator

slp commented Mar 25, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors argument parsing and concatenation functions in init.c by removing the fixed MAX_ARGS limit and dynamically allocating memory based on the actual number of arguments. The changes include updating config_parse_args to use token->size for allocation and concat_entrypoint_argv to calculate the total number of arguments before allocation. Review feedback highlights critical issues where the return values of malloc are not checked in both config_parse_args and concat_entrypoint_argv, which could lead to segmentation faults. Additionally, an efficiency improvement was suggested for concat_entrypoint_argv to avoid redundant iterations and use memcpy for copying arguments.

Comment on lines +695 to 708
for (i = 0; entrypoint[i]; i++)
n_args++;
for (j = 0; config_argv[j]; j++)
n_args++;

argv = malloc(MAX_ARGS * sizeof(char *));
argv = malloc((n_args + 1) * sizeof(char *));

for (i = 0; i < MAX_ARGS && entrypoint[i]; i++) {
for (i = 0; entrypoint[i]; i++) {
argv[i] = entrypoint[i];
}

for (j = 0; j < MAX_ARGS && config_argv[j]; i++, j++) {
for (j = 0; config_argv[j]; i++, j++) {
argv[i] = config_argv[j];
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

There are two issues in this function:

  1. Critical: The return value of malloc on line 700 is not checked. If malloc fails, it will cause a segmentation fault on line 703.
  2. Medium: The current implementation iterates over entrypoint and config_argv arrays twice (once for counting, once for copying). This is inefficient.

A more robust and efficient implementation would check for malloc failure and use memcpy for copying after determining the lengths of the arrays. Here is a suggested refactoring of the function body:

    char **argv;
    int entrypoint_len = 0;
    int config_argv_len = 0;

    while (entrypoint[entrypoint_len]) {
        entrypoint_len++;
    }
    while (config_argv[config_argv_len]) {
        config_argv_len++;
    }

    int n_args = entrypoint_len + config_argv_len;
    argv = malloc((n_args + 1) * sizeof(char *));
    if (!argv) {
        perror("malloc");
        return NULL;
    }

    memcpy(argv, entrypoint, entrypoint_len * sizeof(char *));
    memcpy(argv + entrypoint_len, config_argv, config_argv_len * sizeof(char *));
    argv[n_args] = NULL;

    return argv;

Note that i and j would need to be removed from the variable declarations if you use this approach.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may not be a bad idea but it introduces unnecessary changes to the problem being fixed and I consider the original code a bit better readable. As for malloc() return value, this is handled in the newly added commit.

mz-pdm added 3 commits March 25, 2026 19:04
There are a few malloc() calls in init.c without accompanied checks for
their return values.  All of them are in argv processing.  Let's add the
missing checks to them.

In case of an allocation error, we simply print the error and return
NULL, which is similar to handling memory allocation errors in other
places in init.c.  NULL is a valid return value in the given cases.  It
leads to the arguments being ignored and running the default command
defined in init.c (/bin/sh).  This is not completely correct but is
still better than the original segmentation faults.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
The number of the command line arguments is limited by MAX_ARGS constant
in init.c.  When parsing the arguments there, `argv' arrays to store
pointers to them are allocated with wrong sizes:

- Space for the closing NULL marker is not allocated.

- In config_parse_args, there is no check on MAX_ARGS when adding the
  arguments to the array.

- In concat_entrypoint_argv, there can be up to 2 * MAX_ARGS
  entries (two loops adding them, each with up to MAX_ARGS iterations)
  but the allocated array size is only MAX_ARGS.

This patch fixes these problems.  When on it, the useless `j' variable
in config_parse_args that just mimics `i' value is removed.

Silently ignoring the provided command line arguments is generally wrong
and dangerous (imagine the last argument is e.g. --dry-run).  This is
addressed in the followup patch; this patch serves just for starting
from a correct basis.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
init.c imposes limit of MAX_ARGS command line arguments.  If there are
more arguments then they are silently ignored.  Which is wrong and
dangerous, imagine one of those arguments being e.g. --dry-run or
--safe.

There is no reason to limit the number of the arguments to 32 (the value
of MAX_ARGS) declared in init.c.  Common limits on the number of
arguments are much higher, if any.  The arguments are passed in the
config file provided to the VM, it's the responsibility of the caller to
provide sane arguments.  Which means we can lift the limit completely
and to allocate `argv' arrays to the exact size needed rather than to
the predefined maximum limit.

For example, the following command works fine for me with this patch,
while printing only the first 31 numbers previously:

  podman run --runtime krun --rm -t \
         docker.io/library/alpine echo $(seq 1 10000)

Fixes: containers#323

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
@mz-pdm
Copy link
Copy Markdown
Collaborator Author

mz-pdm commented Mar 25, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors argument parsing and concatenation functions (config_parse_args and concat_entrypoint_argv) in init.c. It removes the MAX_ARGS constant and replaces fixed-size array allocations with dynamic memory allocation based on the actual number of arguments. Additionally, malloc error checks and cleanup logic have been added to improve robustness. I have no feedback to provide on the current changes.

@mz-pdm
Copy link
Copy Markdown
Collaborator Author

mz-pdm commented Mar 25, 2026

The CI failures look unrelated, is there a way to rerun?

Copy link
Copy Markdown
Collaborator

@slp slp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@slp slp merged commit c58f00a into containers:main Mar 27, 2026
14 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants