Skip to content

Commit

Permalink
Add command-pid member to --json-status-fd
Browse files Browse the repository at this point in the history
In cases where bwrap runs its own additional PID 1 process (e.g.
--unshare-pid), child-pid is the PID of that process, not the
PID of the user-specified COMMAND.

This is inconvenient as the user might want to send e.g. SIGTERM to the
command to give it a chance to exit gracefully.

Closes containers#553
  • Loading branch information
WGH- committed Apr 17, 2023
1 parent 9286389 commit 1f125c1
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
27 changes: 27 additions & 0 deletions bubblewrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2630,6 +2630,7 @@ main (int argc,
int clone_flags;
char *old_cwd = NULL;
pid_t pid;
pid_t command_pid;
int event_fd = -1;
int child_wait_fd = -1;
int setup_finished_pipe[] = {-1, -1};
Expand All @@ -2641,6 +2642,7 @@ main (int argc,
int res UNUSED;
cleanup_free char *args_data UNUSED = NULL;
int intermediate_pids_sockets[2] = {-1, -1};
int command_pid_sockets[2] = {-1, -1};

/* Handle --version early on before we try to acquire/drop
* any capabilities so it works in a build environment;
Expand Down Expand Up @@ -2872,6 +2874,14 @@ main (int argc,
create_pid_socketpair (intermediate_pids_sockets);
}

/* Sometimes we spawn command as immediate child, sometimes we run pid 1, sometimes there are more intermediate pids...
* For simplicity, get pid just before exec'ing command to get the real pid.
**/
if (opt_json_status_fd != -1)
{
create_pid_socketpair (command_pid_sockets);
}

pid = raw_clone (clone_flags, NULL);
if (pid == -1)
{
Expand Down Expand Up @@ -2961,6 +2971,16 @@ main (int argc,
/* Ignore res, if e.g. the child died and closed child_wait_fd we don't want to error out here */
close (child_wait_fd);

close (command_pid_sockets[1]);
command_pid = read_pid_from_socket (command_pid_sockets[0]);
close (command_pid_sockets[0]);

if (opt_json_status_fd != -1)
{
cleanup_free char *output = xasprintf ("{ \"command-pid\": %i }\n", command_pid);
dump_info (opt_json_status_fd, output, TRUE);
}

return monitor_child (event_fd, pid, setup_finished_pipe[0]);
}

Expand Down Expand Up @@ -3319,6 +3339,13 @@ main (int argc,

__debug__ (("launch executable %s\n", argv[0]));

if (opt_json_status_fd != -1)
{
close (command_pid_sockets[0]);
send_pid_on_socket (command_pid_sockets[1]);
close (command_pid_sockets[1]);
}

if (proc_fd != -1)
close (proc_fd);

Expand Down
8 changes: 8 additions & 0 deletions bwrap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -439,17 +439,25 @@
Multiple JSON documents are written to <arg choice="plain">FD</arg>,
one per line (<ulink url="https://jsonlines.org/">"JSON lines" format</ulink>).
Each line is a single JSON object.
</para><para>
After <command>bwrap</command> has started the child process inside the sandbox,
it writes an object with a <literal>child-pid</literal> member to the
<option>--json-status-fd</option> (this duplicates the older <option>--info-fd</option>).
The corresponding value is the process ID of the child process in the pid namespace from
which <command>bwrap</command> was run.
If available, the namespace IDs are also included in the object with the <literal>child-pid</literal>;
again, this duplicates the older <option>--info-fd</option>.
</para><para>
Just before COMMAND is exec'ed, the process writes its process ID with a <literal>command-pid</literal>
member. This process ID is the PID of COMMAND, and it might not match <literal>child-pid</literal>
mentioned above if <command>bwrap</command> runs additional pid 1 process(e.g. when using
<option>--unshare-pid</option>).
</para><para>
When the child process inside the sandbox exits, <command>bwrap</command> writes an object
with an exit-code member, and then closes the <option>--json-status-fd</option>. The value
corresponding to <literal>exit-code</literal> is the exit status of the child, in the usual
shell encoding (n if it exited normally with status n, or 128+n if it was killed by signal n).
</para><para>
Other members may be added to those objects in future versions of <command>bwrap</command>,
and other JSON objects may be added before or after the current objects, so readers must
ignore members and objects that they do not understand.
Expand Down

0 comments on commit 1f125c1

Please sign in to comment.