Package: mount
Version: 2.12p-2
Severity: wishlist
Tags: patch

I have added support for using cryptsetup to mount devices over the dmcrypt
API present in kernels >= 2.6.4. It works like loopback encryption, but
whenever the user passes the option 'dmname=xxx' this switches to dmcrypt.

I choose to invoke /sbin/cryptsetup rather than link it in like losetup
because I don't think mount should depend on cryptographic libraries. This
way, if the user needs it, he is told to install it.

I've tested in in conjunction with loopback (ie: fs over dmcrypt over loop)
and by itself on block devices and it seems to work. It also works well with
automounting encrypted DVD/CDs. ;-)

Let me know what you think!

PS. There is one more thing I would like to change, but in a later patch to
keep things small and separate: when mount fails, it doesn't release
loopback devices (and now also device mapper devices). Since the user can
typo a passphrase, this should be handled more gracefully than it is now.

-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.6.8-1-686
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8)

Versions of packages mount depends on:
ii  libblkid1                   1.35-6       Block device id library
ii  libc6                       2.3.2.ds1-20 GNU C Library: Shared libraries
an
ii  libuuid1                    1.35-6       Universally unique id library

-- no debconf information
#! /bin/sh /usr/share/dpatch/dpatch-run
## 20cryptsetup.dpatch by Wesley W. Terpstra <[EMAIL PROTECTED]>
##
## All lines beginning with ## DP:' are a description of the patch.
## DP: Add cryptsetup support for mounting dmcrypt'd block devices

@DPATCH@
diff -ru util-linux-2.12p.orig/mount/lomount.c util-linux-2.12p/mount/lomount.c
--- util-linux-2.12p.orig/mount/lomount.c       2005-01-13 16:01:04.000000000 
+0100
+++ util-linux-2.12p/mount/lomount.c    2005-01-13 16:02:18.000000000 +0100
@@ -17,6 +17,7 @@
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <sys/sysmacros.h>
+#include <sys/wait.h>
 
 #include "loop.h"
 #include "lomount.h"
@@ -29,6 +30,8 @@
 extern char *xstrdup (const char *s);  /* not: #include "sundries.h" */
 extern void error (const char *fmt, ...);      /* idem */
 
+static const char cryptsetup[] = "/sbin/cryptsetup";
+
 #ifdef LOOP_SET_FD
 
 #include <getopt.h>
@@ -506,6 +509,65 @@
        return 1;
 }
 
+static int
+reap_dmcrypt (pid_t p) {
+       int st;
+       
+       if (waitpid(p, &st, 0) != p) {
+               fprintf(stderr, _("mount: could not reap cryptsetup\n"));
+               return 1;
+       }
+       
+       if (WIFEXITED(st) && WEXITSTATUS(st) == 0)
+               return 0;
+       
+       fprintf(stderr, _("mount: cryptsetup did not succeed\n"));
+       return 1;
+}
+
+static int
+check_cryptsetup(void) {
+       if (access(cryptsetup, X_OK) != 0) {
+               fprintf(stderr, _("mount: cryptsetup not installed?\n"));
+               fprintf(stderr, _("failed to (de)configure dmcrypt\n"));
+               return 1;
+       }
+       
+       return 0;
+}
+
+int
+set_dmcrypt(char* args[]) {
+       pid_t p;
+       
+       if (check_cryptsetup() != 0) 
+               return 1;
+       
+       if ((p = fork()) == 0) {
+               execv(cryptsetup, args);
+               fprintf(stderr, _("mount: cryptsetup exec failed\n"));
+               exit(1);
+       }
+       
+       return reap_dmcrypt(p);
+}
+
+int
+del_dmcrypt(const char* dmname) {
+       pid_t p;
+       
+       if (check_cryptsetup() != 0)
+               return 1;
+       
+       if ((p = fork()) == 0) {
+               execl(cryptsetup, cryptsetup, "remove", dmname, 0);
+               fprintf(stderr, _("mount: cryptsetup exec failed\n"));
+               exit(1);
+       }
+       
+       return reap_dmcrypt(p);
+}
+
 int 
 del_loop (const char *device) {
        int fd;
diff -ru util-linux-2.12p.orig/mount/lomount.h util-linux-2.12p/mount/lomount.h
--- util-linux-2.12p.orig/mount/lomount.h       2005-01-13 16:01:04.000000000 
+0100
+++ util-linux-2.12p/mount/lomount.h    2005-01-13 16:02:18.000000000 +0100
@@ -2,5 +2,7 @@
 extern int set_loop(const char *, const char *, unsigned long long,
                    const char *, int, int, int *, int);
 extern int del_loop(const char *);
+extern int set_dmcrypt(char* args[]);
+extern int del_dmcrypt(const char* dmname);
 extern int is_loop_device(const char *);
 extern char * find_unused_loop_device(void);
diff -ru util-linux-2.12p.orig/mount/mount.c util-linux-2.12p/mount/mount.c
--- util-linux-2.12p.orig/mount/mount.c 2005-01-13 16:01:04.000000000 +0100
+++ util-linux-2.12p/mount/mount.c      2005-01-13 16:02:18.000000000 +0100
@@ -174,7 +174,8 @@
 };
 
 static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
-  *opt_keybits, *opt_nohashpass, *opt_speed, *opt_comment;
+  *opt_keybits, *opt_keyhash, *opt_keyfile, *opt_nohashpass, *opt_dmname,
+  *opt_speed, *opt_comment;
 
 static struct string_opt_map {
   char *tag;
@@ -184,8 +185,11 @@
   { "loop=",   0, &opt_loopdev },
   { "vfs=",    1, &opt_vfstype },
   { "offset=", 0, &opt_offset },
+  { "dmname=", 0, &opt_dmname },
   { "encryption=", 0, &opt_encryption },
   { "keybits=", 0, &opt_keybits },
+  { "keyhash=", 0, &opt_keyhash },
+  { "keyfile=", 0, &opt_keyfile },
   { "nohashpass", 0, &opt_nohashpass },
   { "speed=", 0, &opt_speed },
   { "comment=", 1, &opt_comment },
@@ -615,8 +619,8 @@
       *type = opt_vfstype;
   }
 
-  *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption ||
-          opt_keybits);
+  *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || 
+           ((opt_encryption || opt_keybits) && !opt_dmname));
   *loopfile = *spec;
 
   if (*loop) {
@@ -655,6 +659,66 @@
   return 0;
 }
 
+static int
+dmcrypt_check(const char **spec, int* flags, 
+              int* dmcrypt, const char **dmdev) {
+       const char* args[30];
+       char* mapper;
+       int i = 0;
+       *dmcrypt = opt_dmname?1:0;
+       
+       if (*dmcrypt) {
+               *dmdev = *spec;
+               *spec = mapper = malloc(strlen(opt_dmname) + 30);
+               sprintf(mapper, "/dev/mapper/%s", opt_dmname);
+               
+               args[i++] = "cryptsetup";
+               
+               if (*flags & MS_RDONLY) {
+                       args[i++] = "-r";
+               }
+               if (opt_keyfile) {
+                       args[i++] = "--key-file";
+                       args[i++] = opt_keyfile;
+               }
+               if (opt_keybits) {
+                       args[i++] = "--key-size";
+                       args[i++] = opt_keybits;
+               }
+               if (opt_keyhash) {
+                       args[i++] = "--hash";
+                       args[i++] = opt_keyhash;
+               }
+               if (opt_encryption) {
+                       args[i++] = "--cipher";
+                       args[i++] = opt_encryption;
+               }
+               
+               args[i++] = "create";
+               args[i++] = opt_dmname;
+               args[i++] = *dmdev;
+               args[i] = 0;
+               
+               if (verbose) {
+                       int j;
+                       printf("mount:");
+                       for (j = 0; j < i; ++j)
+                               printf(" %s", args[j]);
+                       printf("\n");
+               }
+               
+               if (set_dmcrypt((char**)args) != 0)
+                       return EX_FAIL;
+       } else {
+               if (opt_keyhash)
+                       fprintf(stderr, _("mount: keyhash only supported with 
cryptsetup; set dmname\n"));
+               if (opt_keyfile)
+                       fprintf(stderr, _("mount: keyfile only supported with 
cryptsetup; set dmname\n"));
+       }
+       
+       return 0;
+}
+
 static void
 update_mtab_entry(const char *spec, const char *node, const char *type,
                  const char *opts, int flags, int freq, int pass) {
@@ -800,8 +864,8 @@
   char *mount_opts;            /* actually used on system call */
   const char *opts, *spec, *node, *types;
   char *user = 0;
-  int loop = 0;
-  const char *loopdev = 0, *loopfile = 0;
+  int loop = 0, dmcrypt = 0;
+  const char *loopdev = 0, *loopfile = 0, *dmdev = 0;
   struct stat statbuf;
   int nfs_mount_version = 0;   /* any version */
 
@@ -836,6 +890,10 @@
       res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile);
       if (res)
          goto out;
+      
+      res = dmcrypt_check(&spec, &flags, &dmcrypt, &dmdev);
+      if (res)
+         goto out;
   }
 
   /*
@@ -877,7 +945,7 @@
       if (loop)
          opt_loopdev = loopdev;
 
-      update_mtab_entry(loop ? loopfile : spec,
+      update_mtab_entry(loop ? loopfile : (dmcrypt ? dmdev : spec),
                        node,
                        types ? types : "unknown",
                        fix_opts_string (flags & ~MS_NOMTAB, extra_opts, user),
@@ -892,6 +960,8 @@
 
   mnt_err = errno;
 
+  if (dmcrypt)
+       del_dmcrypt(opt_dmname);
   if (loop)
        del_loop(spec);
 
diff -ru util-linux-2.12p.orig/mount/umount.c util-linux-2.12p/mount/umount.c
--- util-linux-2.12p.orig/mount/umount.c        2004-12-20 23:03:45.000000000 
+0100
+++ util-linux-2.12p/mount/umount.c     2005-01-13 16:02:19.000000000 +0100
@@ -274,6 +274,7 @@
        int res;
        int status;
        const char *loopdev;
+       const char *dmname;
 
        /* Special case for root.  As of 0.99pl10 we can (almost) unmount root;
           the kernel will remount it readonly so that we can carry on running
@@ -366,11 +367,28 @@
        }
 
        loopdev = 0;
+       dmname = 0;
        if (res >= 0) {
                /* Umount succeeded */
                if (verbose)
                        printf (_("%s umounted\n"), spec);
 
+               /* Remove the crypted device first */
+               if (mc) {
+                       char *optl;
+                       
+                       /* new style mtab line? */
+                       optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : "";
+                       for (optl = strtok (optl, ","); optl;
+                            optl = strtok (NULL, ",")) {
+                               if (!strncmp(optl, "dmname=", 7)) {
+                                       dmname = optl+7;
+                               }
+                       }
+                       
+                       if (dmname) del_dmcrypt(dmname);
+               }
+               
                /* Free any loop devices that we allocated ourselves */
                if (mc) {
                        char *optl;

Attachment: signature.asc
Description: Digital signature

Reply via email to