Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions src/libcrun/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -1160,37 +1160,42 @@ 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);

if (before.st_dev != after.st_dev || before.st_ino != after.st_ino)
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;
}
Expand Down
26 changes: 19 additions & 7 deletions src/libcrun/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
Loading