Skip to content

Commit

Permalink
Merge pull request #173 from giuseppe/fix-symlink-resolution
Browse files Browse the repository at this point in the history
utils: if the path exists check if it a directory
  • Loading branch information
giuseppe authored Nov 9, 2019
2 parents 9fd0359 + 508bf70 commit 91db0f4
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 37 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AC_PREREQ([2.69])
AC_INIT([crun], [0.10.4], [[email protected]])
AC_INIT([crun], [0.10.5], [[email protected]])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
Expand Down
4 changes: 2 additions & 2 deletions src/libcrun/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ enter_cgroup_subsystem (pid_t pid, const char *subsystem, const char *path, int
xasprintf (&cgroup_path, "/sys/fs/cgroup/%s%s", subsystem, path ? path : "");
if (ensure_missing)
{
ret = crun_ensure_directory (cgroup_path, 0755, err);
ret = crun_ensure_directory (cgroup_path, 0755, false, err);
if (UNLIKELY (ret < 0))
{
if (errno != EROFS)
Expand Down Expand Up @@ -461,7 +461,7 @@ enter_cgroup (int cgroup_mode, pid_t pid, const char *path, bool ensure_missing,
xasprintf (&cgroup_path, "/sys/fs/cgroup/%s", path);
if (ensure_missing)
{
ret = crun_ensure_directory (cgroup_path, 0755, err);
ret = crun_ensure_directory (cgroup_path, 0755, false, err);
if (UNLIKELY (ret < 0))
return ret;
}
Expand Down
13 changes: 7 additions & 6 deletions src/libcrun/chroot_realpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]
if (path[2] == '\0' || path[2] == '/') {
path += 2;
/* Ignore ".." at root. */
if (new_path == got_path_root + 1)
if (new_path == got_path_root || new_path[-1] != '/')
continue;
/* Handle ".." by backing up. */
while ((--new_path)[-1] != '/');
Expand Down Expand Up @@ -145,6 +145,8 @@ char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]
return NULL;
}
} else {
size_t sprintf_len;

/* Note: readlink doesn't add the null byte. */
link_path[n] = '\0';
if (*link_path == '/')
Expand All @@ -153,14 +155,13 @@ char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]
else
/* Otherwise back up over this component. */
while (*(--new_path) != '/');
/* Safe sex check. */
if (strlen(path) + n >= PATH_MAX - 2) {

/* Insert symlink contents into path. */
sprintf_len = snprintf(copy_path, PATH_MAX - 2, "%s%s", link_path, path);
if (sprintf_len >= PATH_MAX - 2) {
__set_errno(ENAMETOOLONG);
return NULL;
}
/* Insert symlink contents into path. */
strcat(link_path, path);
strcpy(copy_path, link_path);
path = copy_path;
}
#endif /* S_IFLNK */
Expand Down
7 changes: 6 additions & 1 deletion src/libcrun/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,12 @@ libcrun_container_run (libcrun_context_t *context, libcrun_container_t *containe
return ret;

if (!detach && (options & LIBCRUN_RUN_OPTIONS_PREFORK) == 0)
return libcrun_container_run_internal (container, context, -1, err);
{
ret = libcrun_copy_config_file (context->id, context->state_root, context->bundle, err);
if (UNLIKELY (ret < 0))
return ret;
return libcrun_container_run_internal (container, context, -1, err);
}

ret = pipe (container_ret_status);
if (UNLIKELY (ret < 0))
Expand Down
31 changes: 22 additions & 9 deletions src/libcrun/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,10 +604,13 @@ create_dev (libcrun_container_t *container, int devfd, struct device_s *device,
const char *fullname = device->path;
if (binds)
{
cleanup_free char *path_to_container = NULL;
xasprintf (&path_to_container, "%s%s", rootfs, device->path);
char *path_to_container, buffer[PATH_MAX];

ret = crun_ensure_file (path_to_container, 0700, err);
path_to_container = chroot_realpath (rootfs, device->path, buffer);
if (path_to_container == NULL)
return crun_make_error (err, errno, "cannot resolve '%s'", device->path);

ret = crun_ensure_file (path_to_container, 0700, true, err);
if (UNLIKELY (ret < 0))
return ret;

Expand Down Expand Up @@ -645,7 +648,7 @@ create_dev (libcrun_container_t *container, int devfd, struct device_s *device,
if (tmp != resolved_path)
{
*tmp = '\0';
ret = crun_ensure_directory (resolved_path, 0700, err);
ret = crun_ensure_directory (resolved_path, 0700, true, err);
if (UNLIKELY (ret < 0))
return ret;
*tmp = '/';
Expand Down Expand Up @@ -756,7 +759,7 @@ do_masked_and_readonly_paths (libcrun_container_t *container, const char *rootfs
if (ret == 0)
continue;

dir = crun_dir_p (path, err);
dir = crun_dir_p (path, true, err);
if (UNLIKELY (dir < 0))
return ret;

Expand Down Expand Up @@ -825,6 +828,16 @@ do_pivot (libcrun_container_t *container, const char *rootfs, libcrun_error_t *e
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "umount oldroot");

do
{
ret = umount2 (".", MNT_DETACH);
if (ret < 0 && errno == EINVAL)
break;
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "umount oldroot");
}
while (ret == 0);

ret = chdir ("/");
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "chdir to newroot");
Expand Down Expand Up @@ -945,7 +958,7 @@ do_mounts (libcrun_container_t *container, const char *rootfs, libcrun_error_t *

if (def->mounts[i]->source && (flags & MS_BIND))
{
is_dir = crun_dir_p (def->mounts[i]->source, err);
is_dir = crun_dir_p (def->mounts[i]->source, true, err);
if (UNLIKELY (is_dir < 0))
return is_dir;

Expand All @@ -970,13 +983,13 @@ do_mounts (libcrun_container_t *container, const char *rootfs, libcrun_error_t *

if (is_dir)
{
ret = crun_ensure_directory (target, 01755, err);
ret = crun_ensure_directory (target, 01755, true, err);
if (UNLIKELY (ret < 0))
return ret;
}
else
{
ret = crun_ensure_file (target, 0755, err);
ret = crun_ensure_file (target, 0755, true, err);
if (UNLIKELY (ret < 0))
return ret;
}
Expand Down Expand Up @@ -1124,7 +1137,7 @@ do_finalize_notify_socket (libcrun_container_t *container, libcrun_error_t *err)
container_notify_socket_path_dir_alloc = xstrdup (container_notify_socket_path);
container_notify_socket_path_dir = dirname (container_notify_socket_path_dir_alloc);

ret = crun_ensure_directory (container_notify_socket_path_dir, 0755, err);
ret = crun_ensure_directory (container_notify_socket_path_dir, 0755, false, err);
if (UNLIKELY (ret < 0))
return ret;

Expand Down
4 changes: 2 additions & 2 deletions src/libcrun/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ get_run_directory (const char *state_root)
if (root == NULL)
root = xstrdup ("/run/crun");

ret = crun_ensure_directory (root, 0700, &err);
ret = crun_ensure_directory (root, 0700, false, &err);
if (UNLIKELY (ret < 0))
crun_error_release (&err);
return root;
Expand Down Expand Up @@ -160,7 +160,7 @@ libcrun_status_check_directories (const char *state_root, const char *id, libcru
cleanup_free char *run_directory = get_run_directory (state_root);
int ret;

ret = crun_ensure_directory (run_directory, 0700, err);
ret = crun_ensure_directory (run_directory, 0700, false, err);
if (UNLIKELY (ret < 0))
return ret;

Expand Down
35 changes: 25 additions & 10 deletions src/libcrun/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,26 @@ ensure_directory_internal (char *path, size_t len, int mode, libcrun_error_t *er
}

int
crun_ensure_directory (const char *path, int mode, libcrun_error_t *err)
crun_ensure_directory (const char *path, int mode, bool nofollow, libcrun_error_t *err)
{
int ret;
cleanup_free char *tmp = xstrdup (path);
return ensure_directory_internal (tmp, strlen (tmp), mode, err);
ret = ensure_directory_internal (tmp, strlen (tmp), mode, err);
if (UNLIKELY (ret < 0))
return ret;

ret = crun_dir_p (path, nofollow, err);
if (UNLIKELY (ret < 0))
return ret;

if (ret == 0)
return crun_make_error (err, ENOTDIR, "The path '%s' is not a directory", path);

return 0;
}

int
crun_ensure_file (const char *path, int mode, libcrun_error_t *err)
crun_ensure_file (const char *path, int mode, bool nofollow, libcrun_error_t *err)
{
cleanup_free char *tmp = xstrdup (path);
size_t len = strlen (tmp);
Expand All @@ -289,7 +301,7 @@ crun_ensure_file (const char *path, int mode, libcrun_error_t *err)
if (it > tmp)
{
*it = '\0';
ret = crun_ensure_directory (tmp, mode, err);
ret = crun_ensure_directory (tmp, mode, nofollow, err);
if (UNLIKELY (ret < 0))
return ret;
*it = '/';
Expand Down Expand Up @@ -326,15 +338,15 @@ get_file_size (int fd, off_t *size)
}

static int
get_file_type (mode_t *mode, const char *path)
get_file_type (mode_t *mode, bool nofollow, const char *path)
{
struct stat st;
int ret;

#ifdef HAVE_STATX
struct statx stx;

ret = statx (AT_FDCWD, path, AT_STATX_DONT_SYNC, STATX_TYPE, &stx);
ret = statx (AT_FDCWD, path, (nofollow ? AT_SYMLINK_NOFOLLOW : 0) | AT_STATX_DONT_SYNC, STATX_TYPE, &stx);
if (UNLIKELY (ret < 0))
{
if (errno == ENOSYS)
Expand All @@ -347,20 +359,23 @@ get_file_type (mode_t *mode, const char *path)

fallback:
#endif
ret = stat (path, &st);
if (nofollow)
ret = lstat (path, &st);
else
ret = stat (path, &st);
if (UNLIKELY (ret < 0))
return ret;
*mode = st.st_mode;
return ret;
}

int
crun_dir_p (const char *path, libcrun_error_t *err)
crun_dir_p (const char *path, bool nofollow, libcrun_error_t *err)
{
mode_t mode;
int ret;

ret = get_file_type (&mode, path);
ret = get_file_type (&mode, nofollow, path);
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "error stat'ing file '%s'", path);

Expand Down Expand Up @@ -1202,7 +1217,7 @@ check_access (const char *path)
if (ret < 0)
return ret;

ret = get_file_type (&mode, path);
ret = get_file_type (&mode, false, path);
if (UNLIKELY (ret < 0))
return ret;

Expand Down
6 changes: 3 additions & 3 deletions src/libcrun/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ int write_file (const char *name, const void *data, size_t len, libcrun_error_t

int write_file_at (int dirfd, const char *name, const void *data, size_t len, libcrun_error_t *err);

int crun_ensure_directory (const char *path, int mode, libcrun_error_t *err);
int crun_ensure_directory (const char *path, int mode, bool nofollow, libcrun_error_t *err);

int crun_ensure_file (const char *path, int mode, libcrun_error_t *err);
int crun_ensure_file (const char *path, int mode, bool nofollow, libcrun_error_t *err);

int crun_dir_p (const char *path, libcrun_error_t *err);
int crun_dir_p (const char *path, bool nofollow, libcrun_error_t *err);

int detach_process ();

Expand Down
6 changes: 3 additions & 3 deletions tests/tests_libcrun_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,11 @@ static int
test_dir_p ()
{
libcrun_error_t err;
if (crun_dir_p ("/usr", &err) <= 0)
if (crun_dir_p ("/usr", false, &err) <= 0)
return -1;
if (crun_dir_p ("/dev/zero", &err) != 0)
if (crun_dir_p ("/dev/zero", false, &err) != 0)
return -1;
if (crun_dir_p ("/hopefully/does/not/really/exist", &err) >= 0)
if (crun_dir_p ("/hopefully/does/not/really/exist", false, &err) >= 0)
return -1;
return 0;
}
Expand Down

0 comments on commit 91db0f4

Please sign in to comment.