Set context for DM log for all DM backend entries.

Try to handle error if run as non-root user better.
This commit is contained in:
Milan Broz
2012-08-14 16:53:02 +02:00
parent 97224b072a
commit 1d5788f779
8 changed files with 145 additions and 79 deletions

View File

@@ -2,6 +2,7 @@
* Allocate loop device late (only when real block device needed).
* Rework underlying device/file access functions.
* Create hash image if doesn't exist in veritysetup format.
* Provide better error message if running as non-root user (device-mapper, loop).
2012-07-10 Milan Broz <gmazyland@gmail.com>
* Version 1.5.0.

View File

@@ -38,10 +38,11 @@
/* Set if dm-crypt version was probed */
static int _dm_crypt_checked = 0;
static int _quiet_log = 0;
static uint32_t _dm_crypt_flags = 0;
static int _dm_use_count = 0;
static struct crypt_device *_context = NULL;
static int _dm_use_count = 0;
/* Check if we have DM flag to instruct kernel to force wipe buffers */
#if !HAVE_DECL_DM_TASK_SECURE_DATA
@@ -81,11 +82,14 @@ static void set_dm_error(int level,
va_start(va, f);
if (vasprintf(&msg, f, va) > 0) {
if (level < 4) {
if (level < 4 && !_quiet_log) {
log_err(_context, msg);
log_err(_context, "\n");
} else
log_dbg(msg);
} else {
/* We do not use DM visual stack backtrace here */
if (strncmp(msg, "<backtrace>", 11))
log_dbg(msg);
}
}
free(msg);
va_end(va);
@@ -142,23 +146,23 @@ static int _dm_check_versions(void)
struct dm_task *dmt;
struct dm_versions *target, *last_target;
char dm_version[16];
int r = 0;
if (_dm_crypt_checked)
return 1;
/* Shut up DM while checking */
_quiet_log = 1;
/* FIXME: add support to DM so it forces crypt target module load here */
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return 0;
goto out;
if (!dm_task_run(dmt)) {
dm_task_destroy(dmt);
return 0;
}
if (!dm_task_run(dmt))
goto out;
if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version))) {
dm_task_destroy(dmt);
return 0;
}
if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version)))
goto out;
target = dm_task_get_versions(dmt);
do {
@@ -177,52 +181,67 @@ static int _dm_check_versions(void)
target = (struct dm_versions *)((char *) target + target->next);
} while (last_target != target);
dm_task_destroy(dmt);
return 1;
r = 1;
log_dbg("Device-mapper backend running with UDEV support %sabled.",
_dm_use_udev() ? "en" : "dis");
out:
if (dmt)
dm_task_destroy(dmt);
_quiet_log = 0;
return r;
}
uint32_t dm_flags(void)
{
if (!_dm_crypt_checked)
_dm_check_versions();
_dm_check_versions();
return _dm_crypt_flags;
}
int dm_init(struct crypt_device *context, int check_kernel)
/* This doesn't run any kernel checks, just set up userspace libdevmapper */
void dm_backend_init(void)
{
if (!_dm_use_count++) {
log_dbg("Initialising device-mapper backend%s, UDEV is %sabled.",
check_kernel ? "" : " (NO kernel check requested)",
_dm_use_udev() ? "en" : "dis");
if (check_kernel && !_dm_check_versions()) {
log_err(context, _("Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"));
return -1;
}
if (getuid() || geteuid())
log_dbg(("WARNING: Running as a non-root user. Functionality may be unavailable."));
log_dbg("Initialising device-mapper backend library.");
dm_log_init(set_dm_error);
dm_log_init_verbose(10);
}
// FIXME: global context is not safe
if (context)
_context = context;
return 1; /* unsafe memory */
}
void dm_exit(void)
void dm_backend_exit(void)
{
if (_dm_use_count && (!--_dm_use_count)) {
log_dbg("Releasing device-mapper backend.");
dm_log_init_verbose(0);
dm_log_init(NULL);
dm_lib_release();
_context = NULL;
}
}
/*
* libdevmapper is not context friendly, switch context on every DM call.
* FIXME: this is not safe if called in parallel but neither is DM lib.
*/
static int dm_init_context(struct crypt_device *cd)
{
_context = cd;
if (!_dm_check_versions()) {
if (getuid() || geteuid())
log_err(cd, _("Cannot initialize device-mapper, "
"running as non-root user.\n"));
else
log_err(cd, _("Cannot initialize device-mapper. "
"Is dm_mod kernel module loaded?\n"));
_context = NULL;
return -ENOTSUP;
}
return 0;
}
static void dm_exit_context(void)
{
_context = NULL;
}
/* Return path to DM device */
char *dm_device_path(const char *prefix, int major, int minor)
{
@@ -435,6 +454,9 @@ int dm_remove_device(struct crypt_device *cd, const char *name,
if (!name || (force && !size))
return -EINVAL;
if (dm_init_context(cd))
return -ENOTSUP;
do {
r = _dm_simple(DM_DEVICE_REMOVE, name, 1) ? 0 : -EINVAL;
if (--retries && r) {
@@ -457,6 +479,7 @@ int dm_remove_device(struct crypt_device *cd, const char *name,
} while (r == -EINVAL && retries);
dm_task_update_nodes();
dm_exit_context();
return r;
}
@@ -596,17 +619,25 @@ int dm_create_device(struct crypt_device *cd, const char *name,
int reload)
{
char *table_params = NULL;
int r = -EINVAL;
if (!type)
return -EINVAL;
if (dm_init_context(cd))
return -ENOTSUP;
if (dmd->target == DM_CRYPT)
table_params = get_dm_crypt_params(dmd);
else if (dmd->target == DM_VERITY)
table_params = get_dm_verity_params(dmd->u.verity.vp, dmd);
if (!table_params || !type)
return -EINVAL;
return _dm_create_device(name, type, dmd->data_device, dmd->flags,
dmd->uuid, dmd->size, table_params, reload);
if (table_params)
r = _dm_create_device(name, type, dmd->data_device,
dmd->flags, dmd->uuid, dmd->size,
table_params, reload);
dm_exit_context();
return r;
}
static int dm_status_dmi(const char *name, struct dm_info *dmi,
@@ -664,7 +695,10 @@ int dm_status_device(struct crypt_device *cd, const char *name)
int r;
struct dm_info dmi;
if (dm_init_context(cd))
return -ENOTSUP;
r = dm_status_dmi(name, &dmi, NULL, NULL);
dm_exit_context();
if (r < 0)
return r;
@@ -676,7 +710,10 @@ int dm_status_suspended(struct crypt_device *cd, const char *name)
int r;
struct dm_info dmi;
if (dm_init_context(cd))
return -ENOTSUP;
r = dm_status_dmi(name, &dmi, DM_CRYPT_TARGET, NULL);
dm_exit_context();
if (r < 0)
return r;
@@ -704,7 +741,13 @@ static int _dm_status_verity_ok(const char *name)
int dm_status_verity_ok(struct crypt_device *cd, const char *name)
{
return _dm_status_verity_ok(name);
int r;
if (dm_init_context(cd))
return -ENOTSUP;
r = _dm_status_verity_ok(name);
dm_exit_context();
return r;
}
/* FIXME use hex wrapper, user val wrappers for line parsing */
@@ -943,6 +986,8 @@ int dm_query_device(struct crypt_device *cd, const char *name,
void *next = NULL;
int r = -EINVAL;
if (dm_init_context(cd))
return -ENOTSUP;
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
goto out;
if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
@@ -1004,6 +1049,7 @@ out:
if (dmt)
dm_task_destroy(dmt);
dm_exit_context();
return r;
}
@@ -1036,49 +1082,62 @@ static int _dm_message(const char *name, const char *msg)
int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name)
{
if (!_dm_check_versions())
int r = -ENOTSUP;
if (dm_init_context(cd))
return -ENOTSUP;
if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED))
return -ENOTSUP;
goto out;
if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0))
return -EINVAL;
if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0)) {
r = -EINVAL;
goto out;
}
if (!_dm_message(name, "key wipe")) {
_dm_simple(DM_DEVICE_RESUME, name, 1);
return -EINVAL;
r = -EINVAL;
goto out;
}
return 0;
r = 0;
out:
dm_exit_context();
return r;
}
int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
size_t key_size, const char *key)
{
int msg_size = key_size * 2 + 10; // key set <key>
char *msg;
int r = 0;
char *msg = NULL;
int r = -ENOTSUP;
if (!_dm_check_versions())
if (dm_init_context(cd))
return -ENOTSUP;
if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED))
return -ENOTSUP;
goto out;
msg = crypt_safe_alloc(msg_size);
if (!msg)
return -ENOMEM;
if (!msg) {
r = -ENOMEM;
goto out;
}
memset(msg, 0, msg_size);
strcpy(msg, "key set ");
hex_key(&msg[8], key_size, key);
if (!_dm_message(name, msg) ||
!_dm_simple(DM_DEVICE_RESUME, name, 1))
!_dm_simple(DM_DEVICE_RESUME, name, 1)) {
r = -EINVAL;
goto out;
}
r = 0;
out:
crypt_safe_free(msg);
dm_exit_context();
return r;
}

View File

@@ -143,7 +143,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
r = setup_mapping(dmCipherSpec, name, bsize, vk, sector, srcLength, mode, ctx);
if(r < 0) {
if (r != -EACCES)
if (r != -EACCES && r != -ENOTSUP)
log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
"Check that kernel supports %s cipher (check syslog for more info).\n%s"),
device_path(crypt_metadata_device(ctx)), dmCipherSpec,

View File

@@ -530,10 +530,7 @@ int crypt_init(struct crypt_device **cd, const char *device)
if (r < 0)
goto bad;
if (dm_init(h, 1) < 0) {
r = -ENOSYS;
goto bad;
}
dm_backend_init();
h->iteration_time = 1000;
h->password_verify = 0;
@@ -940,6 +937,11 @@ static int _crypt_format_luks1(struct crypt_device *cd,
&required_alignment,
&alignment_offset, DEFAULT_DISK_ALIGNMENT);
/* Check early if we cannot allocate block device for key slot access */
r = device_block_adjust(cd, cd->device, DEV_OK, 0, NULL, NULL);
if(r < 0)
return r;
r = LUKS_generate_phdr(&cd->hdr, cd->volume_key, cipher, cipher_mode,
(params && params->hash) ? params->hash : "sha1",
uuid, LUKS_STRIPES,
@@ -1334,7 +1336,7 @@ void crypt_free(struct crypt_device *cd)
if (cd) {
log_dbg("Releasing crypt device %s context.", mdata_device_path(cd));
dm_exit();
dm_backend_exit();
crypt_free_volume_key(cd->volume_key);
device_free(cd->device);
@@ -1382,8 +1384,8 @@ int crypt_suspend(struct crypt_device *cd,
return -EINVAL;
}
if (!cd && dm_init(NULL, 1) < 0)
return -ENOSYS;
if (!cd)
dm_backend_init();
r = dm_status_suspended(cd, name);
if (r < 0)
@@ -1402,7 +1404,7 @@ int crypt_suspend(struct crypt_device *cd,
log_err(cd, "Error during suspending device %s.\n", name);
out:
if (!cd)
dm_exit();
dm_backend_exit();
return r;
}
@@ -2019,8 +2021,8 @@ int crypt_deactivate(struct crypt_device *cd, const char *name)
log_dbg("Deactivating volume %s.", name);
if (!cd && dm_init(NULL, 1) < 0)
return -ENOSYS;
if (!cd)
dm_backend_init();
switch (crypt_status(cd, name)) {
case CRYPT_ACTIVE:
@@ -2037,7 +2039,7 @@ int crypt_deactivate(struct crypt_device *cd, const char *name)
}
if (!cd)
dm_exit();
dm_backend_exit();
return r;
}
@@ -2167,13 +2169,13 @@ crypt_status_info crypt_status(struct crypt_device *cd, const char *name)
{
int r;
if (!cd && dm_init(NULL, 1) < 0)
return CRYPT_INVALID;
if (!cd)
dm_backend_init();
r = dm_status_device(cd, name);
if (!cd)
dm_exit();
dm_backend_exit();
if (r < 0 && r != -ENODEV)
return CRYPT_INVALID;

View File

@@ -229,7 +229,7 @@ int crypt_memlock_inc(struct crypt_device *ctx)
if (!_memlock_count++) {
log_dbg("Locking memory.");
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
log_err(ctx, _("WARNING!!! Possibly insecure memory. Are you root?\n"));
log_dbg("Cannot lock memory with mlockall.");
_memlock_count--;
return 0;
}

View File

@@ -326,11 +326,15 @@ static int device_internal_prepare(struct crypt_device *cd, struct device *devic
if (device->init_done)
return 0;
log_dbg("Allocating free loop device.");
log_dbg("Allocating a free loop device.");
loop_device = crypt_loop_get_device();
if (!loop_device) {
log_err(cd, _("Cannot find a free loopback device.\n"));
return -EINVAL;
if (getuid() || geteuid())
log_err(cd, _("Cannot use a loopback device, "
"running as non-root user.\n"));
else
log_err(cd, _("Cannot find a free loopback device.\n"));
return -ENOTSUP;
}
/* Keep the loop open, dettached on last close. */

View File

@@ -79,8 +79,8 @@ struct crypt_dm_active_device {
} u;
};
int dm_init(struct crypt_device *context, int check_kernel);
void dm_exit(void);
void dm_backend_init(void);
void dm_backend_exit(void);
int dm_remove_device(struct crypt_device *cd, const char *name,
int force, uint64_t size);

View File

@@ -582,7 +582,7 @@ static int verify_keyslot(struct crypt_device *cd, int key_slot,
}
}
if (r < 0)
if (r == -EPERM)
log_err(_("No key available with this passphrase.\n"));
out:
crypt_safe_free(password);