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;
signature.asc
Description: Digital signature