diff --git a/src/libcrun/linux.c b/src/libcrun/linux.c index e99a53d99c..9205fe237e 100644 --- a/src/libcrun/linux.c +++ b/src/libcrun/linux.c @@ -1144,7 +1144,7 @@ static int mount_masked_dir (libcrun_container_t *container, int pathfd, const char *rel_path, libcrun_error_t *err) { struct private_data_s *private_data = get_private_data (container); - cleanup_close int mountfd = -1; + cleanup_close int newfd = -1; libcrun_error_t tmp_err = NULL; int ret; @@ -1160,24 +1160,23 @@ mount_masked_dir (libcrun_container_t *container, int pathfd, const char *rel_pa goto fallback_to_tmpfs; } - mountfd = private_data->maskdir_fd; - if (mountfd >= 0) + if (private_data->maskdir_fd >= 0) { - int rootfsfd = get_private_data (container)->rootfsfd; + int rootfsfd = private_data->rootfsfd; struct stat before, after; - ret = fstat (mountfd, &before); + ret = fstat (private_data->maskdir_fd, &before); if (UNLIKELY (ret < 0)) return crun_make_error (err, errno, "fstat masked dir `%s`", rel_path); - ret = fs_move_mount_to (mountfd, pathfd, NULL); + ret = fs_move_mount_to (private_data->maskdir_fd, pathfd, NULL); if (LIKELY (ret == 0)) { - mountfd = get_bind_mount (rootfsfd, rel_path, true, true, false, MS_PRIVATE, err); - if (UNLIKELY (mountfd < 0)) - return mountfd; + newfd = get_bind_mount (rootfsfd, rel_path, true, true, false, MS_PRIVATE, err); + if (UNLIKELY (newfd < 0)) + return newfd; - ret = fstat (mountfd, &after); + ret = fstat (newfd, &after); if (UNLIKELY (ret < 0)) return crun_make_error (err, errno, "fstat masked dir `%s`", rel_path); @@ -1185,12 +1184,18 @@ mount_masked_dir (libcrun_container_t *container, int pathfd, const char *rel_pa return crun_make_error (err, 0, "race condition detected remounting masked path `/%s`", rel_path); TEMP_FAILURE_RETRY (close (private_data->maskdir_fd)); - private_data->maskdir_fd = mountfd; - mountfd = -1; + private_data->maskdir_fd = newfd; + newfd = -1; return 0; } + { + int move_errno = errno; + crun_error_release (&tmp_err); + crun_make_error (&tmp_err, move_errno, "move mount masked dir `%s`", rel_path); + } + TEMP_FAILURE_RETRY (close (private_data->maskdir_fd)); private_data->maskdir_fd = -1; } diff --git a/src/libcrun/utils.c b/src/libcrun/utils.c index 514b9ac9fb..b0f1ef787c 100644 --- a/src/libcrun/utils.c +++ b/src/libcrun/utils.c @@ -815,7 +815,7 @@ libcrun_initialize_apparmor (libcrun_error_t *err) { cleanup_close int fd = -1; int size; - char buf[2]; + char buf[1]; if (apparmor_enabled >= 0) return apparmor_enabled; @@ -832,7 +832,7 @@ libcrun_initialize_apparmor (libcrun_error_t *err) return crun_make_error (err, errno, "open `/sys/module/apparmor/parameters/enabled`"); } - size = TEMP_FAILURE_RETRY (read (fd, buf, 2)); + size = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf))); apparmor_enabled = size > 0 && buf[0] == 'Y' ? 1 : 0; @@ -963,9 +963,12 @@ libcrun_is_apparmor_enabled (libcrun_error_t *err) static int is_current_process_confined (libcrun_container_t *container, libcrun_error_t *err) { +#define UNCONFINED "unconfined" +#define UNCONFINED_LEN (ssize_t) (sizeof (UNCONFINED) - 1) cleanup_free const char *attr_path = lsm_attr_path (container, "apparmor", "current", err); cleanup_close int fd = -1; - char buf[256]; + /* Only the "unconfined" token plus one delimiter byte are inspected. */ + char buf[UNCONFINED_LEN + 1]; if (UNLIKELY (attr_path == NULL)) return -1; @@ -977,13 +980,22 @@ is_current_process_confined (libcrun_container_t *container, libcrun_error_t *er if (UNLIKELY (check_proc_super_magic (fd, attr_path, err))) return -1; - ssize_t bytes_read = read (fd, buf, sizeof (buf) - 1); + ssize_t bytes_read = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf))); if (UNLIKELY (bytes_read < 0)) return crun_make_error (err, errno, "read from `%s`", attr_path); -#define UNCONFINED "unconfined" -#define UNCONFINED_LEN (ssize_t) (sizeof (UNCONFINED) - 1) - return bytes_read >= UNCONFINED_LEN && memcmp (buf, UNCONFINED, UNCONFINED_LEN); + /* The process is unconfined only when the attribute is exactly the token + "unconfined", optionally followed by a delimiter. Anything shorter (a + short read), or a longer profile name such as "unconfined_foo", means the + process is confined. When in doubt default to confined, which is the safe + assumption for the caller. */ + if (bytes_read < UNCONFINED_LEN || memcmp (buf, UNCONFINED, UNCONFINED_LEN) != 0) + return 1; + if (bytes_read == UNCONFINED_LEN || buf[UNCONFINED_LEN] == '\n' || buf[UNCONFINED_LEN] == ' ') + return 0; + return 1; +#undef UNCONFINED +#undef UNCONFINED_LEN } int