diff options
author | Tyler Hicks <tyhicks@canonical.com> | 2012-06-11 12:47:47 -0400 |
---|---|---|
committer | Tyler Hicks <tyhicks@canonical.com> | 2012-07-08 13:51:44 -0400 |
commit | 2ecaf55db6dcf4dd25e1ef8d5eb6068e3286a20f (patch) | |
tree | daa89105f89d64579d5ee04a376e4e31543871cf /fs | |
parent | 566968866555a19d0a78e0bfa845cd249a7eeae2 (diff) |
eCryptfs: Make all miscdev functions use daemon ptr in file private_data
Now that a pointer to a valid struct ecryptfs_daemon is stored in the
private_data of an opened /dev/ecryptfs file, the remaining miscdev
functions can utilize the pointer rather than looking up the
ecryptfs_daemon at the beginning of each operation.
The security model of /dev/ecryptfs is simplified a little bit with this
patch. Upon opening /dev/ecryptfs, a per-user ecryptfs_daemon is
registered. Another daemon cannot be registered for that user until the
last file reference is released. During the lifetime of the
ecryptfs_daemon, access checks are not performed on the /dev/ecryptfs
operations because it is assumed that the application securely handles
the opened file descriptor and does not unintentionally leak it to
processes that are not trusted.
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Cc: Sasha Levin <levinsasha928@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 16 | ||||
-rw-r--r-- | fs/ecryptfs/messaging.c | 105 | ||||
-rw-r--r-- | fs/ecryptfs/miscdev.c | 98 |
3 files changed, 47 insertions, 172 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 01a1f8575950..0deb4f24957a 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -392,10 +392,7 @@ struct ecryptfs_daemon { | |||
392 | #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 | 392 | #define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008 |
393 | u32 flags; | 393 | u32 flags; |
394 | u32 num_queued_msg_ctx; | 394 | u32 num_queued_msg_ctx; |
395 | struct pid *pid; | 395 | struct file *file; |
396 | uid_t euid; | ||
397 | struct user_namespace *user_ns; | ||
398 | struct task_struct *task; | ||
399 | struct mutex mux; | 396 | struct mutex mux; |
400 | struct list_head msg_ctx_out_queue; | 397 | struct list_head msg_ctx_out_queue; |
401 | wait_queue_head_t wait; | 398 | wait_queue_head_t wait; |
@@ -619,9 +616,8 @@ int | |||
619 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 616 | ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
620 | size_t size, int flags); | 617 | size_t size, int flags); |
621 | int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); | 618 | int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); |
622 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | 619 | int ecryptfs_process_response(struct ecryptfs_daemon *daemon, |
623 | struct user_namespace *user_ns, struct pid *pid, | 620 | struct ecryptfs_message *msg, u32 seq); |
624 | u32 seq); | ||
625 | int ecryptfs_send_message(char *data, int data_len, | 621 | int ecryptfs_send_message(char *data, int data_len, |
626 | struct ecryptfs_msg_ctx **msg_ctx); | 622 | struct ecryptfs_msg_ctx **msg_ctx); |
627 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, | 623 | int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, |
@@ -666,8 +662,7 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, | |||
666 | struct inode *ecryptfs_inode); | 662 | struct inode *ecryptfs_inode); |
667 | struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); | 663 | struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index); |
668 | int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); | 664 | int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon); |
669 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, | 665 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon); |
670 | struct user_namespace *user_ns); | ||
671 | int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, | 666 | int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, |
672 | size_t *length_size); | 667 | size_t *length_size); |
673 | int ecryptfs_write_packet_length(char *dest, size_t size, | 668 | int ecryptfs_write_packet_length(char *dest, size_t size, |
@@ -679,8 +674,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, | |||
679 | u16 msg_flags, struct ecryptfs_daemon *daemon); | 674 | u16 msg_flags, struct ecryptfs_daemon *daemon); |
680 | void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); | 675 | void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx); |
681 | int | 676 | int |
682 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | 677 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file); |
683 | struct user_namespace *user_ns, struct pid *pid); | ||
684 | int ecryptfs_init_kthread(void); | 678 | int ecryptfs_init_kthread(void); |
685 | void ecryptfs_destroy_kthread(void); | 679 | void ecryptfs_destroy_kthread(void); |
686 | int ecryptfs_privileged_open(struct file **lower_file, | 680 | int ecryptfs_privileged_open(struct file **lower_file, |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index c11911decdc1..b29bb8bfa8d9 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -32,8 +32,8 @@ static struct mutex ecryptfs_msg_ctx_lists_mux; | |||
32 | static struct hlist_head *ecryptfs_daemon_hash; | 32 | static struct hlist_head *ecryptfs_daemon_hash; |
33 | struct mutex ecryptfs_daemon_hash_mux; | 33 | struct mutex ecryptfs_daemon_hash_mux; |
34 | static int ecryptfs_hash_bits; | 34 | static int ecryptfs_hash_bits; |
35 | #define ecryptfs_uid_hash(uid) \ | 35 | #define ecryptfs_current_euid_hash(uid) \ |
36 | hash_long((unsigned long)uid, ecryptfs_hash_bits) | 36 | hash_long((unsigned long)current_euid(), ecryptfs_hash_bits) |
37 | 37 | ||
38 | static u32 ecryptfs_msg_counter; | 38 | static u32 ecryptfs_msg_counter; |
39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | 39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; |
@@ -105,26 +105,24 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) | |||
105 | 105 | ||
106 | /** | 106 | /** |
107 | * ecryptfs_find_daemon_by_euid | 107 | * ecryptfs_find_daemon_by_euid |
108 | * @euid: The effective user id which maps to the desired daemon id | ||
109 | * @user_ns: The namespace in which @euid applies | ||
110 | * @daemon: If return value is zero, points to the desired daemon pointer | 108 | * @daemon: If return value is zero, points to the desired daemon pointer |
111 | * | 109 | * |
112 | * Must be called with ecryptfs_daemon_hash_mux held. | 110 | * Must be called with ecryptfs_daemon_hash_mux held. |
113 | * | 111 | * |
114 | * Search the hash list for the given user id. | 112 | * Search the hash list for the current effective user id. |
115 | * | 113 | * |
116 | * Returns zero if the user id exists in the list; non-zero otherwise. | 114 | * Returns zero if the user id exists in the list; non-zero otherwise. |
117 | */ | 115 | */ |
118 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, | 116 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon) |
119 | struct user_namespace *user_ns) | ||
120 | { | 117 | { |
121 | struct hlist_node *elem; | 118 | struct hlist_node *elem; |
122 | int rc; | 119 | int rc; |
123 | 120 | ||
124 | hlist_for_each_entry(*daemon, elem, | 121 | hlist_for_each_entry(*daemon, elem, |
125 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)], | 122 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()], |
126 | euid_chain) { | 123 | euid_chain) { |
127 | if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) { | 124 | if ((*daemon)->file->f_cred->euid == current_euid() && |
125 | (*daemon)->file->f_cred->user_ns == current_user_ns()) { | ||
128 | rc = 0; | 126 | rc = 0; |
129 | goto out; | 127 | goto out; |
130 | } | 128 | } |
@@ -137,9 +135,7 @@ out: | |||
137 | /** | 135 | /** |
138 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct | 136 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct |
139 | * @daemon: Pointer to set to newly allocated daemon struct | 137 | * @daemon: Pointer to set to newly allocated daemon struct |
140 | * @euid: Effective user id for the daemon | 138 | * @file: File used when opening /dev/ecryptfs |
141 | * @user_ns: The namespace in which @euid applies | ||
142 | * @pid: Process id for the daemon | ||
143 | * | 139 | * |
144 | * Must be called ceremoniously while in possession of | 140 | * Must be called ceremoniously while in possession of |
145 | * ecryptfs_sacred_daemon_hash_mux | 141 | * ecryptfs_sacred_daemon_hash_mux |
@@ -147,8 +143,7 @@ out: | |||
147 | * Returns zero on success; non-zero otherwise | 143 | * Returns zero on success; non-zero otherwise |
148 | */ | 144 | */ |
149 | int | 145 | int |
150 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | 146 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file) |
151 | struct user_namespace *user_ns, struct pid *pid) | ||
152 | { | 147 | { |
153 | int rc = 0; | 148 | int rc = 0; |
154 | 149 | ||
@@ -159,16 +154,13 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, | |||
159 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); | 154 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); |
160 | goto out; | 155 | goto out; |
161 | } | 156 | } |
162 | (*daemon)->euid = euid; | 157 | (*daemon)->file = file; |
163 | (*daemon)->user_ns = get_user_ns(user_ns); | ||
164 | (*daemon)->pid = get_pid(pid); | ||
165 | (*daemon)->task = current; | ||
166 | mutex_init(&(*daemon)->mux); | 158 | mutex_init(&(*daemon)->mux); |
167 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); | 159 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); |
168 | init_waitqueue_head(&(*daemon)->wait); | 160 | init_waitqueue_head(&(*daemon)->wait); |
169 | (*daemon)->num_queued_msg_ctx = 0; | 161 | (*daemon)->num_queued_msg_ctx = 0; |
170 | hlist_add_head(&(*daemon)->euid_chain, | 162 | hlist_add_head(&(*daemon)->euid_chain, |
171 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]); | 163 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()]); |
172 | out: | 164 | out: |
173 | return rc; | 165 | return rc; |
174 | } | 166 | } |
@@ -188,9 +180,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
188 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) | 180 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) |
189 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { | 181 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { |
190 | rc = -EBUSY; | 182 | rc = -EBUSY; |
191 | printk(KERN_WARNING "%s: Attempt to destroy daemon with pid " | ||
192 | "[0x%p], but it is in the midst of a read or a poll\n", | ||
193 | __func__, daemon->pid); | ||
194 | mutex_unlock(&daemon->mux); | 183 | mutex_unlock(&daemon->mux); |
195 | goto out; | 184 | goto out; |
196 | } | 185 | } |
@@ -203,12 +192,6 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
203 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); | 192 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); |
204 | } | 193 | } |
205 | hlist_del(&daemon->euid_chain); | 194 | hlist_del(&daemon->euid_chain); |
206 | if (daemon->task) | ||
207 | wake_up_process(daemon->task); | ||
208 | if (daemon->pid) | ||
209 | put_pid(daemon->pid); | ||
210 | if (daemon->user_ns) | ||
211 | put_user_ns(daemon->user_ns); | ||
212 | mutex_unlock(&daemon->mux); | 195 | mutex_unlock(&daemon->mux); |
213 | kzfree(daemon); | 196 | kzfree(daemon); |
214 | out: | 197 | out: |
@@ -219,8 +202,6 @@ out: | |||
219 | * ecryptfs_process_reponse | 202 | * ecryptfs_process_reponse |
220 | * @msg: The ecryptfs message received; the caller should sanity check | 203 | * @msg: The ecryptfs message received; the caller should sanity check |
221 | * msg->data_len and free the memory | 204 | * msg->data_len and free the memory |
222 | * @pid: The process ID of the userspace application that sent the | ||
223 | * message | ||
224 | * @seq: The sequence number of the message; must match the sequence | 205 | * @seq: The sequence number of the message; must match the sequence |
225 | * number for the existing message context waiting for this | 206 | * number for the existing message context waiting for this |
226 | * response | 207 | * response |
@@ -239,16 +220,11 @@ out: | |||
239 | * | 220 | * |
240 | * Returns zero on success; non-zero otherwise | 221 | * Returns zero on success; non-zero otherwise |
241 | */ | 222 | */ |
242 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | 223 | int ecryptfs_process_response(struct ecryptfs_daemon *daemon, |
243 | struct user_namespace *user_ns, struct pid *pid, | 224 | struct ecryptfs_message *msg, u32 seq) |
244 | u32 seq) | ||
245 | { | 225 | { |
246 | struct ecryptfs_daemon *uninitialized_var(daemon); | ||
247 | struct ecryptfs_msg_ctx *msg_ctx; | 226 | struct ecryptfs_msg_ctx *msg_ctx; |
248 | size_t msg_size; | 227 | size_t msg_size; |
249 | struct nsproxy *nsproxy; | ||
250 | struct user_namespace *tsk_user_ns; | ||
251 | uid_t ctx_euid; | ||
252 | int rc; | 228 | int rc; |
253 | 229 | ||
254 | if (msg->index >= ecryptfs_message_buf_len) { | 230 | if (msg->index >= ecryptfs_message_buf_len) { |
@@ -261,51 +237,6 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | |||
261 | } | 237 | } |
262 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; | 238 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; |
263 | mutex_lock(&msg_ctx->mux); | 239 | mutex_lock(&msg_ctx->mux); |
264 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
265 | rcu_read_lock(); | ||
266 | nsproxy = task_nsproxy(msg_ctx->task); | ||
267 | if (nsproxy == NULL) { | ||
268 | rc = -EBADMSG; | ||
269 | printk(KERN_ERR "%s: Receiving process is a zombie. Dropping " | ||
270 | "message.\n", __func__); | ||
271 | rcu_read_unlock(); | ||
272 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
273 | goto wake_up; | ||
274 | } | ||
275 | tsk_user_ns = __task_cred(msg_ctx->task)->user_ns; | ||
276 | ctx_euid = task_euid(msg_ctx->task); | ||
277 | rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); | ||
278 | rcu_read_unlock(); | ||
279 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
280 | if (rc) { | ||
281 | rc = -EBADMSG; | ||
282 | printk(KERN_WARNING "%s: User [%d] received a " | ||
283 | "message response from process [0x%p] but does " | ||
284 | "not have a registered daemon\n", __func__, | ||
285 | ctx_euid, pid); | ||
286 | goto wake_up; | ||
287 | } | ||
288 | if (ctx_euid != euid) { | ||
289 | rc = -EBADMSG; | ||
290 | printk(KERN_WARNING "%s: Received message from user " | ||
291 | "[%d]; expected message from user [%d]\n", __func__, | ||
292 | euid, ctx_euid); | ||
293 | goto unlock; | ||
294 | } | ||
295 | if (tsk_user_ns != user_ns) { | ||
296 | rc = -EBADMSG; | ||
297 | printk(KERN_WARNING "%s: Received message from user_ns " | ||
298 | "[0x%p]; expected message from user_ns [0x%p]\n", | ||
299 | __func__, user_ns, tsk_user_ns); | ||
300 | goto unlock; | ||
301 | } | ||
302 | if (daemon->pid != pid) { | ||
303 | rc = -EBADMSG; | ||
304 | printk(KERN_ERR "%s: User [%d] sent a message response " | ||
305 | "from an unrecognized process [0x%p]\n", | ||
306 | __func__, ctx_euid, pid); | ||
307 | goto unlock; | ||
308 | } | ||
309 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { | 240 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { |
310 | rc = -EINVAL; | 241 | rc = -EINVAL; |
311 | printk(KERN_WARNING "%s: Desired context element is not " | 242 | printk(KERN_WARNING "%s: Desired context element is not " |
@@ -328,9 +259,8 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, | |||
328 | } | 259 | } |
329 | memcpy(msg_ctx->msg, msg, msg_size); | 260 | memcpy(msg_ctx->msg, msg, msg_size); |
330 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; | 261 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; |
331 | rc = 0; | ||
332 | wake_up: | ||
333 | wake_up_process(msg_ctx->task); | 262 | wake_up_process(msg_ctx->task); |
263 | rc = 0; | ||
334 | unlock: | 264 | unlock: |
335 | mutex_unlock(&msg_ctx->mux); | 265 | mutex_unlock(&msg_ctx->mux); |
336 | out: | 266 | out: |
@@ -352,14 +282,11 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type, | |||
352 | struct ecryptfs_msg_ctx **msg_ctx) | 282 | struct ecryptfs_msg_ctx **msg_ctx) |
353 | { | 283 | { |
354 | struct ecryptfs_daemon *daemon; | 284 | struct ecryptfs_daemon *daemon; |
355 | uid_t euid = current_euid(); | ||
356 | int rc; | 285 | int rc; |
357 | 286 | ||
358 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | 287 | rc = ecryptfs_find_daemon_by_euid(&daemon); |
359 | if (rc || !daemon) { | 288 | if (rc || !daemon) { |
360 | rc = -ENOTCONN; | 289 | rc = -ENOTCONN; |
361 | printk(KERN_ERR "%s: User [%d] does not have a daemon " | ||
362 | "registered\n", __func__, euid); | ||
363 | goto out; | 290 | goto out; |
364 | } | 291 | } |
365 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | 292 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); |
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index c0038f6566d4..412e6eda25f8 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c | |||
@@ -33,7 +33,7 @@ static atomic_t ecryptfs_num_miscdev_opens; | |||
33 | 33 | ||
34 | /** | 34 | /** |
35 | * ecryptfs_miscdev_poll | 35 | * ecryptfs_miscdev_poll |
36 | * @file: dev file (ignored) | 36 | * @file: dev file |
37 | * @pt: dev poll table (ignored) | 37 | * @pt: dev poll table (ignored) |
38 | * | 38 | * |
39 | * Returns the poll mask | 39 | * Returns the poll mask |
@@ -41,20 +41,10 @@ static atomic_t ecryptfs_num_miscdev_opens; | |||
41 | static unsigned int | 41 | static unsigned int |
42 | ecryptfs_miscdev_poll(struct file *file, poll_table *pt) | 42 | ecryptfs_miscdev_poll(struct file *file, poll_table *pt) |
43 | { | 43 | { |
44 | struct ecryptfs_daemon *daemon; | 44 | struct ecryptfs_daemon *daemon = file->private_data; |
45 | unsigned int mask = 0; | 45 | unsigned int mask = 0; |
46 | uid_t euid = current_euid(); | ||
47 | int rc; | ||
48 | 46 | ||
49 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
50 | /* TODO: Just use file->private_data? */ | ||
51 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
52 | if (rc || !daemon) { | ||
53 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
54 | return -EINVAL; | ||
55 | } | ||
56 | mutex_lock(&daemon->mux); | 47 | mutex_lock(&daemon->mux); |
57 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
58 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { | 48 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { |
59 | printk(KERN_WARNING "%s: Attempt to poll on zombified " | 49 | printk(KERN_WARNING "%s: Attempt to poll on zombified " |
60 | "daemon\n", __func__); | 50 | "daemon\n", __func__); |
@@ -79,7 +69,7 @@ out_unlock_daemon: | |||
79 | /** | 69 | /** |
80 | * ecryptfs_miscdev_open | 70 | * ecryptfs_miscdev_open |
81 | * @inode: inode of miscdev handle (ignored) | 71 | * @inode: inode of miscdev handle (ignored) |
82 | * @file: file for miscdev handle (ignored) | 72 | * @file: file for miscdev handle |
83 | * | 73 | * |
84 | * Returns zero on success; non-zero otherwise | 74 | * Returns zero on success; non-zero otherwise |
85 | */ | 75 | */ |
@@ -87,7 +77,6 @@ static int | |||
87 | ecryptfs_miscdev_open(struct inode *inode, struct file *file) | 77 | ecryptfs_miscdev_open(struct inode *inode, struct file *file) |
88 | { | 78 | { |
89 | struct ecryptfs_daemon *daemon = NULL; | 79 | struct ecryptfs_daemon *daemon = NULL; |
90 | uid_t euid = current_euid(); | ||
91 | int rc; | 80 | int rc; |
92 | 81 | ||
93 | mutex_lock(&ecryptfs_daemon_hash_mux); | 82 | mutex_lock(&ecryptfs_daemon_hash_mux); |
@@ -98,30 +87,20 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) | |||
98 | "count; rc = [%d]\n", __func__, rc); | 87 | "count; rc = [%d]\n", __func__, rc); |
99 | goto out_unlock_daemon_list; | 88 | goto out_unlock_daemon_list; |
100 | } | 89 | } |
101 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | 90 | rc = ecryptfs_find_daemon_by_euid(&daemon); |
102 | if (rc || !daemon) { | 91 | if (!rc) { |
103 | rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(), | ||
104 | task_pid(current)); | ||
105 | if (rc) { | ||
106 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " | ||
107 | "rc = [%d]\n", __func__, rc); | ||
108 | goto out_module_put_unlock_daemon_list; | ||
109 | } | ||
110 | } | ||
111 | mutex_lock(&daemon->mux); | ||
112 | if (daemon->pid != task_pid(current)) { | ||
113 | rc = -EINVAL; | 92 | rc = -EINVAL; |
114 | printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " | 93 | goto out_unlock_daemon_list; |
115 | "but pid [0x%p] has attempted to open the handle " | 94 | } |
116 | "instead\n", __func__, daemon->pid, daemon->euid, | 95 | rc = ecryptfs_spawn_daemon(&daemon, file); |
117 | task_pid(current)); | 96 | if (rc) { |
118 | goto out_unlock_daemon; | 97 | printk(KERN_ERR "%s: Error attempting to spawn daemon; " |
98 | "rc = [%d]\n", __func__, rc); | ||
99 | goto out_module_put_unlock_daemon_list; | ||
119 | } | 100 | } |
101 | mutex_lock(&daemon->mux); | ||
120 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { | 102 | if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) { |
121 | rc = -EBUSY; | 103 | rc = -EBUSY; |
122 | printk(KERN_ERR "%s: Miscellaneous device handle may only be " | ||
123 | "opened once per daemon; pid [0x%p] already has this " | ||
124 | "handle open\n", __func__, daemon->pid); | ||
125 | goto out_unlock_daemon; | 104 | goto out_unlock_daemon; |
126 | } | 105 | } |
127 | daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; | 106 | daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; |
@@ -140,7 +119,7 @@ out_unlock_daemon_list: | |||
140 | /** | 119 | /** |
141 | * ecryptfs_miscdev_release | 120 | * ecryptfs_miscdev_release |
142 | * @inode: inode of fs/ecryptfs/euid handle (ignored) | 121 | * @inode: inode of fs/ecryptfs/euid handle (ignored) |
143 | * @file: file for fs/ecryptfs/euid handle (ignored) | 122 | * @file: file for fs/ecryptfs/euid handle |
144 | * | 123 | * |
145 | * This keeps the daemon registered until the daemon sends another | 124 | * This keeps the daemon registered until the daemon sends another |
146 | * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. | 125 | * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. |
@@ -150,20 +129,18 @@ out_unlock_daemon_list: | |||
150 | static int | 129 | static int |
151 | ecryptfs_miscdev_release(struct inode *inode, struct file *file) | 130 | ecryptfs_miscdev_release(struct inode *inode, struct file *file) |
152 | { | 131 | { |
153 | struct ecryptfs_daemon *daemon = NULL; | 132 | struct ecryptfs_daemon *daemon = file->private_data; |
154 | uid_t euid = current_euid(); | ||
155 | int rc; | 133 | int rc; |
156 | 134 | ||
157 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
158 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
159 | if (rc || !daemon) | ||
160 | daemon = file->private_data; | ||
161 | mutex_lock(&daemon->mux); | 135 | mutex_lock(&daemon->mux); |
162 | BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); | 136 | BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); |
163 | daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; | 137 | daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; |
164 | atomic_dec(&ecryptfs_num_miscdev_opens); | 138 | atomic_dec(&ecryptfs_num_miscdev_opens); |
165 | mutex_unlock(&daemon->mux); | 139 | mutex_unlock(&daemon->mux); |
140 | |||
141 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
166 | rc = ecryptfs_exorcise_daemon(daemon); | 142 | rc = ecryptfs_exorcise_daemon(daemon); |
143 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
167 | if (rc) { | 144 | if (rc) { |
168 | printk(KERN_CRIT "%s: Fatal error whilst attempting to " | 145 | printk(KERN_CRIT "%s: Fatal error whilst attempting to " |
169 | "shut down daemon; rc = [%d]. Please report this " | 146 | "shut down daemon; rc = [%d]. Please report this " |
@@ -171,7 +148,6 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file) | |||
171 | BUG(); | 148 | BUG(); |
172 | } | 149 | } |
173 | module_put(THIS_MODULE); | 150 | module_put(THIS_MODULE); |
174 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
175 | return rc; | 151 | return rc; |
176 | } | 152 | } |
177 | 153 | ||
@@ -248,7 +224,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, | |||
248 | 224 | ||
249 | /** | 225 | /** |
250 | * ecryptfs_miscdev_read - format and send message from queue | 226 | * ecryptfs_miscdev_read - format and send message from queue |
251 | * @file: fs/ecryptfs/euid miscdevfs handle (ignored) | 227 | * @file: miscdevfs handle |
252 | * @buf: User buffer into which to copy the next message on the daemon queue | 228 | * @buf: User buffer into which to copy the next message on the daemon queue |
253 | * @count: Amount of space available in @buf | 229 | * @count: Amount of space available in @buf |
254 | * @ppos: Offset in file (ignored) | 230 | * @ppos: Offset in file (ignored) |
@@ -262,43 +238,27 @@ static ssize_t | |||
262 | ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, | 238 | ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, |
263 | loff_t *ppos) | 239 | loff_t *ppos) |
264 | { | 240 | { |
265 | struct ecryptfs_daemon *daemon; | 241 | struct ecryptfs_daemon *daemon = file->private_data; |
266 | struct ecryptfs_msg_ctx *msg_ctx; | 242 | struct ecryptfs_msg_ctx *msg_ctx; |
267 | size_t packet_length_size; | 243 | size_t packet_length_size; |
268 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; | 244 | char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
269 | size_t i; | 245 | size_t i; |
270 | size_t total_length; | 246 | size_t total_length; |
271 | uid_t euid = current_euid(); | ||
272 | int rc; | 247 | int rc; |
273 | 248 | ||
274 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
275 | /* TODO: Just use file->private_data? */ | ||
276 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); | ||
277 | if (rc || !daemon) { | ||
278 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | mutex_lock(&daemon->mux); | 249 | mutex_lock(&daemon->mux); |
282 | if (task_pid(current) != daemon->pid) { | ||
283 | mutex_unlock(&daemon->mux); | ||
284 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
285 | return -EPERM; | ||
286 | } | ||
287 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { | 250 | if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { |
288 | rc = 0; | 251 | rc = 0; |
289 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
290 | printk(KERN_WARNING "%s: Attempt to read from zombified " | 252 | printk(KERN_WARNING "%s: Attempt to read from zombified " |
291 | "daemon\n", __func__); | 253 | "daemon\n", __func__); |
292 | goto out_unlock_daemon; | 254 | goto out_unlock_daemon; |
293 | } | 255 | } |
294 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { | 256 | if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { |
295 | rc = 0; | 257 | rc = 0; |
296 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
297 | goto out_unlock_daemon; | 258 | goto out_unlock_daemon; |
298 | } | 259 | } |
299 | /* This daemon will not go away so long as this flag is set */ | 260 | /* This daemon will not go away so long as this flag is set */ |
300 | daemon->flags |= ECRYPTFS_DAEMON_IN_READ; | 261 | daemon->flags |= ECRYPTFS_DAEMON_IN_READ; |
301 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
302 | check_list: | 262 | check_list: |
303 | if (list_empty(&daemon->msg_ctx_out_queue)) { | 263 | if (list_empty(&daemon->msg_ctx_out_queue)) { |
304 | mutex_unlock(&daemon->mux); | 264 | mutex_unlock(&daemon->mux); |
@@ -382,16 +342,12 @@ out_unlock_daemon: | |||
382 | * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon | 342 | * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon |
383 | * @data: Bytes comprising struct ecryptfs_message | 343 | * @data: Bytes comprising struct ecryptfs_message |
384 | * @data_size: sizeof(struct ecryptfs_message) + data len | 344 | * @data_size: sizeof(struct ecryptfs_message) + data len |
385 | * @euid: Effective user id of miscdevess sending the miscdev response | ||
386 | * @user_ns: The namespace in which @euid applies | ||
387 | * @pid: Miscdevess id of miscdevess sending the miscdev response | ||
388 | * @seq: Sequence number for miscdev response packet | 345 | * @seq: Sequence number for miscdev response packet |
389 | * | 346 | * |
390 | * Returns zero on success; non-zero otherwise | 347 | * Returns zero on success; non-zero otherwise |
391 | */ | 348 | */ |
392 | static int ecryptfs_miscdev_response(char *data, size_t data_size, | 349 | static int ecryptfs_miscdev_response(struct ecryptfs_daemon *daemon, char *data, |
393 | uid_t euid, struct user_namespace *user_ns, | 350 | size_t data_size, u32 seq) |
394 | struct pid *pid, u32 seq) | ||
395 | { | 351 | { |
396 | struct ecryptfs_message *msg = (struct ecryptfs_message *)data; | 352 | struct ecryptfs_message *msg = (struct ecryptfs_message *)data; |
397 | int rc; | 353 | int rc; |
@@ -403,7 +359,7 @@ static int ecryptfs_miscdev_response(char *data, size_t data_size, | |||
403 | rc = -EINVAL; | 359 | rc = -EINVAL; |
404 | goto out; | 360 | goto out; |
405 | } | 361 | } |
406 | rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq); | 362 | rc = ecryptfs_process_response(daemon, msg, seq); |
407 | if (rc) | 363 | if (rc) |
408 | printk(KERN_ERR | 364 | printk(KERN_ERR |
409 | "Error processing response message; rc = [%d]\n", rc); | 365 | "Error processing response message; rc = [%d]\n", rc); |
@@ -413,7 +369,7 @@ out: | |||
413 | 369 | ||
414 | /** | 370 | /** |
415 | * ecryptfs_miscdev_write - handle write to daemon miscdev handle | 371 | * ecryptfs_miscdev_write - handle write to daemon miscdev handle |
416 | * @file: File for misc dev handle (ignored) | 372 | * @file: File for misc dev handle |
417 | * @buf: Buffer containing user data | 373 | * @buf: Buffer containing user data |
418 | * @count: Amount of data in @buf | 374 | * @count: Amount of data in @buf |
419 | * @ppos: Pointer to offset in file (ignored) | 375 | * @ppos: Pointer to offset in file (ignored) |
@@ -428,7 +384,6 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, | |||
428 | u32 seq; | 384 | u32 seq; |
429 | size_t packet_size, packet_size_length; | 385 | size_t packet_size, packet_size_length; |
430 | char *data; | 386 | char *data; |
431 | uid_t euid = current_euid(); | ||
432 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; | 387 | unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; |
433 | ssize_t rc; | 388 | ssize_t rc; |
434 | 389 | ||
@@ -488,10 +443,9 @@ memdup: | |||
488 | } | 443 | } |
489 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); | 444 | memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); |
490 | seq = be32_to_cpu(counter_nbo); | 445 | seq = be32_to_cpu(counter_nbo); |
491 | rc = ecryptfs_miscdev_response( | 446 | rc = ecryptfs_miscdev_response(file->private_data, |
492 | &data[PKT_LEN_OFFSET + packet_size_length], | 447 | &data[PKT_LEN_OFFSET + packet_size_length], |
493 | packet_size, euid, current_user_ns(), | 448 | packet_size, seq); |
494 | task_pid(current), seq); | ||
495 | if (rc) { | 449 | if (rc) { |
496 | printk(KERN_WARNING "%s: Failed to deliver miscdev " | 450 | printk(KERN_WARNING "%s: Failed to deliver miscdev " |
497 | "response to requesting operation; rc = [%zd]\n", | 451 | "response to requesting operation; rc = [%zd]\n", |