1a59d1b8e05ea (Thomas Gleixner 2019-05-27 08:55:05 +0200 1) // SPDX-License-Identifier: GPL-2.0-or-later
446b5836af9fc (Lee Jones 2021-03-30 17:44:49 +0100 2) /*
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 3) * eCryptfs: Linux filesystem encryption layer
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 4) *
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 5) * Copyright (C) 2008 International Business Machines Corp.
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 6) * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 7) */
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 8)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 9) #include <linux/kthread.h>
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 10) #include <linux/freezer.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 11) #include <linux/slab.h>
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 12) #include <linux/wait.h>
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 13) #include <linux/mount.h>
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 14) #include "ecryptfs_kernel.h"
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 15)
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 16) struct ecryptfs_open_req {
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 17) struct file **lower_file;
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 18) struct path path;
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 19) struct completion done;
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 20) struct list_head kthread_ctl_list;
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 21) };
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 22)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 23) static struct ecryptfs_kthread_ctl {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 24) #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 25) u32 flags;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 26) struct mutex mux;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 27) struct list_head req_list;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 28) wait_queue_head_t wait;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 29) } ecryptfs_kthread_ctl;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 30)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 31) static struct task_struct *ecryptfs_kthread;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 32)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 33) /**
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 34) * ecryptfs_threadfn
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 35) * @ignored: ignored
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 36) *
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 37) * The eCryptfs kernel thread that has the responsibility of getting
332ab16f830f5 (Tyler Hicks 2011-04-14 15:35:11 -0500 38) * the lower file with RW permissions.
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 39) *
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 40) * Returns zero on success; non-zero otherwise
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 41) */
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 42) static int ecryptfs_threadfn(void *ignored)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 43) {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 44) set_freezable();
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 45) while (1) {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 46) struct ecryptfs_open_req *req;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 47)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 48) wait_event_freezable(
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 49) ecryptfs_kthread_ctl.wait,
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 50) (!list_empty(&ecryptfs_kthread_ctl.req_list)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 51) || kthread_should_stop()));
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 52) mutex_lock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 53) if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 54) mutex_unlock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 55) goto out;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 56) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 57) while (!list_empty(&ecryptfs_kthread_ctl.req_list)) {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 58) req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 59) struct ecryptfs_open_req,
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 60) kthread_ctl_list);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 61) list_del(&req->kthread_ctl_list);
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 62) *req->lower_file = dentry_open(&req->path,
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 63) (O_RDWR | O_LARGEFILE), current_cred());
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 64) complete(&req->done);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 65) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 66) mutex_unlock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 67) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 68) out:
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 69) return 0;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 70) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 71)
7371a38201d04 (Jerome Marchand 2010-08-17 17:24:05 +0200 72) int __init ecryptfs_init_kthread(void)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 73) {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 74) int rc = 0;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 75)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 76) mutex_init(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 77) init_waitqueue_head(&ecryptfs_kthread_ctl.wait);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 78) INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 79) ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL,
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 80) "ecryptfs-kthread");
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 81) if (IS_ERR(ecryptfs_kthread)) {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 82) rc = PTR_ERR(ecryptfs_kthread);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 83) printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]"
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 84) "\n", __func__, rc);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 85) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 86) return rc;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 87) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 88)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 89) void ecryptfs_destroy_kthread(void)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 90) {
8bbca57cff7f1 (Wei Yongjun 2012-08-21 10:46:05 +0800 91) struct ecryptfs_open_req *req, *tmp;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 92)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 93) mutex_lock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 94) ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
8bbca57cff7f1 (Wei Yongjun 2012-08-21 10:46:05 +0800 95) list_for_each_entry_safe(req, tmp, &ecryptfs_kthread_ctl.req_list,
8bbca57cff7f1 (Wei Yongjun 2012-08-21 10:46:05 +0800 96) kthread_ctl_list) {
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 97) list_del(&req->kthread_ctl_list);
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 98) *req->lower_file = ERR_PTR(-EIO);
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 99) complete(&req->done);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 100) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 101) mutex_unlock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 102) kthread_stop(ecryptfs_kthread);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 103) wake_up(&ecryptfs_kthread_ctl.wait);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 104) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 105)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 106) /**
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 107) * ecryptfs_privileged_open
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 108) * @lower_file: Result of dentry_open by root on lower dentry
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 109) * @lower_dentry: Lower dentry for file to open
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 110) * @lower_mnt: Lower vfsmount for file to open
446b5836af9fc (Lee Jones 2021-03-30 17:44:49 +0100 111) * @cred: credential to use for this call
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 112) *
57366a8d0bf24 (Masahiro Yamada 2017-02-27 14:29:12 -0800 113) * This function gets a r/w file opened against the lower dentry.
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 114) *
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 115) * Returns zero on success; non-zero otherwise
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 116) */
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 117) int ecryptfs_privileged_open(struct file **lower_file,
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 118) struct dentry *lower_dentry,
745ca2475a6ac (David Howells 2008-11-14 10:39:22 +1100 119) struct vfsmount *lower_mnt,
745ca2475a6ac (David Howells 2008-11-14 10:39:22 +1100 120) const struct cred *cred)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 121) {
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 122) struct ecryptfs_open_req req;
ac22ba23b659e (Tyler Hicks 2009-08-12 01:06:54 -0500 123) int flags = O_LARGEFILE;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 124) int rc = 0;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 125)
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 126) init_completion(&req.done);
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 127) req.lower_file = lower_file;
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 128) req.path.dentry = lower_dentry;
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 129) req.path.mnt = lower_mnt;
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 130)
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 131) /* Corresponding dput() and mntput() are done when the
332ab16f830f5 (Tyler Hicks 2011-04-14 15:35:11 -0500 132) * lower file is fput() when all eCryptfs files for the inode are
332ab16f830f5 (Tyler Hicks 2011-04-14 15:35:11 -0500 133) * released. */
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 134) flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR;
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 135) (*lower_file) = dentry_open(&req.path, flags, cred);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 136) if (!IS_ERR(*lower_file))
78c4e172412de (Jeff Mahoney 2016-07-05 17:32:29 -0400 137) goto out;
9fe79d7600497 (Tyler Hicks 2012-06-12 11:17:01 -0700 138) if ((flags & O_ACCMODE) == O_RDONLY) {
ac22ba23b659e (Tyler Hicks 2009-08-12 01:06:54 -0500 139) rc = PTR_ERR((*lower_file));
ac22ba23b659e (Tyler Hicks 2009-08-12 01:06:54 -0500 140) goto out;
ac22ba23b659e (Tyler Hicks 2009-08-12 01:06:54 -0500 141) }
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 142) mutex_lock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 143) if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 144) rc = -EIO;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 145) mutex_unlock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 146) printk(KERN_ERR "%s: We are in the middle of shutting down; "
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 147) "aborting privileged request to open lower file\n",
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 148) __func__);
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 149) goto out;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 150) }
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 151) list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 152) mutex_unlock(&ecryptfs_kthread_ctl.mux);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 153) wake_up(&ecryptfs_kthread_ctl.wait);
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 154) wait_for_completion(&req.done);
78c4e172412de (Jeff Mahoney 2016-07-05 17:32:29 -0400 155) if (IS_ERR(*lower_file))
3b8b487114c95 (Al Viro 2012-06-25 11:38:56 +0400 156) rc = PTR_ERR(*lower_file);
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 157) out:
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 158) return rc;
746f1e558bc52 (Michael Halcrow 2008-07-23 21:30:02 -0700 159) }