mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-07 08:50:05 +01:00
Fix TCRYPT system encryption mapping for multiple partitions.
Since this commit, one can use partition directly as device parameter. Should fix Issue#183 and Issue#188.
This commit is contained in:
@@ -95,6 +95,8 @@ char *crypt_lookup_dev(const char *dev_id);
|
|||||||
int crypt_dev_is_rotational(int major, int minor);
|
int crypt_dev_is_rotational(int major, int minor);
|
||||||
int crypt_dev_is_partition(const char *dev_path);
|
int crypt_dev_is_partition(const char *dev_path);
|
||||||
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size);
|
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size);
|
||||||
|
char *crypt_get_base_device(const char *dev_path);
|
||||||
|
uint64_t crypt_dev_partition_offset(const char *dev_path);
|
||||||
|
|
||||||
ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count);
|
ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count);
|
||||||
ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count);
|
ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count);
|
||||||
|
|||||||
@@ -573,8 +573,9 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
|
|||||||
struct tcrypt_phdr *hdr,
|
struct tcrypt_phdr *hdr,
|
||||||
struct crypt_params_tcrypt *params)
|
struct crypt_params_tcrypt *params)
|
||||||
{
|
{
|
||||||
struct device *device = crypt_metadata_device(cd);
|
struct device *base_device, *device = crypt_metadata_device(cd);
|
||||||
ssize_t hdr_size = sizeof(struct tcrypt_phdr);
|
ssize_t hdr_size = sizeof(struct tcrypt_phdr);
|
||||||
|
char *base_device_path;
|
||||||
int devfd = 0, r, bs;
|
int devfd = 0, r, bs;
|
||||||
|
|
||||||
assert(sizeof(struct tcrypt_phdr) == 512);
|
assert(sizeof(struct tcrypt_phdr) == 512);
|
||||||
@@ -586,7 +587,23 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
|
|||||||
if (bs < 0)
|
if (bs < 0)
|
||||||
return bs;
|
return bs;
|
||||||
|
|
||||||
|
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER &&
|
||||||
|
crypt_dev_is_partition(device_path(device))) {
|
||||||
|
base_device_path = crypt_get_base_device(device_path(device));
|
||||||
|
|
||||||
|
log_dbg("Reading TCRYPT system header from device %s.", base_device_path ?: "?");
|
||||||
|
if (!base_device_path)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
r = device_alloc(&base_device, base_device_path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
devfd = device_open(base_device, O_RDONLY);
|
||||||
|
free(base_device_path);
|
||||||
|
device_free(base_device);
|
||||||
|
} else
|
||||||
devfd = device_open(device, O_RDONLY);
|
devfd = device_open(device, O_RDONLY);
|
||||||
|
|
||||||
if (devfd == -1) {
|
if (devfd == -1) {
|
||||||
log_err(cd, _("Cannot open device %s.\n"), device_path(device));
|
log_err(cd, _("Cannot open device %s.\n"), device_path(device));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -694,25 +711,23 @@ int TCRYPT_activate(struct crypt_device *cd,
|
|||||||
if (!algs)
|
if (!algs)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
|
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
|
||||||
|
dmd.size = 0;
|
||||||
|
else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
|
||||||
dmd.size = hdr->d.hidden_volume_size / hdr->d.sector_size;
|
dmd.size = hdr->d.hidden_volume_size / hdr->d.sector_size;
|
||||||
else
|
else
|
||||||
dmd.size = hdr->d.volume_size / hdr->d.sector_size;
|
dmd.size = hdr->d.volume_size / hdr->d.sector_size;
|
||||||
|
|
||||||
/*
|
if (dmd.flags & CRYPT_ACTIVATE_SHARED)
|
||||||
* System encryption use the whole device mapping, there can
|
|
||||||
* be active partitions.
|
|
||||||
* FIXME: This will allow multiple mappings unexpectedly.
|
|
||||||
*/
|
|
||||||
if ((dmd.flags & CRYPT_ACTIVATE_SHARED) ||
|
|
||||||
(params->flags & CRYPT_TCRYPT_SYSTEM_HEADER))
|
|
||||||
device_check = DEV_SHARED;
|
device_check = DEV_SHARED;
|
||||||
else
|
else
|
||||||
device_check = DEV_EXCL;
|
device_check = DEV_EXCL;
|
||||||
|
|
||||||
if ((params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) &&
|
if ((params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) &&
|
||||||
(part_path = crypt_get_partition_device(device_path(dmd.data_device),
|
!crypt_dev_is_partition(device_path(dmd.data_device))) {
|
||||||
dmd.u.crypt.offset, dmd.size))) {
|
part_path = crypt_get_partition_device(device_path(dmd.data_device),
|
||||||
|
dmd.u.crypt.offset, dmd.size);
|
||||||
|
if (part_path) {
|
||||||
if (!device_alloc(&part_device, part_path)) {
|
if (!device_alloc(&part_device, part_path)) {
|
||||||
log_verbose(cd, _("Activating TCRYPT system encryption for partition %s.\n"),
|
log_verbose(cd, _("Activating TCRYPT system encryption for partition %s.\n"),
|
||||||
part_path);
|
part_path);
|
||||||
@@ -720,6 +735,12 @@ int TCRYPT_activate(struct crypt_device *cd,
|
|||||||
dmd.u.crypt.offset = 0;
|
dmd.u.crypt.offset = 0;
|
||||||
}
|
}
|
||||||
free(part_path);
|
free(part_path);
|
||||||
|
} else
|
||||||
|
/*
|
||||||
|
* System encryption use the whole device mapping, there can
|
||||||
|
* be active partitions.
|
||||||
|
*/
|
||||||
|
device_check = DEV_SHARED;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = device_block_adjust(cd, dmd.data_device, device_check,
|
r = device_block_adjust(cd, dmd.data_device, device_check,
|
||||||
@@ -924,8 +945,11 @@ uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
|
|||||||
goto hdr_offset;
|
goto hdr_offset;
|
||||||
|
|
||||||
/* Mapping through whole device, not partition! */
|
/* Mapping through whole device, not partition! */
|
||||||
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
|
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
|
||||||
|
if (crypt_dev_is_partition(device_path(crypt_metadata_device(cd))))
|
||||||
|
return 0;
|
||||||
goto hdr_offset;
|
goto hdr_offset;
|
||||||
|
}
|
||||||
|
|
||||||
if (params->mode && !strncmp(params->mode, "xts", 3)) {
|
if (params->mode && !strncmp(params->mode, "xts", 3)) {
|
||||||
if (hdr->d.version < 3)
|
if (hdr->d.version < 3)
|
||||||
@@ -955,15 +979,21 @@ hdr_offset:
|
|||||||
|
|
||||||
uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
|
uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
|
||||||
struct tcrypt_phdr *hdr,
|
struct tcrypt_phdr *hdr,
|
||||||
struct crypt_params_tcrypt *params
|
struct crypt_params_tcrypt *params)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (params->mode && !strncmp(params->mode, "xts", 3))
|
uint64_t iv_offset;
|
||||||
return TCRYPT_get_data_offset(cd, hdr, params);
|
|
||||||
else if (params->mode && !strncmp(params->mode, "lrw", 3))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return hdr->d.mk_offset / hdr->d.sector_size;
|
if (params->mode && !strncmp(params->mode, "xts", 3))
|
||||||
|
iv_offset = TCRYPT_get_data_offset(cd, hdr, params);
|
||||||
|
else if (params->mode && !strncmp(params->mode, "lrw", 3))
|
||||||
|
iv_offset = 0;
|
||||||
|
else
|
||||||
|
iv_offset = hdr->d.mk_offset / hdr->d.sector_size;
|
||||||
|
|
||||||
|
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
|
||||||
|
iv_offset += crypt_dev_partition_offset(device_path(crypt_metadata_device(cd)));
|
||||||
|
|
||||||
|
return iv_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TCRYPT_get_volume_key(struct crypt_device *cd,
|
int TCRYPT_get_volume_key(struct crypt_device *cd,
|
||||||
|
|||||||
@@ -236,6 +236,24 @@ int crypt_dev_is_partition(const char *dev_path)
|
|||||||
return val ? 1 : 0;
|
return val ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t crypt_dev_partition_offset(const char *dev_path)
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (!crypt_dev_is_partition(dev_path))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (stat(dev_path, &st) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!_sysfs_get_uint64(major(st.st_rdev), minor(st.st_rdev),
|
||||||
|
&val, "start"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to find partition which match offset and size on top level device */
|
/* Try to find partition which match offset and size on top level device */
|
||||||
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size)
|
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size)
|
||||||
{
|
{
|
||||||
@@ -305,3 +323,42 @@ char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to find base device from partition */
|
||||||
|
char *crypt_get_base_device(const char *dev_path)
|
||||||
|
{
|
||||||
|
char link[PATH_MAX], path[PATH_MAX], part_path[PATH_MAX], *devname;
|
||||||
|
struct stat st;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
if (!crypt_dev_is_partition(dev_path))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (stat(dev_path, &st) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
|
||||||
|
major(st.st_rdev), minor(st.st_rdev)) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = readlink(path, link, sizeof(link) - 1);
|
||||||
|
if (len < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Get top level disk name for sysfs search */
|
||||||
|
link[len] = '\0';
|
||||||
|
devname = strrchr(link, '/');
|
||||||
|
if (!devname)
|
||||||
|
return NULL;
|
||||||
|
*devname = '\0';
|
||||||
|
devname = strrchr(link, '/');
|
||||||
|
if (!devname)
|
||||||
|
return NULL;
|
||||||
|
devname++;
|
||||||
|
|
||||||
|
if (dm_is_dm_kernel_name(devname))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
snprintf(part_path, sizeof(part_path), "/dev/%s", devname);
|
||||||
|
return strdup(part_path);
|
||||||
|
}
|
||||||
|
|||||||
@@ -423,8 +423,19 @@ The \fBtcryptDump\fR command should work for all recognized TCRYPT devices
|
|||||||
and doesn't require superuser privilege.
|
and doesn't require superuser privilege.
|
||||||
|
|
||||||
To map system device (device with boot loader where the whole encrypted
|
To map system device (device with boot loader where the whole encrypted
|
||||||
system resides) use \fB\-\-tcrypt\-system\fR option. Use the whole
|
system resides) use \fB\-\-tcrypt\-system\fR option.
|
||||||
device not the system partition as the device parameter.
|
You can use partition device as the parameter (parameter must be real partition
|
||||||
|
device, not image in file), then only this partition is mapped.
|
||||||
|
|
||||||
|
If you have whole TCRYPT device as a file image and you want to map multiple
|
||||||
|
partition encrypted with system encryption, please create loopback mapping
|
||||||
|
with partitions first (\fBlosetup -P\fR, see \fPlosetup(8)\fR man page for more info),
|
||||||
|
and use loop partition as the device parameter.
|
||||||
|
|
||||||
|
If you use whole base device as parameter, one device for the whole system
|
||||||
|
encryption is mapped. This mode is available only for backward compatibility
|
||||||
|
with older cryptsetup versions which mapped TCRYPT system encryption
|
||||||
|
using whole device.
|
||||||
|
|
||||||
To use hidden header (and map hidden device, if available),
|
To use hidden header (and map hidden device, if available),
|
||||||
use \fB\-\-tcrypt\-hidden\fR option.
|
use \fB\-\-tcrypt\-hidden\fR option.
|
||||||
|
|||||||
Reference in New Issue
Block a user