Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/ecryptfs/kthread.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* eCryptfs: Linux filesystem encryption layer
4
*
5
* Copyright (C) 2008 International Business Machines Corp.
6
* Author(s): Michael A. Halcrow <[email protected]>
7
*/
8
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"
15
16
struct ecryptfs_open_req {
17
struct file **lower_file;
18
struct path path;
19
struct completion done;
20
struct list_head kthread_ctl_list;
21
};
22
23
static struct ecryptfs_kthread_ctl {
24
#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
25
u32 flags;
26
struct mutex mux;
27
struct list_head req_list;
28
wait_queue_head_t wait;
29
} ecryptfs_kthread_ctl;
30
31
static struct task_struct *ecryptfs_kthread;
32
33
/**
34
* ecryptfs_threadfn
35
* @ignored: ignored
36
*
37
* The eCryptfs kernel thread that has the responsibility of getting
38
* the lower file with RW permissions.
39
*
40
* Returns zero on success; non-zero otherwise
41
*/
42
static int ecryptfs_threadfn(void *ignored)
43
{
44
set_freezable();
45
while (1) {
46
struct ecryptfs_open_req *req;
47
48
wait_event_freezable(
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);
55
goto out;
56
}
57
while (!list_empty(&ecryptfs_kthread_ctl.req_list)) {
58
req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
59
struct ecryptfs_open_req,
60
kthread_ctl_list);
61
list_del(&req->kthread_ctl_list);
62
*req->lower_file = dentry_open(&req->path,
63
(O_RDWR | O_LARGEFILE), current_cred());
64
complete(&req->done);
65
}
66
mutex_unlock(&ecryptfs_kthread_ctl.mux);
67
}
68
out:
69
return 0;
70
}
71
72
int __init ecryptfs_init_kthread(void)
73
{
74
int rc = 0;
75
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,
80
"ecryptfs-kthread");
81
if (IS_ERR(ecryptfs_kthread)) {
82
rc = PTR_ERR(ecryptfs_kthread);
83
printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]"
84
"\n", __func__, rc);
85
}
86
return rc;
87
}
88
89
void ecryptfs_destroy_kthread(void)
90
{
91
struct ecryptfs_open_req *req, *tmp;
92
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,
96
kthread_ctl_list) {
97
list_del(&req->kthread_ctl_list);
98
*req->lower_file = ERR_PTR(-EIO);
99
complete(&req->done);
100
}
101
mutex_unlock(&ecryptfs_kthread_ctl.mux);
102
kthread_stop(ecryptfs_kthread);
103
wake_up(&ecryptfs_kthread_ctl.wait);
104
}
105
106
/**
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
112
*
113
* This function gets a r/w file opened against the lower dentry.
114
*
115
* Returns zero on success; non-zero otherwise
116
*/
117
int ecryptfs_privileged_open(struct file **lower_file,
118
struct dentry *lower_dentry,
119
struct vfsmount *lower_mnt,
120
const struct cred *cred)
121
{
122
struct ecryptfs_open_req req;
123
int flags = O_LARGEFILE;
124
int rc = 0;
125
126
init_completion(&req.done);
127
req.lower_file = lower_file;
128
req.path.dentry = lower_dentry;
129
req.path.mnt = lower_mnt;
130
131
/* Corresponding dput() and mntput() are done when the
132
* lower file is fput() when all eCryptfs files for the inode are
133
* released. */
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))
137
goto out;
138
if ((flags & O_ACCMODE) == O_RDONLY) {
139
rc = PTR_ERR((*lower_file));
140
goto out;
141
}
142
mutex_lock(&ecryptfs_kthread_ctl.mux);
143
if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
144
rc = -EIO;
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",
148
__func__);
149
goto out;
150
}
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);
157
out:
158
return rc;
159
}
160
161