ecryptfs-devel team mailing list archive
-
ecryptfs-devel team
-
Mailing list archive
-
Message #00000
[PATCH] mount.ecryptfs_private/umount.ecryptfs_private counter
[PATCH] mount.ecryptfs_private/umount.ecryptfs_private counter
We have been receiving bug reports about "random" unmounts of
encrypted private directories. Rather than truly "random", these were
undesired, and caused usually by cronjobs or additional ssh/console
login sessions. Each of these would trigger a pam close session,
which would call umount.ecryptfs_private.
To solve this correctly, we need a counter, incremented each time a
mount.ecryptfs_private is successfully attempted, and a decrement each
time umount.ecryptfs_private is successfully attempted, as well as
zero'ing out the counter when an unmount succeeds. A umount is then
only actually attempted when the counter reaches 0 (or if the user
overrides the counter with a -f option). Alternatively, the user can
remove their counter file at any time (interpreted as a count of 0).
This patch also updates the manpage to describe the -f option.
We are about to carry this patch in Ubuntu Intrepid, but any feedback
would be much appreciated.
Signed-off-by: Dustin Kirkland <kirkland@xxxxxxxxxxxxx>
--- ecryptfs-utils-53/doc/manpage/umount.ecryptfs_private.1 2008-07-23 11:17:30.000000000 -0500
+++ ecryptfs-utils-53/doc/manpage/umount.ecryptfs_private.1 2008-10-16 23:08:23.057270798 -0500
@@ -3,7 +3,13 @@
umount.ecryptfs_private \- eCryptfs private unmount helper.
.SH SYNOPSIS
-\fBumount.ecryptfs_private\fP
+\fBumount.ecryptfs_private\fP [\-f]
+
+.SH OPTIONS
+Options available for the \fBumount.ecryptfs_private\fP command:
+.TP
+.B \-f
+Force the unmount, ignoring the value of the mount counter in \fI/tmp/ecryptfs-USERNAME-Private\fP
.SH DESCRIPTION
\fBumount.ecryptfs_private\fP is a mount helper utility for non-root users to unmount a cryptographically mounted private directory, ~/Private.
@@ -12,6 +18,7 @@ If, and only if:
- the private mount passphrase is in their kernel keyring, and
- the current user owns both ~/.Private and ~/Private, and
- ~/.Private is currently mounted on ~/Private
+ - the mount counter is 0 (counter is ignored if \-f option is used)
This program will:
- unmount ~/Private
@@ -27,6 +34,8 @@ The system administrator can add the pam
\fI~/.ecryptfs/Private.sig\fP - file containing signature of mountpoint passphrase
+\fI/tmp/ecryptfs-USERNAME-Private\fP - file containing the mount counter, incremented on each mount, decremented on each unmount
+
.SH SEE ALSO
.PD 0
.TP
--- ecryptfs-utils-53/src/utils/mount.ecryptfs_private.c 2008-10-16 22:52:50.545866066 -0500
+++ ecryptfs-utils-53/src/utils/mount.ecryptfs_private.c 2008-10-16 23:24:33.756948619 -0500
@@ -25,6 +25,7 @@
*/
+#include <sys/file.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -254,6 +255,87 @@ int update_mtab(char *dev, char *mnt, ch
}
+int bump_counter(char *u, int delta) {
+/* Maintain a mount counter
+ * increment on delta = 1
+ * decrement on delta = -1
+ * remove the counter file on delta = 0
+ * return the updated count, negative on error
+ */
+ char *f;
+ FILE *fh;
+ struct stat s;
+ mode_t m;
+ int count;
+ /* We expect /tmp to exist, be writeable by the user,
+ * and for this file to be cleared on boot */
+ if (
+ asprintf(&f, "/tmp/%s-%s-%s", FSTYPE, u, PRIVATE_DIR) < 0
+ ) {
+ perror("asprintf");
+ return -1;
+ }
+ if (delta == 0) {
+ /* Try to remove the counter file */
+ return unlink(f);
+ }
+ if (stat(f, &s) == 0) {
+ /* If the counter file exists, open for reading/writing */
+ fh = fopen(f, "r+");
+ } else {
+ /* If the counter file does not exist, create for writing */
+ m = umask(0177);
+ fh = fopen(f, "w+");
+ umask(m);
+ }
+ if (fh == NULL) {
+ perror("fopen");
+ return -1;
+ }
+ /* Lock the file for reading/writing */
+ if (flock(fileno(fh), LOCK_EX) != 0) {
+ perror("flock");
+ return -1;
+ }
+ rewind(fh);
+ /* Read the count from file, default to 0 */
+ if (fscanf(fh, "%d\n", &count) != 1) {
+ count = 0;
+ }
+ /* Increment/decrement the counter */
+ count += delta;
+ if (count < 0) {
+ /* Don't set a count less than 0 */
+ count = 0;
+ }
+ /* Write the count to file */
+ rewind(fh);
+ fprintf(fh, "%d\n", count);
+ /* Unlock the file */
+ if (flock(fileno(fh), LOCK_UN) != 0) {
+ perror("flock");
+ }
+ return count;
+}
+
+
+int increment(char *u) {
+/* Bump counter up */
+ return bump_counter(u, 1);
+}
+
+
+int decrement(char *u) {
+/* Bump counter down */
+ return bump_counter(u, -1);
+}
+
+int zero(char *u) {
+/* Remove the counter file */
+ return bump_counter(u, 0);
+}
+
+
/* This program is a setuid-executable allowing a non-privileged user to mount
* and unmount an ecryptfs private directory. This program is necessary to
* keep from adding such entries to /etc/fstab.
@@ -289,7 +371,7 @@ int update_mtab(char *dev, char *mnt, ch
* c) updating /etc/mtab
*/
int main(int argc, char *argv[]) {
- int uid, rc, mounting;
+ int uid, rc, mounting, force;
struct passwd *pwd;
char *dev, *mnt, *opt;
char *sig;
@@ -321,6 +403,12 @@ int main(int argc, char *argv[]) {
mounting = 1;
} else {
mounting = 0;
+ /* Determine if unmounting is forced */
+ if (argv[1] != NULL && strncmp(argv[1], "-f", 2) == 0) {
+ force = 1;
+ } else {
+ force = 0;
+ }
}
/* Fetch signature from file */
@@ -355,6 +443,8 @@ int main(int argc, char *argv[]) {
}
if (mounting == 1) {
+ /* Increment mount counter, errors non-fatal */
+ increment(pwd->pw_name);
/* Mounting, so exit if already mounted */
if (is_mounted(dev, mnt, sig, mounting) == 1) {
/* fputs("Already mounted\n", stderr); */
@@ -380,6 +470,15 @@ int main(int argc, char *argv[]) {
return 1;
}
} else {
+ /* Decrement counter, exiting if >0, and non-forced unmount */
+ if (decrement(pwd->pw_name) > 0 && force != 1) {
+ fputs("Sessions still open, not unmounting\n", stderr);
+ return 1;
+ }
+ /* If we have made it here, zero the counter,
+ * as we are going to unmount.
+ */
+ zero(pwd->pw_name);
/* Unmounting, so exit if not mounted */
if (is_mounted(dev, mnt, sig, mounting) == 0) {
/* fputs("Not currently mounted\n", stderr); */