Skip to content

Commit

Permalink
Merge pull request #386 from giuseppe/improve-exec-errors
Browse files Browse the repository at this point in the history
linux: report exec errors while setting up tty
  • Loading branch information
rhatdan authored Jun 5, 2020
2 parents 0c9b75f + 2694bb5 commit 5ea2786
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 82 deletions.
98 changes: 30 additions & 68 deletions src/libcrun/container.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* crun - OCI runtime written in C
*
* Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano <[email protected]>
* Copyright (C) 2017, 2018, 2019, 2020 Giuseppe Scrivano <[email protected]>
* crun is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
Expand Down Expand Up @@ -1369,26 +1369,27 @@ flush_fd_to_err (libcrun_context_t *context, int terminal_fd)
fsync (2);
}

static void
cleanup_watch (libcrun_context_t *context, pid_t init_pid, runtime_spec_schema_config_schema *def, const char *id, int sync_socket, int terminal_fd)
static int
cleanup_watch (libcrun_context_t *context, pid_t init_pid, runtime_spec_schema_config_schema *def, const char *id, int sync_socket, int terminal_fd, libcrun_error_t *err)
{
libcrun_error_t err = NULL;
container_delete_internal (context, def, id, 1, true, &err);
crun_error_release (&err);
libcrun_error_t tmp_err = NULL;
container_delete_internal (context, def, id, 1, true, &tmp_err);
crun_error_release (&tmp_err);

if (init_pid)
kill (init_pid, SIGKILL);

sync_socket_wait_sync (context, sync_socket, true, &err);
if (err)
sync_socket_wait_sync (context, sync_socket, true, &tmp_err);
if (tmp_err)
{
if (context->output_handler)
context->output_handler (err->status, err->msg, false, context->output_handler_arg);
crun_error_release (&err);
crun_error_release (err);
*err = tmp_err;
}

if (terminal_fd >= 0)
flush_fd_to_err (context, terminal_fd);

return -1;
}

static int
Expand Down Expand Up @@ -1627,39 +1628,27 @@ libcrun_container_run_internal (libcrun_container_t *container, libcrun_context_

ret = libcrun_cgroup_enter (&cg, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

if (def->linux && def->linux->resources)
{
ret = libcrun_update_cgroup_resources (cgroup_mode,
def->linux->resources,
cgroup_path, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);
}
}

/* sync 1. */
ret = sync_socket_send_sync (sync_socket, true, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

/* sync 2. */
ret = sync_socket_wait_sync (context, sync_socket, false, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

/* The container is waiting that we write back. In this phase we can launch the
prestart hooks. */
Expand All @@ -1669,21 +1658,15 @@ libcrun_container_run_internal (libcrun_container_t *container, libcrun_context_
(hook **) def->hooks->prestart,
def->hooks->prestart_len, hooks_out_fd, hooks_err_fd, err);
if (UNLIKELY (ret != 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);
}
if (def->hooks && def->hooks->create_runtime_len)
{
ret = do_hooks (def, pid, context->id, false, NULL, "created",
(hook **) def->hooks->create_runtime,
def->hooks->create_runtime_len, hooks_out_fd, hooks_err_fd, err);
if (UNLIKELY (ret != 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);
}

if (seccomp_fd >= 0)
Expand All @@ -1697,78 +1680,57 @@ libcrun_container_run_internal (libcrun_container_t *container, libcrun_context_

ret = libcrun_generate_seccomp (container, seccomp_fd, seccomp_gen_options, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);
close_and_reset (&seccomp_fd);
}

/* sync 3. */
ret = sync_socket_send_sync (sync_socket, true, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

if (def->process && def->process->terminal && !detach && context->console_socket == NULL)
{
terminal_fd = receive_fd_from_socket (socket_pair_0, err);
if (UNLIKELY (terminal_fd < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return terminal_fd;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

close_and_reset (&socket_pair_0);

ret = libcrun_setup_terminal_master (terminal_fd, &orig_terminal, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return terminal_fd;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);
}

/* sync 4. */
ret = sync_socket_wait_sync (context, sync_socket, false, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

ret = close_and_reset (&sync_socket);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

get_current_timestamp (created);
ret = write_container_status (container, context, pid, cgroup_path, scope, created, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);

if (def->hooks && def->hooks->poststart_len)
{
ret = do_hooks (def, pid, context->id, true, NULL, "running",
(hook **) def->hooks->poststart,
def->hooks->poststart_len, hooks_out_fd, hooks_err_fd, err);
if (UNLIKELY (ret < 0))
{
cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd);
return ret;
}
return cleanup_watch (context, pid, def, context->id, sync_socket, terminal_fd, err);
}

ret = wait_for_process (pid, context, terminal_fd, notify_socket, container_ready_fd, err);
if (!context->detach)
cleanup_watch (context, 0, def, context->id, sync_socket, terminal_fd);
{
cleanup_watch (context, 0, def, context->id, sync_socket, terminal_fd, err);
crun_error_release (err);
}

return ret;
}
Expand Down
126 changes: 112 additions & 14 deletions src/libcrun/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -2839,6 +2839,94 @@ libcrun_run_linux_container (libcrun_container_t *container,
_exit (EXIT_FAILURE);
}

static bool
read_error_from_sync_socket (int sync_socket_fd, int *error, char **str)
{
cleanup_free char *b = NULL;
size_t size;
int code;
int ret;

ret = TEMP_FAILURE_RETRY (read (sync_socket_fd, &code, sizeof (code)));
if (UNLIKELY (ret < 0))
return false;

*error = code;

ret = TEMP_FAILURE_RETRY (read (sync_socket_fd, &size, sizeof (size)));
if (UNLIKELY (ret < 0))
return false;

if (size == 0)
return false;

if (size > 1024)
size = 1024;

b = xmalloc (size + 1);
ret = TEMP_FAILURE_RETRY (read (sync_socket_fd, b, size));
if (UNLIKELY (ret < 0))
return false;

b[ret] = '\0';

*str = b;
b = NULL;
return true;
}

static bool
send_error_to_sync_socket (int sync_socket_fd, libcrun_error_t *err)
{
int ret;
int code;
size_t size;
char *msg;

if (err == NULL || *err == NULL)
return false;

code = crun_error_get_errno (err);

/* dummy terminal fd. */
ret = TEMP_FAILURE_RETRY (write (sync_socket_fd, "1", 1));
if (UNLIKELY (ret < 0))
return false;

ret = TEMP_FAILURE_RETRY (write (sync_socket_fd, &code, sizeof (code)));
if (UNLIKELY (ret < 0))
return false;

msg = (*err)->msg;
size = strlen (msg) + 1;
ret = TEMP_FAILURE_RETRY (write (sync_socket_fd, &size, sizeof (size)));
if (UNLIKELY (ret < 0))
return false;

ret = TEMP_FAILURE_RETRY (write (sync_socket_fd, msg, size));
if (UNLIKELY (ret < 0))
return false;

return true;
}

static __attribute__ ((noreturn)) void
send_error_to_sync_socket_and_die (int sync_socket_fd, libcrun_error_t *err)
{
char *msg;

if (err == NULL || *err == NULL)
_exit (EXIT_FAILURE);

if (send_error_to_sync_socket (sync_socket_fd, err))
_exit (EXIT_FAILURE);

errno = crun_error_get_errno (err);
msg = (*err)->msg;
libcrun_fail_with_error (errno, msg);
_exit (EXIT_FAILURE);
}

static int
join_process_parent_helper (pid_t child_pid,
int sync_socket_fd,
Expand Down Expand Up @@ -2886,8 +2974,13 @@ join_process_parent_helper (pid_t child_pid,
ret = receive_fd_from_socket (sync_fd, err);
if (UNLIKELY (ret < 0))
{
crun_error_release (err);
return crun_make_error (err, errno, "receive fd");
int err_code;
cleanup_free char *err_str = NULL;

if (read_error_from_sync_socket (sync_fd, &err_code, &err_str))
return crun_make_error (err, err_code, "%s", err_str);

return crun_error_wrap (err, "receive fd");
}
*terminal_fd = ret;
}
Expand Down Expand Up @@ -3035,30 +3128,35 @@ libcrun_join_process (libcrun_container_t *container, pid_t pid_to_join, libcrun
{
cleanup_close int master_fd = -1;

if (setsid () < 0)
libcrun_fail_with_error (errno, "setsid");
ret = setsid ();
if (ret < 0)
{
crun_make_error (err, errno, "setsid");
send_error_to_sync_socket_and_die (sync_fd, err);
}

ret = setgid (0);
if (UNLIKELY (ret < 0))
libcrun_fail_with_error (errno, "setgid");
{
crun_make_error (err, errno, "setgid");
send_error_to_sync_socket_and_die (sync_fd, err);
}

ret = setuid (0);
if (UNLIKELY (ret < 0))
libcrun_fail_with_error (errno, "setuid");
{
crun_make_error (err, errno, "setuid");
send_error_to_sync_socket_and_die (sync_fd, err);
}

master_fd = open_terminal (container, &slave, err);
if (UNLIKELY (master_fd < 0))
{
crun_error_write_warning_and_release (stderr, &err);
_exit (EXIT_FAILURE);
}
send_error_to_sync_socket_and_die (sync_fd, err);


ret = send_fd_to_socket (sync_fd, master_fd, err);
if (UNLIKELY (ret < 0))
{
crun_error_write_warning_and_release (stderr, &err);
_exit (EXIT_FAILURE);
}
send_error_to_sync_socket_and_die (sync_fd, err);
}

if (r < 0)
Expand Down

0 comments on commit 5ea2786

Please sign in to comment.