#if HAVE_BLKID
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
_cleanup_close_ int fd = -EBADF;
+ struct stat st;
int r;
assert(path);
if (fd < 0)
return -errno;
- r = fd_verify_regular(fd);
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ r = stat_verify_regular(&st);
if (r < 0)
return r;
if (r < 0)
return r;
+ m->image_size = st.st_size;
+
r = probe_sector_size(fd, &m->sector_size);
if (r < 0)
return r;
"(fsck)",
NULL,
&node_fd, 1, /* Leave the node fd open */
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
&pid);
if (r < 0)
return log_debug_errno(r, "Failed to fork off fsck: %m");
if (node_fd < 0)
return log_debug_errno(errno, "Failed to open node device %s: %m", node_path);
- if (ioctl(node_fd, BLKGETSIZE64, &size) != 0)
- return log_debug_errno(errno, "Failed to get block device size of %s: %m", node_path);
+ r = blockdev_get_device_size(node_fd, &size);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get block device size of %s: %m", node_path);
if (mount_fd < 0) {
assert(mount_path);
if (m->fsmount_fd >= 0) {
/* Case #1: Attach existing fsmount fd to the file system */
- if (move_mount(m->fsmount_fd, "", -EBADF, p, MOVE_MOUNT_F_EMPTY_PATH) < 0)
- return -errno;
+ r = mount_exchange_graceful(
+ m->fsmount_fd,
+ p,
+ FLAGS_SET(flags, DISSECT_IMAGE_TRY_ATOMIC_MOUNT_EXCHANGE));
+ if (r < 0)
+ return log_debug_errno(r, "Failed to mount image on '%s': %m", p);
} else {
assert(node);
(void) fs_grow(node, -EBADF, p);
if (userns_fd >= 0) {
- r = remount_idmap_fd(p, userns_fd);
+ r = remount_idmap_fd(STRV_MAKE(p), userns_fd);
if (r < 0)
return r;
}
if (r > 0)
ok = true;
}
- if (!ok && FLAGS_SET(flags, DISSECT_IMAGE_VALIDATE_OS_EXT)) {
+ if (!ok && FLAGS_SET(flags, DISSECT_IMAGE_VALIDATE_OS_EXT) && m->image_name) {
r = extension_has_forbidden_content(where);
if (r < 0)
return r;
DecryptedImage *d) {
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
- _cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
_cleanup_free_ char *node = NULL, *name = NULL;
_cleanup_close_ int mount_node_fd = -EBADF;
int r;
* In case of ENODEV/ENOENT, which can happen if another process is activating at the exact same time,
* retry a few times before giving up. */
for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
+ _cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
_cleanup_(sym_crypt_freep) struct crypt_device *existing_cd = NULL;
_cleanup_close_ int fd = -EBADF;
return log_debug_errno(r, "Failed to activate verity device %s: %m", node);
check:
- if (!restore_deferred_remove){
- /* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */
- r = dm_deferred_remove_cancel(name);
- /* -EBUSY and -ENXIO: the device has already been removed or being removed. We cannot
- * use the device, try to open again. See target_message() in drivers/md/dm-ioctl.c
- * and dm_cancel_deferred_remove() in drivers/md/dm.c */
- if (IN_SET(r, -EBUSY, -ENXIO))
- goto try_again;
- if (r < 0)
- return log_debug_errno(r, "Failed to disable automated deferred removal for verity device %s: %m", node);
+ /* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */
+ r = dm_deferred_remove_cancel(name);
+ /* -EBUSY and -ENXIO: the device has already been removed or being removed. We cannot
+ * use the device, try to open again. See target_message() in drivers/md/dm-ioctl.c
+ * and dm_cancel_deferred_remove() in drivers/md/dm.c */
+ if (IN_SET(r, -EBUSY, -ENXIO))
+ goto try_again;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to disable automated deferred removal for verity device %s: %m", node);
- restore_deferred_remove = strdup(name);
- if (!restore_deferred_remove)
- return log_oom_debug();
- }
+ restore_deferred_remove = strdup(name);
+ if (!restore_deferred_remove)
+ return log_oom_debug();
r = verity_can_reuse(verity, name, &existing_cd);
/* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */
}
}
+ /* Everything looks good and we'll be able to mount the device, so deferred remove will be re-enabled at that point. */
+ restore_deferred_remove = mfree(restore_deferred_remove);
+
mount_node_fd = TAKE_FD(fd);
if (existing_cd)
crypt_free_and_replace(cd, existing_cd);
return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), "All attempts to activate verity device %s failed.", name);
success:
- /* Everything looks good and we'll be able to mount the device, so deferred remove will be re-enabled at that point. */
- restore_deferred_remove = mfree(restore_deferred_remove);
-
d->decrypted[d->n_decrypted++] = (DecryptedPartition) {
.name = TAKE_PTR(name),
.device = TAKE_PTR(cd),
};
_cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL, **initrd_release = NULL, **sysext_release = NULL, **confext_release = NULL;
- _cleanup_close_pair_ int error_pipe[2] = PIPE_EBADF;
+ _cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR;
_cleanup_(rmdir_and_freep) char *t = NULL;
_cleanup_(sigkill_waitp) pid_t child = 0;
sd_id128_t machine_id = SD_ID128_NULL;
assert(m);
for (; n_meta_initialized < _META_MAX; n_meta_initialized ++) {
- if (!paths[n_meta_initialized]) {
- fds[2*n_meta_initialized] = fds[2*n_meta_initialized+1] = -EBADF;
- continue;
- }
+ assert(paths[n_meta_initialized]);
if (pipe2(fds + 2*n_meta_initialized, O_CLOEXEC) < 0) {
r = -errno;
goto finish;
}
- r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child);
+ r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child);
if (r < 0)
goto finish;
if (r == 0) {
for (unsigned k = 0; k < _META_MAX; k++) {
_cleanup_close_ int fd = -ENOENT;
- if (!paths[k])
- continue;
+ assert(paths[k]);
fds[2*k] = safe_close(fds[2*k]);
switch (k) {
case META_SYSEXT_RELEASE:
+ if (!m->image_name)
+ goto next;
+
/* As per the os-release spec, if the image is an extension it will have a
* file named after the image name in extension-release.d/ - we use the image
* name and try to resolve it with the extension-release helpers, as
break;
case META_CONFEXT_RELEASE:
+ if (!m->image_name)
+ goto next;
+
/* As above */
r = open_extension_release(
t,
if (r < 0)
goto inner_fail;
- continue;
+ goto next;
}
default:
if (fd < 0) {
log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]);
- fds[2*k+1] = safe_close(fds[2*k+1]);
- continue;
+ goto next;
}
r = copy_bytes(fd, fds[2*k+1], UINT64_MAX, 0);
if (r < 0)
goto inner_fail;
+ next:
fds[2*k+1] = safe_close(fds[2*k+1]);
}
for (unsigned k = 0; k < _META_MAX; k++) {
_cleanup_fclose_ FILE *f = NULL;
- if (!paths[k])
- continue;
+ assert(paths[k]);
fds[2*k+1] = safe_close(fds[2*k+1]);
r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
child = 0;
if (r < 0)
- return r;
+ goto finish;
n = read(error_pipe[0], &v, sizeof(v));
- if (n < 0)
- return -errno;
- if (n == sizeof(v))
- return v; /* propagate error sent to us from child */
- if (n != 0)
- return -EIO;
-
- if (r != EXIT_SUCCESS)
- return -EPROTO;
+ if (n < 0) {
+ r = -errno;
+ goto finish;
+ }
+ if (n == sizeof(v)) {
+ r = v; /* propagate error sent to us from child */
+ goto finish;
+ }
+ if (n != 0) {
+ r = -EIO;
+ goto finish;
+ }
+ if (r != EXIT_SUCCESS) {
+ r = -EPROTO;
+ goto finish;
+ }
free_and_replace(m->hostname, hostname);
m->machine_id = machine_id;
return r;
m->loop = loop_device_ref(loop);
+ m->image_size = m->loop->device_size;
m->sector_size = m->loop->sector_size;
r = dissect_image(m, loop->fd, loop->node, verity, mount_options, image_policy, flags);