g13: Implement --umount for dm-crypt.
authorWerner Koch <wk@gnupg.org>
Sun, 14 Aug 2016 18:17:51 +0000 (20:17 +0200)
committerWerner Koch <wk@gnupg.org>
Sun, 14 Aug 2016 18:17:51 +0000 (20:17 +0200)
* 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 <wk@gnupg.org>
g13/backend.c
g13/backend.h
g13/be-dmcrypt.c
g13/be-dmcrypt.h
g13/call-syshelp.c
g13/call-syshelp.h
g13/g13-syshelp.h
g13/g13.c
g13/mount.c
g13/sh-cmd.c
g13/sh-dmcrypt.c

index dd21768..659c6b7 100644 (file)
@@ -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)
index 66d9cd5..d1cedb3 100644 (file)
@@ -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,
index e5e9b33..c65be08 100644 (file)
@@ -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)
index d74e09f..189bfee 100644 (file)
@@ -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);
index 952d8de..76d181b 100644 (file)
@@ -522,6 +522,40 @@ call_syshelp_run_mount (ctrl_t ctrl, int conttype, const char *mountpoint,
 
 \f
 /*
+ * 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;
+}
+
+
+\f
+/*
  * Run the SUSPEND command on the current device.  CONTTYPES gives the
  * requested content type for the new container.
  */
index aa4b692..0e110c9 100644 (file)
@@ -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);
index dae2bd0..618b41d 100644 (file)
@@ -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);
index 799fd66..7744855 100644 (file)
--- 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;
 
index d682585..f4371cc 100644 (file)
@@ -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)
+    {
+      /* 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 ("runner %u not found\n", rid);
-      return gpg_error (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;
 
-  runner_cancel (runner);
-  runner_release (runner);
+      err = mountinfo_find_mount (filename, mountpoint, &rid);
+      if (err)
+        return err;
 
-  return 0;
+      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);
+    }
+
+  xfree (blockdev);
+  return err;
 }
index 20db8dc..8214919 100644 (file)
@@ -500,6 +500,40 @@ cmd_mount (assuan_context_t ctx, char *line)
 }
 
 
+static const char hlp_umount[] =
+  "UMOUNT <type>\n"
+  "\n"
+  "Unmount an encrypted partition and wipe the key.\n"
+  "<type> 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 <type>\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 },
index e0cd2e1..201f856 100644 (file)
@@ -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)