libmount: add support for encrypted loopdevs

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2012-01-11 16:16:00 +01:00
parent 6af8d3d722
commit 1a7a421ed7
6 changed files with 54 additions and 2 deletions

View File

@ -896,6 +896,26 @@ struct libmnt_cache *mnt_context_get_cache(struct libmnt_context *cxt)
return cxt->cache;
}
/**
* mnt_context_set_passwd_cb:
* @cxt: mount context
*
* Sets callbacks for encryption password.
*
* Returns: 0 on success, negative number in case of error.
*/
int mnt_context_set_passwd_cb(struct libmnt_context *cxt,
char *(*get)(struct libmnt_context *),
void (*release)(struct libmnt_context *, char *))
{
if (!cxt)
return -EINVAL;
cxt->pwd_get_cb = get;
cxt->pwd_release_cb = release;
return 0;
}
/**
* mnt_context_get_lock:
* @cxt: mount context

View File

@ -34,7 +34,8 @@ int mnt_context_is_loopdev(struct libmnt_context *cxt)
if (cxt->user_mountflags & (MNT_MS_LOOP |
MNT_MS_OFFSET |
MNT_MS_SIZELIMIT))
MNT_MS_SIZELIMIT |
MNT_MS_ENCRYPTION))
return 1;
if (cxt->mountflags & (MS_BIND | MS_MOVE | MS_PROPAGATION))
@ -64,7 +65,7 @@ int mnt_context_is_loopdev(struct libmnt_context *cxt)
int mnt_context_setup_loopdev(struct libmnt_context *cxt)
{
const char *backing_file, *optstr, *loopdev = NULL;
char *val = NULL;
char *val = NULL, *enc = NULL, *pwd = NULL;
size_t len;
struct loopdev_cxt lc;
int rc = 0, lo_flags = 0;
@ -125,6 +126,20 @@ int mnt_context_setup_loopdev(struct libmnt_context *cxt)
DBG(CXT, mnt_debug_h(cxt, "failed to parse sizelimit="));
}
/*
* encryption=
*/
if (rc == 0 && (cxt->user_mountflags & MNT_MS_ENCRYPTION) &&
mnt_optstr_get_option(optstr, "encryption", &val, &len) == 0) {
enc = strndup(val, len);
if (val && !enc)
rc = -ENOMEM;
if (enc && cxt->pwd_get_cb) {
DBG(CXT, mnt_debug_h(cxt, "asking for pass"));
pwd = cxt->pwd_get_cb(cxt);
}
}
if (rc)
goto done;
@ -156,6 +171,8 @@ int mnt_context_setup_loopdev(struct libmnt_context *cxt)
rc = loopcxt_set_offset(&lc, offset);
if (!rc && sizelimit)
rc = loopcxt_set_sizelimit(&lc, sizelimit);
if (!rc && enc && pwd)
loopcxt_set_encryption(&lc, enc, pwd);
if (!rc)
loopcxt_set_flags(&lc, lo_flags);
if (rc) {
@ -208,6 +225,11 @@ int mnt_context_setup_loopdev(struct libmnt_context *cxt)
loopcxt_set_fd(&lc, -1, 0);
}
done:
free(enc);
if (pwd && cxt->pwd_release_cb) {
DBG(CXT, mnt_debug_h(cxt, "release pass"));
cxt->pwd_release_cb(cxt, pwd);
}
loopcxt_deinit(&lc);
return rc;
}

View File

@ -431,6 +431,10 @@ extern int mnt_context_set_fstype_pattern(struct libmnt_context *cxt,
extern int mnt_context_set_options_pattern(struct libmnt_context *cxt,
const char *pattern);
extern int mnt_context_set_passwd_cb(struct libmnt_context *cxt,
char *(*get)(struct libmnt_context *),
void (*release)(struct libmnt_context *, char *));
extern int mnt_context_set_tables_errcb(struct libmnt_context *cxt,
int (*cb)(struct libmnt_table *tb, const char *filename, int line));
extern int mnt_context_set_fstab(struct libmnt_context *cxt,
@ -498,6 +502,7 @@ extern int mnt_context_set_syscall_status(struct libmnt_context *cxt, int status
#define MNT_MS_XCOMMENT (1 << 13)
#define MNT_MS_OFFSET (1 << 14)
#define MNT_MS_SIZELIMIT (1 << 15)
#define MNT_MS_ENCRYPTION (1 << 16)
/*
* mount(2) MS_* masks (MNT_MAP_LINUX map)

View File

@ -213,6 +213,7 @@ global:
mnt_context_is_fork;
mnt_context_is_parent;
mnt_context_next_umount;
mnt_context_set_passwd_cb;
mnt_context_wait_for_children;
mnt_fs_is_netfs;
mnt_fs_is_pseudofs;

View File

@ -276,6 +276,9 @@ struct libmnt_context
int (*table_errcb)(struct libmnt_table *tb, /* callback for libmnt_table structs */
const char *filename, int line);
char *(*pwd_get_cb)(struct libmnt_context *); /* get encryption password */
void (*pwd_release_cb)(struct libmnt_context *, char *); /* release password */
int optsmode; /* fstab optstr mode MNT_OPTSMODE_{AUTO,FORCE,IGNORE} */
int loopdev_fd; /* open loopdev */

View File

@ -147,6 +147,7 @@ static const struct libmnt_optmap userspace_opts_map[] =
{ "loop[=]", MNT_MS_LOOP }, /* use the loop device */
{ "offset=", MNT_MS_OFFSET, MNT_NOMTAB }, /* loop device offset */
{ "sizelimit=", MNT_MS_SIZELIMIT, MNT_NOMTAB }, /* loop device size limit */
{ "encryption=", MNT_MS_ENCRYPTION, MNT_NOMTAB }, /* loop device encryption */
{ "nofail", MNT_MS_NOFAIL, MNT_NOMTAB }, /* Do not fail if ENOENT on dev */