X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Futils_blockdev.c;h=ae6dec4979f3b667177dccd6ae4b4a378a0a49b8;hb=6497abd1df88001eb1f45f7348534911b33d05b5;hp=a96f3091bcd15fb200ca910d8c9f213e6bd6629b;hpb=f7fc3bb4e50cce23dd95111b246b6e034537e2cf;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/src/utils_blockdev.c b/src/utils_blockdev.c index a96f309..ae6dec4 100644 --- a/src/utils_blockdev.c +++ b/src/utils_blockdev.c @@ -1,8 +1,8 @@ /* * Linux block devices helpers * - * Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved. - * Copyright (C) 2018-2021 Ondrej Kozina + * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2023 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,11 +26,6 @@ #endif #include -#define DM_UUID_LEN 129 -#define DM_BY_ID_PREFIX "dm-uuid-" -#define DM_BY_ID_PREFIX_LEN 8 -#define DM_UUID_PREFIX "CRYPT-" -#define DM_UUID_PREFIX_LEN 6 #define UUID_LEN 37 /* 36 + \0, libuuid ... */ static int dm_prepare_uuid(const char *type, const char *uuid, char *buf, size_t buflen) @@ -53,29 +48,28 @@ static int dm_prepare_uuid(const char *type, const char *uuid, char *buf, size_t } } - snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s", - type ?: "", type ? "-" : "", - uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : ""); + if (snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s", + type ?: "", type ? "-" : "", + uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "") < 0) + return 0; return 1; } /* return number of holders in general, if matched dm_uuid prefix it's returned via dm_name */ /* negative value is error */ -static int lookup_holder_dm_name(const char *dm_uuid, size_t max_len, dev_t devno, char *dm_name, size_t dm_name_length) +static int lookup_holder_dm_name(const char *dm_uuid, dev_t devno, char **r_dm_name) { struct dirent *entry; - char dm_subpath[PATH_MAX], data_dev_dir[PATH_MAX], uuid[max_len]; + char dm_subpath[PATH_MAX], data_dev_dir[PATH_MAX], uuid[DM_UUID_LEN], dm_name[PATH_MAX] = {}; ssize_t s; struct stat st; int dmfd, fd, len, r = 0; /* not found */ DIR *dir; - if (!dm_name || !dm_name_length) + if (!r_dm_name) return -EINVAL; - *dm_name = '\0'; - len = snprintf(data_dev_dir, PATH_MAX, "/sys/dev/block/%u:%u/holders", major(devno), minor(devno)); if (len < 0 || len >= PATH_MAX) return -EINVAL; @@ -120,7 +114,7 @@ static int lookup_holder_dm_name(const char *dm_uuid, size_t max_len, dev_t devn } /* reads binary data */ - s = read_buffer(fd, uuid, max_len - 1); + s = read_buffer(fd, uuid, sizeof(uuid) - 1); close(fd); uuid[s > 0 ? s : 0] = '\0'; if (!strncmp(uuid, dm_uuid, strlen(dm_uuid))) @@ -143,12 +137,14 @@ static int lookup_holder_dm_name(const char *dm_uuid, size_t max_len, dev_t devn } /* reads binary data */ - s = read_buffer(fd, dm_name, dm_name_length - 1); + s = read_buffer(fd, dm_name, sizeof(dm_name)); close(fd); close(dmfd); if (s > 1) { dm_name[s-1] = '\0'; log_dbg("Found dm device %s", dm_name); + if (!(*r_dm_name = strdup(dm_name))) + return -ENOMEM; } } @@ -158,9 +154,8 @@ static int lookup_holder_dm_name(const char *dm_uuid, size_t max_len, dev_t devn } int tools_lookup_crypt_device(struct crypt_device *cd, const char *type, - const char *data_device_path, char *name, size_t name_length) + const char *data_device_path, char **r_name) { - int r; char *c; struct stat st; char dev_uuid[DM_UUID_LEN + DM_BY_ID_PREFIX_LEN] = DM_BY_ID_PREFIX; @@ -183,7 +178,205 @@ int tools_lookup_crypt_device(struct crypt_device *cd, const char *type, if (!S_ISBLK(st.st_mode)) return -ENOTBLK; - r = lookup_holder_dm_name(dev_uuid + DM_BY_ID_PREFIX_LEN, DM_UUID_LEN, - st.st_rdev, name, name_length); + return lookup_holder_dm_name(dev_uuid + DM_BY_ID_PREFIX_LEN, st.st_rdev, r_name); +} + +static void report_partition(const char *value, const char *device, bool batch_mode) +{ + if (batch_mode) + log_dbg("Device %s already contains a '%s' partition signature.", device, value); + else + log_std(_("WARNING: Device %s already contains a '%s' partition signature.\n"), device, value); +} + +static void report_superblock(const char *value, const char *device, bool batch_mode) +{ + if (batch_mode) + log_dbg("Device %s already contains a '%s' superblock signature.", device, value); + else + log_std(_("WARNING: Device %s already contains a '%s' superblock signature.\n"), device, value); +} + +int tools_detect_signatures(const char *device, tools_probe_filter_info filter, + size_t *count,bool batch_mode) +{ + int r; + size_t tmp_count; + struct blkid_handle *h; + blk_probe_status pr; + + if (!count) + count = &tmp_count; + + *count = 0; + + if (!blk_supported()) { + log_dbg("Blkid support disabled."); + return 0; + } + + if ((r = blk_init_by_path(&h, device))) { + log_err(_("Failed to initialize device signature probes.")); + return -EINVAL; + } + + switch (filter) { + case PRB_FILTER_LUKS: + if (blk_superblocks_filter_luks(h)) { + r = -EINVAL; + goto out; + } + /* fall-through */ + case PRB_FILTER_NONE: + blk_set_chains_for_full_print(h); + break; + case PRB_ONLY_LUKS: + blk_set_chains_for_fast_detection(h); + if (blk_superblocks_only_luks(h)) { + r = -EINVAL; + goto out; + } + } + + while ((pr = blk_probe(h)) < PRB_EMPTY) { + if (blk_is_partition(h)) + report_partition(blk_get_partition_type(h), device, batch_mode); + else if (blk_is_superblock(h)) + report_superblock(blk_get_superblock_type(h), device, batch_mode); + else { + log_dbg("Internal tools_detect_signatures() error."); + r = -EINVAL; + goto out; + } + (*count)++; + } + + if (pr == PRB_FAIL) + r = -EINVAL; +out: + blk_free(h); return r; } + +int tools_wipe_all_signatures(const char *path, bool exclusive, bool only_luks) +{ + int fd, flags, r; + blk_probe_status pr; + struct stat st; + struct blkid_handle *h = NULL; + + if (!blk_supported()) { + log_dbg("Blkid support disabled."); + return 0; + } + + if (stat(path, &st)) { + log_err(_("Failed to stat device %s."), path); + return -EINVAL; + } + + flags = O_RDWR; + if (S_ISBLK(st.st_mode) && exclusive) + flags |= O_EXCL; + + /* better than opening regular file with O_EXCL (undefined) */ + /* coverity[toctou] */ + fd = open(path, flags); /* lgtm[cpp/toctou-race-condition] */ + if (fd < 0) { + if (errno == EBUSY) + log_err(_("Cannot exclusively open %s, device in use."), path); + else + log_err(_("Failed to open file %s in read/write mode."), path); + return -EINVAL; + } + + if ((r = blk_init_by_fd(&h, fd))) { + log_err(_("Failed to initialize device signature probes.")); + r = -EINVAL; + goto out; + } + + blk_set_chains_for_wipes(h); + if (only_luks && (r = blk_superblocks_only_luks(h))) { + r = -EINVAL; + goto out; + } + + while ((pr = blk_probe(h)) < PRB_EMPTY) { + if (blk_is_partition(h)) + log_verbose(_("Existing '%s' partition signature on device %s will be wiped."), + blk_get_partition_type(h), path); + if (blk_is_superblock(h)) + log_verbose(_("Existing '%s' superblock signature on device %s will be wiped."), + blk_get_superblock_type(h), path); + if (blk_do_wipe(h) || fsync(fd)) { + log_err(_("Failed to wipe device signature.")); + r = -EINVAL; + goto out; + } + } + + if (pr != PRB_EMPTY) { + log_err(_("Failed to probe device %s for a signature."), path); + r = -EINVAL; + } +out: + close(fd); + blk_free(h); + return r; +} + +int tools_superblock_block_size(const char *device, char *sb_name, size_t sb_name_len, unsigned *r_block_size) +{ + struct blkid_handle *h; + const char *name; + int r = 0; + + if (!r_block_size || !sb_name || sb_name_len < 1) + return -EINVAL; + + if (!blk_supported()) { + log_dbg("Blkid support disabled."); + return 0; + } + + if ((r = blk_init_by_path(&h, device))) { + log_err(_("Failed to initialize device signature probes.")); + return -EINVAL; + } + + blk_set_chains_for_superblocks(h); + + switch (blk_probe(h)) { + case PRB_OK: + *r_block_size = blk_get_block_size(h); + if (!*r_block_size) /* same as not-found */ + break; + + if (!(name = blk_get_superblock_type(h))) { + r = -EINVAL; + break; + } + + /* we don't mind truncating */ + strncpy(sb_name, name, sb_name_len - 1); + sb_name[sb_name_len-1] = '\0'; + + log_dbg("Detected superblock %s on device %s (block size: %u).", sb_name, device, *r_block_size); + r = 1; + /* fall-through */ + case PRB_EMPTY: + break; + default: + r = -EINVAL; + } + + blk_free(h); + + return r; +} + +bool tools_blkid_supported(void) +{ + return blk_supported() != 0; +}