1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * eCryptfs: Linux filesystem encryption layer
5 * Copyright (C) 2008 International Business Machines Corp.
6 * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
9 #include <linux/kthread.h>
10 #include <linux/freezer.h>
11 #include <linux/slab.h>
12 #include <linux/wait.h>
13 #include <linux/mount.h>
14 #include "ecryptfs_kernel.h"
16 struct ecryptfs_open_req
{
17 struct file
**lower_file
;
19 struct completion done
;
20 struct list_head kthread_ctl_list
;
23 static struct ecryptfs_kthread_ctl
{
24 #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
27 struct list_head req_list
;
28 wait_queue_head_t wait
;
29 } ecryptfs_kthread_ctl
;
31 static struct task_struct
*ecryptfs_kthread
;
37 * The eCryptfs kernel thread that has the responsibility of getting
38 * the lower file with RW permissions.
40 * Returns zero on success; non-zero otherwise
42 static int ecryptfs_threadfn(void *ignored
)
46 struct ecryptfs_open_req
*req
;
49 ecryptfs_kthread_ctl
.wait
,
50 (!list_empty(&ecryptfs_kthread_ctl
.req_list
)
51 || kthread_should_stop()));
52 mutex_lock(&ecryptfs_kthread_ctl
.mux
);
53 if (ecryptfs_kthread_ctl
.flags
& ECRYPTFS_KTHREAD_ZOMBIE
) {
54 mutex_unlock(&ecryptfs_kthread_ctl
.mux
);
57 while (!list_empty(&ecryptfs_kthread_ctl
.req_list
)) {
58 req
= list_first_entry(&ecryptfs_kthread_ctl
.req_list
,
59 struct ecryptfs_open_req
,
61 list_del(&req
->kthread_ctl_list
);
62 *req
->lower_file
= dentry_open(&req
->path
,
63 (O_RDWR
| O_LARGEFILE
), current_cred());
66 mutex_unlock(&ecryptfs_kthread_ctl
.mux
);
72 int __init
ecryptfs_init_kthread(void)
76 mutex_init(&ecryptfs_kthread_ctl
.mux
);
77 init_waitqueue_head(&ecryptfs_kthread_ctl
.wait
);
78 INIT_LIST_HEAD(&ecryptfs_kthread_ctl
.req_list
);
79 ecryptfs_kthread
= kthread_run(&ecryptfs_threadfn
, NULL
,
81 if (IS_ERR(ecryptfs_kthread
)) {
82 rc
= PTR_ERR(ecryptfs_kthread
);
83 printk(KERN_ERR
"%s: Failed to create kernel thread; rc = [%d]"
89 void ecryptfs_destroy_kthread(void)
91 struct ecryptfs_open_req
*req
, *tmp
;
93 mutex_lock(&ecryptfs_kthread_ctl
.mux
);
94 ecryptfs_kthread_ctl
.flags
|= ECRYPTFS_KTHREAD_ZOMBIE
;
95 list_for_each_entry_safe(req
, tmp
, &ecryptfs_kthread_ctl
.req_list
,
97 list_del(&req
->kthread_ctl_list
);
98 *req
->lower_file
= ERR_PTR(-EIO
);
101 mutex_unlock(&ecryptfs_kthread_ctl
.mux
);
102 kthread_stop(ecryptfs_kthread
);
103 wake_up(&ecryptfs_kthread_ctl
.wait
);
107 * ecryptfs_privileged_open
108 * @lower_file: Result of dentry_open by root on lower dentry
109 * @lower_dentry: Lower dentry for file to open
110 * @lower_mnt: Lower vfsmount for file to open
111 * @cred: credential to use for this call
113 * This function gets a r/w file opened against the lower dentry.
115 * Returns zero on success; non-zero otherwise
117 int ecryptfs_privileged_open(struct file
**lower_file
,
118 struct dentry
*lower_dentry
,
119 struct vfsmount
*lower_mnt
,
120 const struct cred
*cred
)
122 struct ecryptfs_open_req req
;
123 int flags
= O_LARGEFILE
;
126 init_completion(&req
.done
);
127 req
.lower_file
= lower_file
;
128 req
.path
.dentry
= lower_dentry
;
129 req
.path
.mnt
= lower_mnt
;
131 /* Corresponding dput() and mntput() are done when the
132 * lower file is fput() when all eCryptfs files for the inode are
134 flags
|= IS_RDONLY(d_inode(lower_dentry
)) ? O_RDONLY
: O_RDWR
;
135 (*lower_file
) = dentry_open(&req
.path
, flags
, cred
);
136 if (!IS_ERR(*lower_file
))
138 if ((flags
& O_ACCMODE
) == O_RDONLY
) {
139 rc
= PTR_ERR((*lower_file
));
142 mutex_lock(&ecryptfs_kthread_ctl
.mux
);
143 if (ecryptfs_kthread_ctl
.flags
& ECRYPTFS_KTHREAD_ZOMBIE
) {
145 mutex_unlock(&ecryptfs_kthread_ctl
.mux
);
146 printk(KERN_ERR
"%s: We are in the middle of shutting down; "
147 "aborting privileged request to open lower file\n",
151 list_add_tail(&req
.kthread_ctl_list
, &ecryptfs_kthread_ctl
.req_list
);
152 mutex_unlock(&ecryptfs_kthread_ctl
.mux
);
153 wake_up(&ecryptfs_kthread_ctl
.wait
);
154 wait_for_completion(&req
.done
);
155 if (IS_ERR(*lower_file
))
156 rc
= PTR_ERR(*lower_file
);