From b781113cf1391926dedf8dc943624d3bb9726318 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sun, 14 Aug 2016 20:17:51 +0200 Subject: [PATCH] g13: Implement --umount for dm-crypt. * g13/g13.c (main): Implement command --umount. * g13/mount.c (g13_umount_container): use the syshelper if needed. * g13/backend.c (be_umount_container): New. * g13/be-dmcrypt.c (be_dmcrypt_umount_container): New. * g13/call-syshelp.c (call_syshelp_run_umount): New. * g13/sh-cmd.c (cmd_umount): New. (register_commands): Register UMOUNT. * g13/sh-dmcrypt.c (sh_dmcrypt_umount_container): New. Signed-off-by: Werner Koch --- g13/backend.c | 18 +++++++++ g13/backend.h | 1 + g13/be-dmcrypt.c | 17 +++++++++ g13/be-dmcrypt.h | 1 + g13/call-syshelp.c | 34 +++++++++++++++++ g13/call-syshelp.h | 1 + g13/g13-syshelp.h | 1 + g13/g13.c | 7 ++-- g13/mount.c | 60 ++++++++++++++++++++---------- g13/sh-cmd.c | 35 +++++++++++++++++ g13/sh-dmcrypt.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 245 insertions(+), 23 deletions(-) diff --git a/g13/backend.c b/g13/backend.c index dd2176834..659c6b749 100644 --- a/g13/backend.c +++ b/g13/backend.c @@ -240,6 +240,24 @@ be_mount_container (ctrl_t ctrl, int conttype, } +/* Dispatcher to the backend's umount function. */ +gpg_error_t +be_umount_container (ctrl_t ctrl, int conttype, const char *fname) +{ + switch (conttype) + { + case CONTTYPE_ENCFS: + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + case CONTTYPE_DM_CRYPT: + return be_dmcrypt_umount_container (ctrl, fname); + + default: + return no_such_backend (conttype); + } +} + + /* Dispatcher to the backend's suspend function. */ gpg_error_t be_suspend_container (ctrl_t ctrl, int conttype, const char *fname) diff --git a/g13/backend.h b/g13/backend.h index 66d9cd593..d1cedb36f 100644 --- a/g13/backend.h +++ b/g13/backend.h @@ -39,6 +39,7 @@ gpg_error_t be_mount_container (ctrl_t ctrl, int conttype, const char *fname, const char *mountpoint, tupledesc_t tuples, unsigned int *r_id); +gpg_error_t be_umount_container (ctrl_t ctrl, int conttype, const char *fname); gpg_error_t be_suspend_container (ctrl_t ctrl, int conttype, const char *fname); gpg_error_t be_resume_container (ctrl_t ctrl, int conttype, diff --git a/g13/be-dmcrypt.c b/g13/be-dmcrypt.c index e5e9b332a..c65be0894 100644 --- a/g13/be-dmcrypt.c +++ b/g13/be-dmcrypt.c @@ -64,6 +64,23 @@ be_dmcrypt_mount_container (ctrl_t ctrl, } +/* Unmount the container described by the filename FNAME. */ +gpg_error_t +be_dmcrypt_umount_container (ctrl_t ctrl, const char *fname) +{ + gpg_error_t err; + + err = call_syshelp_set_device (ctrl, fname); + if (err) + goto leave; + + err = call_syshelp_run_umount (ctrl, CONTTYPE_DM_CRYPT); + + leave: + return err; +} + + /* Suspend the container described by the filename FNAME. */ gpg_error_t be_dmcrypt_suspend_container (ctrl_t ctrl, const char *fname) diff --git a/g13/be-dmcrypt.h b/g13/be-dmcrypt.h index d74e09f7c..189bfee7b 100644 --- a/g13/be-dmcrypt.h +++ b/g13/be-dmcrypt.h @@ -27,6 +27,7 @@ gpg_error_t be_dmcrypt_mount_container (ctrl_t ctrl, const char *fname, const char *mountpoint, tupledesc_t tuples); +gpg_error_t be_dmcrypt_umount_container (ctrl_t ctrl, const char *fname); gpg_error_t be_dmcrypt_suspend_container (ctrl_t ctrl, const char *fname); gpg_error_t be_dmcrypt_resume_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples); diff --git a/g13/call-syshelp.c b/g13/call-syshelp.c index 952d8de77..76d181b67 100644 --- a/g13/call-syshelp.c +++ b/g13/call-syshelp.c @@ -520,6 +520,40 @@ call_syshelp_run_mount (ctrl_t ctrl, int conttype, const char *mountpoint, } + +/* + * Run the UMOUNT command on the current device. CONTTYPES gives the + * content type of the container (fixme: Do we really need this?). + */ +gpg_error_t +call_syshelp_run_umount (ctrl_t ctrl, int conttype) +{ + gpg_error_t err; + assuan_context_t ctx; + + err = start_syshelp (ctrl, &ctx); + if (err) + goto leave; + + if (conttype == CONTTYPE_DM_CRYPT) + { + err = assuan_transact (ctx, "UMOUNT dm-crypt", + NULL, NULL, + NULL, NULL, + NULL, NULL); + } + else + { + log_error ("invalid backend type %d given\n", conttype); + err = GPG_ERR_INTERNAL; + goto leave; + } + + leave: + return err; +} + + /* * Run the SUSPEND command on the current device. CONTTYPES gives the diff --git a/g13/call-syshelp.h b/g13/call-syshelp.h index aa4b692f4..0e110c903 100644 --- a/g13/call-syshelp.h +++ b/g13/call-syshelp.h @@ -33,6 +33,7 @@ gpg_error_t call_syshelp_run_create (ctrl_t ctrl, int conttype); gpg_error_t call_syshelp_run_mount (ctrl_t ctrl, int conttype, const char *mountpoint, tupledesc_t tuples); +gpg_error_t call_syshelp_run_umount (ctrl_t ctrl, int conttype); gpg_error_t call_syshelp_run_suspend (ctrl_t ctrl, int conttype); gpg_error_t call_syshelp_run_resume (ctrl_t ctrl, int conttype, tupledesc_t tuples); diff --git a/g13/g13-syshelp.h b/g13/g13-syshelp.h index dae2bd05c..618b41de5 100644 --- a/g13/g13-syshelp.h +++ b/g13/g13-syshelp.h @@ -86,6 +86,7 @@ gpg_error_t sh_dmcrypt_create_container (ctrl_t ctrl, const char *devname, estream_t devfp); gpg_error_t sh_dmcrypt_mount_container (ctrl_t ctrl, const char *devname, tupledesc_t keyblob); +gpg_error_t sh_dmcrypt_umount_container (ctrl_t ctrl, const char *devname); gpg_error_t sh_dmcrypt_suspend_container (ctrl_t ctrl, const char *devname); gpg_error_t sh_dmcrypt_resume_container (ctrl_t ctrl, const char *devname, tupledesc_t keyblob); diff --git a/g13/g13.c b/g13/g13.c index 799fd6651..7744855c2 100644 --- a/g13/g13.c +++ b/g13/g13.c @@ -793,9 +793,10 @@ main ( int argc, char **argv) { if (argc != 1) wrong_args ("--umount filename"); - err = GPG_ERR_NOT_IMPLEMENTED; - log_error ("error unmounting container '%s': %s <%s>\n", - *argv, gpg_strerror (err), gpg_strsource (err)); + err = g13_umount_container (&ctrl, argv[0], NULL); + if (err) + log_error ("error unmounting container '%s': %s <%s>\n", + *argv, gpg_strerror (err), gpg_strsource (err)); } break; diff --git a/g13/mount.c b/g13/mount.c index d6825859d..f4371cce5 100644 --- a/g13/mount.c +++ b/g13/mount.c @@ -64,10 +64,7 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint) if (access (filename, F_OK)) return gpg_error_from_syserror (); - /* Decide whether we need to use the g13-syshelp because we can't - use lock files for them. This is most likely the case for device - files; thus we test for this. FIXME: The correct solution would - be to call g13-syshelp to match the file against the g13tab. */ + /* Decide whether we need to use the g13-syshelp. */ err = call_syshelp_find_device (ctrl, filename, &blockdev_buffer); if (!err) { @@ -217,27 +214,50 @@ gpg_error_t g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint) { gpg_error_t err; - unsigned int rid; - runner_t runner; - - (void)ctrl; + char *blockdev; if (!filename && !mountpoint) return gpg_error (GPG_ERR_ENOENT); - err = mountinfo_find_mount (filename, mountpoint, &rid); - if (err) - return err; - - runner = runner_find_by_rid (rid); - if (!runner) + /* Decide whether we need to use the g13-syshelp. */ + err = call_syshelp_find_device (ctrl, filename, &blockdev); + if (!err) { - log_error ("runner %u not found\n", rid); - return gpg_error (GPG_ERR_NOT_FOUND); + /* Need to employ the syshelper to umount the file system. */ + /* FIXME: We should get the CONTTYPE from the blockdev. */ + err = be_umount_container (ctrl, CONTTYPE_DM_CRYPT, blockdev); + if (!err) + { + /* if (conttype == CONTTYPE_DM_CRYPT) */ + g13_request_shutdown (); + } + } + else if (gpg_err_code (err) != GPG_ERR_NOT_FOUND) + { + log_error ("error finding device '%s': %s <%s>\n", + filename, gpg_strerror (err), gpg_strsource (err)); + } + else + { + /* Not in g13tab - kill the runner process for this mount. */ + unsigned int rid; + runner_t runner; + + err = mountinfo_find_mount (filename, mountpoint, &rid); + if (err) + return err; + + runner = runner_find_by_rid (rid); + if (!runner) + { + log_error ("runner %u not found\n", rid); + return gpg_error (GPG_ERR_NOT_FOUND); + } + + runner_cancel (runner); + runner_release (runner); } - runner_cancel (runner); - runner_release (runner); - - return 0; + xfree (blockdev); + return err; } diff --git a/g13/sh-cmd.c b/g13/sh-cmd.c index 20db8dce0..821491982 100644 --- a/g13/sh-cmd.c +++ b/g13/sh-cmd.c @@ -500,6 +500,40 @@ cmd_mount (assuan_context_t ctx, char *line) } +static const char hlp_umount[] = + "UMOUNT \n" + "\n" + "Unmount an encrypted partition and wipe the key.\n" + " must be \"dm-crypt\" for now."; +static gpg_error_t +cmd_umount (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err = 0; + + line = skip_options (line); + + if (strcmp (line, "dm-crypt")) + { + err = set_error (GPG_ERR_INV_ARG, "Type must be \"dm-crypt\""); + goto leave; + } + + if (!ctrl->server_local->devicename + || !ctrl->server_local->devicefp + || !ctrl->devti) + { + err = set_error (GPG_ERR_ENOENT, "No device has been set"); + goto leave; + } + + err = sh_dmcrypt_umount_container (ctrl, ctrl->server_local->devicename); + + leave: + return leave_cmd (ctx, err); +} + + static const char hlp_suspend[] = "SUSPEND \n" "\n" @@ -713,6 +747,7 @@ register_commands (assuan_context_t ctx, int fail_all) { "CREATE", cmd_create, hlp_create }, { "GETKEYBLOB", cmd_getkeyblob, hlp_getkeyblob }, { "MOUNT", cmd_mount, hlp_mount }, + { "UMOUNT", cmd_umount, hlp_umount }, { "SUSPEND", cmd_suspend,hlp_suspend}, { "RESUME", cmd_resume, hlp_resume }, { "INPUT", NULL }, diff --git a/g13/sh-dmcrypt.c b/g13/sh-dmcrypt.c index e0cd2e1a1..201f8569e 100644 --- a/g13/sh-dmcrypt.c +++ b/g13/sh-dmcrypt.c @@ -723,6 +723,99 @@ sh_dmcrypt_mount_container (ctrl_t ctrl, const char *devname, } +/* Unmount a DM-Crypt container on device DEVNAME and wipe the keys. */ +gpg_error_t +sh_dmcrypt_umount_container (ctrl_t ctrl, const char *devname) +{ + gpg_error_t err; + char *targetname_abs = NULL; + char *result = NULL; + + if (!ctrl->devti) + return gpg_error (GPG_ERR_INV_ARG); + + g13_syshelp_i_know_what_i_am_doing (); + + /* Check that the device is used by device mapper. */ + err = check_blockdev (devname, 1); + if (gpg_err_code (err) != GPG_ERR_EBUSY) + { + log_error ("device '%s' is not used by the device mapper: %s\n", + devname, gpg_strerror (err)); + goto leave; + } + + /* Fixme: Check that this is really a g13 partition. */ + + /* Device mapper needs a name for the device: Take it from the label + or use "0". */ + targetname_abs = strconcat ("/dev/mapper/", + "g13-", ctrl->client.uname, "-", + ctrl->devti->label? ctrl->devti->label : "0", + NULL); + if (!targetname_abs) + { + err = gpg_error_from_syserror (); + goto leave; + } + + /* Run the regular umount command. */ + { + const char *argv[2]; + + argv[0] = targetname_abs; + argv[1] = NULL; + log_debug ("now running \"umount %s\"\n", targetname_abs); + err = gnupg_exec_tool ("/bin/umount", argv, NULL, &result, NULL); + } + if (err) + { + log_error ("error running umount: %s\n", gpg_strerror (err)); + if (1) + { + /* Try to show some info about processes using the partition. */ + const char *argv[3]; + + argv[0] = "-mv"; + argv[1] = targetname_abs; + argv[2] = NULL; + gnupg_exec_tool ("/bin/fuser", argv, NULL, &result, NULL); + } + goto leave; + } + if (result && *result) /* (We should not see output to stdout). */ + log_info ("WARNING: umount returned data on stdout! (%s)\n", result); + xfree (result); + result = NULL; + + /* Run the dmsetup remove command. */ + { + const char *argv[3]; + + argv[0] = "remove"; + argv[1] = targetname_abs; + argv[2] = NULL; + log_debug ("now running \"dmsetup remove %s\"\n", targetname_abs); + err = gnupg_exec_tool ("/sbin/dmsetup", argv, NULL, &result, NULL); + } + if (err) + { + log_error ("error running \"dmsetup remove %s\": %s\n", + targetname_abs, gpg_strerror (err)); + goto leave; + } + if (result && *result) + log_debug ("dmsetup result: %s\n", result); + xfree (result); + result = NULL; + + leave: + xfree (targetname_abs); + xfree (result); + return err; +} + + /* Suspend a DM-Crypt container on device DEVNAME and wipe the keys. */ gpg_error_t sh_dmcrypt_suspend_container (ctrl_t ctrl, const char *devname)