From 658320e3a2f8a7002f0038bb7990e350c4462d9a Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Tue, 28 Jul 2009 20:45:38 -0400 Subject: [PATCH 1/1] capabilities: worthless 1st draft: mount.ecryptfs_private without suid This patch (plus forcing Makefile to -lcap) allows mount.ecryptfs_private to use capabilities --- src/utils/mount.ecryptfs_private.c | 77 +++++++++++++++++++++-------------- 1 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/utils/mount.ecryptfs_private.c b/src/utils/mount.ecryptfs_private.c index 9edefcc..70daa6a 100644 --- a/src/utils/mount.ecryptfs_private.c +++ b/src/utils/mount.ecryptfs_private.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "../include/ecryptfs.h" /* Perhaps a future version of this program will allow these to be configurable @@ -339,20 +340,37 @@ int main(int argc, char *argv[]) { int uid, mounting; int force = 0; int fnek = 1; + int ret; struct passwd *pwd; char *dev, *mnt, *opt; char *sig, *sig_fnek; FILE *fh_counter = NULL; + cap_t cap_lowered = NULL, + cap_raised = NULL, + cap_umount = NULL, + cap_dropped = NULL; - uid = getuid(); - /* Non-privileged effective uid is sufficient for all but the code - * that mounts, unmounts, and updates /etc/mtab. - * Run at a lower privilege until we need it. + /* + * create a few capability sets we might need: + * + * 1. cap_lowered: we have the privs we might need in pP + * 2. cap_dropped: no privs at all + * 3. cap_umount: we have cap_sys_admin in pI only + * 4. cap_raised: we have cap_sys_admin and maybe + cap_da_override in pE. */ - if (seteuid(uid)<0 || geteuid()!=uid) { - perror("setuid"); + cap_lowered = cap_from_text("cap_sys_admin,cap_dac_override=p"); + cap_dropped = cap_init(); + cap_umount = cap_from_text("cap_sys_admin,cap_dac_override=i"); + cap_raised = cap_from_text("cap_sys_admin,cap_dac_override=pe"); + if (!cap_lowered || !cap_dropped || !cap_umount || !cap_raised) { + perror("cap_init"); goto fail; } + + /* we start out running with cap_lowered */ + ret = cap_set_proc(cap_lowered); + uid = getuid(); if ((pwd = getpwuid(uid)) == NULL) { perror("getpwuid"); goto fail; @@ -451,29 +469,23 @@ int main(int argc, char *argv[]) { if (check_ownerships(uid, dev) != 0) { goto fail; } - /* We must maintain our real uid as the user who called this - * program in order to have access to their kernel keyring. - * Even though root has the power to mount, only a user with - * the correct key in their keyring can mount an ecryptfs - * directory correctly. - * Root does not necessarily have the user's key, so we need - * the real uid to be that of the user. - * And we need the effective uid to be root in order to mount. + /* + * set CAP_SYS_ADMIN in pE. */ - setreuid(-1, 0); + ret = cap_set_proc(cap_raised); + if (ret) { + perror("cap_set_proc"); + goto fail; + } /* Perform mount */ - if (mount(dev, mnt, FSTYPE, 0, opt) == 0) { - if (update_mtab(dev, mnt, opt) != 0) { - goto fail; - } - } else { + ret = mount(dev, mnt, FSTYPE, 0, opt); + if (ret != 0) perror("mount"); - /* Drop privileges since the mount did not succeed */ - if (setreuid(uid, uid) < 0) { - perror("setreuid"); - } + if (ret == 0) + ret = update_mtab(dev, mnt, opt); + cap_set_proc(cap_dropped); + if (ret != 0) goto fail; - } } else { /* Decrement counter, exiting if >0, and non-forced unmount */ if (force == 1) { @@ -486,12 +498,11 @@ int main(int argc, char *argv[]) { if (ecryptfs_private_is_mounted(dev, mnt, sig, mounting) == 0) { goto fail; } - /* The key is not needed for unmounting, so we set res=0. - * Perform umount by calling umount utility. This execl will - * update mtab for us, and replace the current process. - * Do not use the umount.ecryptfs helper (-i). - */ - setresuid(0,0,0); + ret = cap_set_proc(cap_umount); + if (ret) { + perror("cap_set_proc"); + goto fail; + } execl("/bin/umount", "umount", "-i", "-l", mnt, NULL); perror("execl unmount failed"); goto fail; @@ -500,6 +511,10 @@ success: unlock_counter(fh_counter); return 0; fail: + cap_free(cap_lowered); + cap_free(cap_raised); + cap_free(cap_dropped); + cap_free(cap_umount); unlock_counter(fh_counter); return 1; } -- 1.6.3.3