Skip to content

Commit

Permalink
Merge commit from fork
Browse files Browse the repository at this point in the history
krun: fix CVE-2025-24965
  • Loading branch information
giuseppe authored Feb 5, 2025
2 parents 73d52bd + 9c9a76a commit 4e51077
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 95 deletions.
20 changes: 20 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
* crun-1.20

- krun: fix CVE-2025-24965. The .krun_config.json file could be
created outside of the container rootfs.
- cgroup: reverted the removal of `tun/tap` from the default allow
list, this was done in crun-1.5. The `tun/tap` device is now added
by default again.
- CRIU: do not set `network_lock` unless explicitly specified.
- status: disallow container names containing slashes in their name.
- linux: Improved error message when failing to set the
`net.ipv4.ping_group_range` sysctl.
- scheduler: Ignore `ENOSYS` errors when resetting the CPU affinity
mask.
- linux: return a better error message when `pidfd_open` fails with
`EINVAL`.
- cgroup: display the absolute path to `cgroup.controllers` when a
controller is unavailable.
- exec: always call setsid. Now processes created through `exec` get
the correct process group id.

* crun-1.19.1

- linux: fix a hang if there are no reads from the tty. Use non
Expand Down
2 changes: 1 addition & 1 deletion src/libcrun/cgroup-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ cgroup_killall_path (const char *path, int signal, libcrun_error_t *err)
if (UNLIKELY (ret < 0))
return ret;

ret = write_file_with_flags (kill_file, 0, "1", 1, err);
ret = write_file_at_with_flags (AT_FDCWD, 0, 0700, kill_file, "1", 1, err);
if (ret >= 0)
return 0;

Expand Down
5 changes: 2 additions & 3 deletions src/libcrun/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -1999,8 +1999,7 @@ wait_for_process (struct wait_for_process_args *args, libcrun_error_t *err)
{
char buf[32];
size_t buf_len = snprintf (buf, sizeof (buf), "%d", args->pid);
ret = write_file_with_flags (args->context->pid_file, O_CREAT | O_TRUNC, buf,
buf_len, err);
ret = write_file_at_with_flags (AT_FDCWD, O_CREAT | O_TRUNC, 0700, args->context->pid_file, buf, buf_len, err);
if (UNLIKELY (ret < 0))
return ret;
}
Expand Down Expand Up @@ -4329,7 +4328,7 @@ libcrun_container_restore (libcrun_context_t *context, const char *id, libcrun_c
{
char buf[32];
size_t buf_len = snprintf (buf, sizeof (buf), "%d", status.pid);
ret = write_file_with_flags (context->pid_file, O_CREAT | O_TRUNC, buf, buf_len, err);
ret = write_file_at_with_flags (AT_FDCWD, O_CREAT | O_TRUNC, 0700, context->pid_file, buf, buf_len, err);
if (UNLIKELY (ret < 0))
return ret;
}
Expand Down
4 changes: 2 additions & 2 deletions src/libcrun/criu.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,15 +738,15 @@ prepare_restore_mounts (runtime_spec_schema_config_schema *def, char *root, libc
{
int ret;

ret = crun_safe_ensure_directory_at (root_fd, root, strlen (root), dest, 0755, err);
ret = crun_safe_ensure_directory_at (root_fd, root, dest, 0755, err);
if (UNLIKELY (ret < 0))
return ret;
}
else
{
int ret;

ret = crun_safe_ensure_file_at (root_fd, root, strlen (root), dest, 0755, err);
ret = crun_safe_ensure_file_at (root_fd, root, dest, 0755, err);
if (UNLIKELY (ret < 0))
return ret;
}
Expand Down
13 changes: 11 additions & 2 deletions src/libcrun/handlers/krun.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
/* libkrun has a hard-limit of 8 vCPUs per microVM. */
#define LIBKRUN_MAX_VCPUS 8

#define KRUN_CONFIG_FILE ".krun_config.json"

struct krun_config
{
void *handle;
Expand Down Expand Up @@ -176,8 +178,8 @@ libkrun_configure_container (void *cookie, enum handler_configure_phase phase,
cleanup_close int devfd = -1;
cleanup_close int rootfsfd_cleanup = -1;
runtime_spec_schema_config_schema *def = container->container_def;
bool create_sev = false;
bool is_user_ns;
bool create_sev;

if (rootfs == NULL)
rootfsfd = AT_FDCWD;
Expand All @@ -193,6 +195,7 @@ libkrun_configure_container (void *cookie, enum handler_configure_phase phase,
cleanup_free char *origin_config_path = NULL;
cleanup_free char *state_dir = NULL;
cleanup_free char *config = NULL;
cleanup_close int fd = -1;
size_t config_size;

ret = libcrun_get_state_directory (&state_dir, context->state_root, context->id, err);
Expand All @@ -207,7 +210,13 @@ libkrun_configure_container (void *cookie, enum handler_configure_phase phase,
if (UNLIKELY (ret < 0))
return ret;

ret = write_file_at (rootfsfd, ".krun_config.json", config, config_size, err);
/* CVE-2025-24965: the content below rootfs cannot be trusted because it is controlled by the user. We
must ensure the file is opened below the rootfs directory. */
fd = safe_openat (rootfsfd, rootfs, KRUN_CONFIG_FILE, WRITE_FILE_DEFAULT_FLAGS | O_NOFOLLOW, 0700, err);
if (UNLIKELY (fd < 0))
return fd;

ret = safe_write (fd, KRUN_CONFIG_FILE, config, config_size, err);
if (UNLIKELY (ret < 0))
return ret;
}
Expand Down
47 changes: 16 additions & 31 deletions src/libcrun/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ struct private_data_s
const char *rootfs;
int rootfsfd;

size_t rootfs_len;
int notify_socket_tree_fd;

struct libcrun_fd_map *mount_fds;
Expand Down Expand Up @@ -930,13 +929,12 @@ static int
open_mount_target (libcrun_container_t *container, const char *target_rel, libcrun_error_t *err)
{
const char *rootfs = get_private_data (container)->rootfs;
size_t rootfs_len = get_private_data (container)->rootfs_len;
int rootfsfd = get_private_data (container)->rootfsfd;

if (rootfsfd < 0)
return crun_make_error (err, 0, "invalid rootfs state");

return safe_openat (rootfsfd, rootfs, rootfs_len, target_rel, O_PATH | O_CLOEXEC, 0, err);
return safe_openat (rootfsfd, rootfs, target_rel, O_PATH | O_CLOEXEC, 0, err);
}

/* Attempt to open a mount of the specified type. */
Expand Down Expand Up @@ -1024,7 +1022,6 @@ do_masked_or_readonly_path (libcrun_container_t *container, const char *rel_path
libcrun_error_t *err)
{
unsigned long mount_flags = 0;
size_t rootfs_len = get_private_data (container)->rootfs_len;
const char *rootfs = get_private_data (container)->rootfs;
int rootfsfd = get_private_data (container)->rootfsfd;
cleanup_close int pathfd = -1;
Expand All @@ -1035,7 +1032,7 @@ do_masked_or_readonly_path (libcrun_container_t *container, const char *rel_path
if (rel_path[0] == '/')
rel_path++;

pathfd = safe_openat (rootfsfd, rootfs, rootfs_len, rel_path, O_PATH | O_CLOEXEC, 0, err);
pathfd = safe_openat (rootfsfd, rootfs, rel_path, O_PATH | O_CLOEXEC, 0, err);
if (UNLIKELY (pathfd < 0))
{
if (errno != ENOENT && errno != EACCES)
Expand Down Expand Up @@ -1579,7 +1576,6 @@ libcrun_create_dev (libcrun_container_t *container, int devfd, int srcfd,
cleanup_close int fd = -1;
int rootfsfd = get_private_data (container)->rootfsfd;
const char *rootfs = get_private_data (container)->rootfs;
size_t rootfs_len = get_private_data (container)->rootfs_len;
if (is_empty_string (fullname))
return crun_make_error (err, EINVAL, "device path is empty");
// Normalize the path by removing trailing slashes.
Expand Down Expand Up @@ -1609,7 +1605,7 @@ libcrun_create_dev (libcrun_container_t *container, int devfd, int srcfd,
{
const char *rel_path = consume_slashes (normalized_path);

fd = crun_safe_create_and_open_ref_at (false, rootfsfd, rootfs, rootfs_len, rel_path, 0755, err);
fd = crun_safe_create_and_open_ref_at (false, rootfsfd, rootfs, rel_path, 0755, err);
if (UNLIKELY (fd < 0))
return fd;
}
Expand Down Expand Up @@ -1644,7 +1640,7 @@ libcrun_create_dev (libcrun_container_t *container, int devfd, int srcfd,
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "mknod `%s`", device->path);

fd = safe_openat (devfd, rootfs, rootfs_len, rel_dev, O_PATH | O_CLOEXEC, 0, err);
fd = safe_openat (devfd, rootfs, rel_dev, O_PATH | O_CLOEXEC, 0, err);
if (UNLIKELY (fd < 0))
return fd;

Expand Down Expand Up @@ -1676,14 +1672,12 @@ libcrun_create_dev (libcrun_container_t *container, int devfd, int srcfd,
dirfd = dup (rootfsfd);
else
{
dirfd = safe_openat (rootfsfd, rootfs, rootfs_len, dirname,
O_DIRECTORY | O_PATH | O_CLOEXEC, 0, err);
dirfd = safe_openat (rootfsfd, rootfs, dirname, O_DIRECTORY | O_PATH | O_CLOEXEC, 0, err);
if (dirfd < 0 && ensure_parent_dir)
{
crun_error_release (err);

dirfd = crun_safe_create_and_open_ref_at (true, rootfsfd, rootfs,
rootfs_len, dirname, 0755, err);
dirfd = crun_safe_create_and_open_ref_at (true, rootfsfd, rootfs, dirname, 0755, err);
}
}
if (UNLIKELY (dirfd < 0))
Expand All @@ -1697,7 +1691,7 @@ libcrun_create_dev (libcrun_container_t *container, int devfd, int srcfd,
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "mknod `%s`", device->path);

fd = safe_openat (dirfd, rootfs, rootfs_len, basename, O_PATH | O_CLOEXEC, 0, err);
fd = safe_openat (dirfd, rootfs, basename, O_PATH | O_CLOEXEC, 0, err);
if (UNLIKELY (fd < 0))
return crun_make_error (err, errno, "open `%s`", device->path);

Expand Down Expand Up @@ -1896,7 +1890,6 @@ do_pivot (libcrun_container_t *container, const char *rootfs, libcrun_error_t *e
static int
append_tmpfs_mode_if_missing (libcrun_container_t *container, runtime_spec_schema_defs_mount *mount, char **data, libcrun_error_t *err)
{
size_t rootfs_len = get_private_data (container)->rootfs_len;
const char *rootfs = get_private_data (container)->rootfs;
int rootfsfd = get_private_data (container)->rootfsfd;
bool empty_data = is_empty_string (*data);
Expand All @@ -1907,7 +1900,7 @@ append_tmpfs_mode_if_missing (libcrun_container_t *container, runtime_spec_schem
if (*data != NULL && strstr (*data, "mode="))
return 0;

fd = safe_openat (rootfsfd, rootfs, rootfs_len, mount->destination, O_CLOEXEC | O_RDONLY, 0, err);
fd = safe_openat (rootfsfd, rootfs, mount->destination, O_CLOEXEC | O_RDONLY, 0, err);
if (fd < 0)
{
if (crun_error_get_errno (err) != ENOENT)
Expand Down Expand Up @@ -1982,7 +1975,7 @@ append_mode_if_missing (char *data, const char *mode)
}

static int
safe_create_symlink (int rootfsfd, const char *rootfs, size_t rootfs_len, const char *target, const char *destination, libcrun_error_t *err)
safe_create_symlink (int rootfsfd, const char *rootfs, const char *target, const char *destination, libcrun_error_t *err)
{
cleanup_close int parent_dir_fd = -1;
cleanup_free char *buffer = NULL;
Expand All @@ -1995,8 +1988,7 @@ safe_create_symlink (int rootfsfd, const char *rootfs, size_t rootfs_len, const
buffer = xstrdup (destination);
part = dirname (buffer);

parent_dir_fd = crun_safe_create_and_open_ref_at (true, rootfsfd, rootfs, rootfs_len,
part, 0755, err);
parent_dir_fd = crun_safe_create_and_open_ref_at (true, rootfsfd, rootfs, part, 0755, err);
if (UNLIKELY (parent_dir_fd < 0))
return crun_make_error (err, errno, "symlink creation");

Expand Down Expand Up @@ -2040,7 +2032,6 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
size_t i;
int ret;
runtime_spec_schema_config_schema *def = container->container_def;
size_t rootfs_len = get_private_data (container)->rootfs_len;
const char *systemd_cgroup_v1 = get_force_cgroup_v1_annotation (container);
cleanup_close_map struct libcrun_fd_map *mount_fds = NULL;

Expand Down Expand Up @@ -2124,7 +2115,7 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
if (UNLIKELY (len < 0))
return len;

ret = safe_create_symlink (rootfsfd, rootfs, rootfs_len, target, def->mounts[i]->destination, err);
ret = safe_create_symlink (rootfsfd, rootfs, target, def->mounts[i]->destination, err);
if (UNLIKELY (ret < 0))
return ret;

Expand Down Expand Up @@ -2162,8 +2153,7 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
bool is_dir = S_ISDIR (src_mode);

/* Make sure any other directory/file is created and take a O_PATH reference to it. */
ret = crun_safe_create_and_open_ref_at (is_dir, rootfsfd, rootfs, rootfs_len, target,
is_dir ? 01755 : 0755, err);
ret = crun_safe_create_and_open_ref_at (is_dir, rootfsfd, rootfs, target, is_dir ? 01755 : 0755, err);
if (UNLIKELY (ret < 0))
return ret;

Expand Down Expand Up @@ -2236,7 +2226,7 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
{
int destfd, tmpfd;

destfd = safe_openat (rootfsfd, rootfs, rootfs_len, target, O_CLOEXEC | O_DIRECTORY, 0, err);
destfd = safe_openat (rootfsfd, rootfs, target, O_CLOEXEC | O_DIRECTORY, 0, err);
if (UNLIKELY (destfd < 0))
return crun_error_wrap (err, "open target to write for tmpcopyup");

Expand All @@ -2253,7 +2243,7 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
const bool is_dir = S_ISDIR (src_mode);
cleanup_close int dfd = -1;

dfd = safe_openat (rootfsfd, rootfs, rootfs_len, target, O_RDONLY | O_PATH | O_CLOEXEC | (is_dir ? O_DIRECTORY : 0), 0, err);
dfd = safe_openat (rootfsfd, rootfs, target, O_RDONLY | O_PATH | O_CLOEXEC | (is_dir ? O_DIRECTORY : 0), 0, err);
if (UNLIKELY (dfd < 0))
return crun_make_error (err, errno, "open mount target `/%s`", target);

Expand All @@ -2275,8 +2265,6 @@ int
libcrun_container_do_bind_mount (libcrun_container_t *container, char *mount_source, char *mount_destination, char **mount_options, size_t mount_options_len, libcrun_error_t *err)
{
int ret, rootfsfd;
size_t rootfs_len = get_private_data (container)->rootfs_len;

const char *target = consume_slashes (mount_destination);
cleanup_free char *data = NULL;
unsigned long flags = 0;
Expand Down Expand Up @@ -2314,8 +2302,7 @@ libcrun_container_do_bind_mount (libcrun_container_t *container, char *mount_sou
}

/* Make sure any other directory/file is created and take a O_PATH reference to it. */
ret = crun_safe_create_and_open_ref_at (is_dir, rootfsfd, rootfs, rootfs_len, target,
is_dir ? 01755 : 0755, err);
ret = crun_safe_create_and_open_ref_at (is_dir, rootfsfd, rootfs, target, is_dir ? 01755 : 0755, err);
if (UNLIKELY (ret < 0))
return ret;

Expand Down Expand Up @@ -2617,7 +2604,6 @@ libcrun_set_mounts (struct container_entrypoint_s *entrypoint_args, libcrun_cont

get_private_data (container)->rootfs = rootfs;
get_private_data (container)->rootfsfd = rootfsfd;
get_private_data (container)->rootfs_len = rootfs ? strlen (rootfs) : 0;

// configure handler mounts
ret = libcrun_container_notify_handler (entrypoint_args, HANDLER_CONFIGURE_MOUNTS, container, rootfs, err);
Expand Down Expand Up @@ -2693,8 +2679,7 @@ libcrun_set_mounts (struct container_entrypoint_s *entrypoint_args, libcrun_cont
libcrun_error_t tmp_err = NULL;
const char *rel_cwd = consume_slashes (def->process->cwd);
/* Ignore errors here and let it fail later. */
(void) crun_safe_ensure_directory_at (rootfsfd, rootfs, strlen (rootfs),
rel_cwd, 0755, &tmp_err);
(void) crun_safe_ensure_directory_at (rootfsfd, rootfs, rel_cwd, 0755, &tmp_err);
crun_error_release (&tmp_err);
}

Expand Down
4 changes: 2 additions & 2 deletions src/libcrun/seccomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,9 +849,9 @@ libcrun_copy_seccomp (struct libcrun_seccomp_gen_ctx_s *gen_ctx, const char *b64
if (UNLIKELY (consumed != (int) in_size))
return crun_make_error (err, 0, "invalid seccomp BPF data");

ret = safe_write (gen_ctx->fd, bpf_data, (ssize_t) size);
ret = safe_write (gen_ctx->fd, "seccomp fd", bpf_data, size, err);
if (UNLIKELY (ret < 0))
return crun_make_error (err, 0, "write to seccomp fd");
return ret;

return 0;
}
Expand Down
8 changes: 3 additions & 5 deletions src/libcrun/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,9 @@ libcrun_write_container_status (const char *state_root, const char *id, libcrun_
if (UNLIKELY (r != yajl_gen_status_ok))
goto yajl_error;

if (UNLIKELY (safe_write (fd_write, buf, (ssize_t) len) < 0))
{
ret = crun_make_error (err, errno, "cannot write status file");
goto exit;
}
ret = safe_write (fd_write, "status file", buf, len, err);
if (UNLIKELY (r < 0))
goto exit;

close_and_reset (&fd_write);

Expand Down
Loading

1 comment on commit 4e51077

@packit-as-a-service
Copy link

Choose a reason for hiding this comment

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

podman-next COPR build failed. @containers/packit-build please check.

Please sign in to comment.