Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/fs/ecryptfs/miscdev.c
15111 views
1
/**
2
* eCryptfs: Linux filesystem encryption layer
3
*
4
* Copyright (C) 2008 International Business Machines Corp.
5
* Author(s): Michael A. Halcrow <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License version
9
* 2 as published by the Free Software Foundation.
10
*
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19
* 02111-1307, USA.
20
*/
21
22
#include <linux/fs.h>
23
#include <linux/hash.h>
24
#include <linux/random.h>
25
#include <linux/miscdevice.h>
26
#include <linux/poll.h>
27
#include <linux/slab.h>
28
#include <linux/wait.h>
29
#include <linux/module.h>
30
#include "ecryptfs_kernel.h"
31
32
static atomic_t ecryptfs_num_miscdev_opens;
33
34
/**
35
* ecryptfs_miscdev_poll
36
* @file: dev file (ignored)
37
* @pt: dev poll table (ignored)
38
*
39
* Returns the poll mask
40
*/
41
static unsigned int
42
ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
43
{
44
struct ecryptfs_daemon *daemon;
45
unsigned int mask = 0;
46
uid_t euid = current_euid();
47
int rc;
48
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
BUG_ON(rc || !daemon);
53
mutex_lock(&daemon->mux);
54
mutex_unlock(&ecryptfs_daemon_hash_mux);
55
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
56
printk(KERN_WARNING "%s: Attempt to poll on zombified "
57
"daemon\n", __func__);
58
goto out_unlock_daemon;
59
}
60
if (daemon->flags & ECRYPTFS_DAEMON_IN_READ)
61
goto out_unlock_daemon;
62
if (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)
63
goto out_unlock_daemon;
64
daemon->flags |= ECRYPTFS_DAEMON_IN_POLL;
65
mutex_unlock(&daemon->mux);
66
poll_wait(file, &daemon->wait, pt);
67
mutex_lock(&daemon->mux);
68
if (!list_empty(&daemon->msg_ctx_out_queue))
69
mask |= POLLIN | POLLRDNORM;
70
out_unlock_daemon:
71
daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL;
72
mutex_unlock(&daemon->mux);
73
return mask;
74
}
75
76
/**
77
* ecryptfs_miscdev_open
78
* @inode: inode of miscdev handle (ignored)
79
* @file: file for miscdev handle (ignored)
80
*
81
* Returns zero on success; non-zero otherwise
82
*/
83
static int
84
ecryptfs_miscdev_open(struct inode *inode, struct file *file)
85
{
86
struct ecryptfs_daemon *daemon = NULL;
87
uid_t euid = current_euid();
88
int rc;
89
90
mutex_lock(&ecryptfs_daemon_hash_mux);
91
rc = try_module_get(THIS_MODULE);
92
if (rc == 0) {
93
rc = -EIO;
94
printk(KERN_ERR "%s: Error attempting to increment module use "
95
"count; rc = [%d]\n", __func__, rc);
96
goto out_unlock_daemon_list;
97
}
98
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
99
if (rc || !daemon) {
100
rc = ecryptfs_spawn_daemon(&daemon, euid, current_user_ns(),
101
task_pid(current));
102
if (rc) {
103
printk(KERN_ERR "%s: Error attempting to spawn daemon; "
104
"rc = [%d]\n", __func__, rc);
105
goto out_module_put_unlock_daemon_list;
106
}
107
}
108
mutex_lock(&daemon->mux);
109
if (daemon->pid != task_pid(current)) {
110
rc = -EINVAL;
111
printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], "
112
"but pid [0x%p] has attempted to open the handle "
113
"instead\n", __func__, daemon->pid, daemon->euid,
114
task_pid(current));
115
goto out_unlock_daemon;
116
}
117
if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) {
118
rc = -EBUSY;
119
printk(KERN_ERR "%s: Miscellaneous device handle may only be "
120
"opened once per daemon; pid [0x%p] already has this "
121
"handle open\n", __func__, daemon->pid);
122
goto out_unlock_daemon;
123
}
124
daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
125
atomic_inc(&ecryptfs_num_miscdev_opens);
126
out_unlock_daemon:
127
mutex_unlock(&daemon->mux);
128
out_module_put_unlock_daemon_list:
129
if (rc)
130
module_put(THIS_MODULE);
131
out_unlock_daemon_list:
132
mutex_unlock(&ecryptfs_daemon_hash_mux);
133
return rc;
134
}
135
136
/**
137
* ecryptfs_miscdev_release
138
* @inode: inode of fs/ecryptfs/euid handle (ignored)
139
* @file: file for fs/ecryptfs/euid handle (ignored)
140
*
141
* This keeps the daemon registered until the daemon sends another
142
* ioctl to fs/ecryptfs/ctl or until the kernel module unregisters.
143
*
144
* Returns zero on success; non-zero otherwise
145
*/
146
static int
147
ecryptfs_miscdev_release(struct inode *inode, struct file *file)
148
{
149
struct ecryptfs_daemon *daemon = NULL;
150
uid_t euid = current_euid();
151
int rc;
152
153
mutex_lock(&ecryptfs_daemon_hash_mux);
154
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
155
BUG_ON(rc || !daemon);
156
mutex_lock(&daemon->mux);
157
BUG_ON(daemon->pid != task_pid(current));
158
BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
159
daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
160
atomic_dec(&ecryptfs_num_miscdev_opens);
161
mutex_unlock(&daemon->mux);
162
rc = ecryptfs_exorcise_daemon(daemon);
163
if (rc) {
164
printk(KERN_CRIT "%s: Fatal error whilst attempting to "
165
"shut down daemon; rc = [%d]. Please report this "
166
"bug.\n", __func__, rc);
167
BUG();
168
}
169
module_put(THIS_MODULE);
170
mutex_unlock(&ecryptfs_daemon_hash_mux);
171
return rc;
172
}
173
174
/**
175
* ecryptfs_send_miscdev
176
* @data: Data to send to daemon; may be NULL
177
* @data_size: Amount of data to send to daemon
178
* @msg_ctx: Message context, which is used to handle the reply. If
179
* this is NULL, then we do not expect a reply.
180
* @msg_type: Type of message
181
* @msg_flags: Flags for message
182
* @daemon: eCryptfs daemon object
183
*
184
* Add msg_ctx to queue and then, if it exists, notify the blocked
185
* miscdevess about the data being available. Must be called with
186
* ecryptfs_daemon_hash_mux held.
187
*
188
* Returns zero on success; non-zero otherwise
189
*/
190
int ecryptfs_send_miscdev(char *data, size_t data_size,
191
struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
192
u16 msg_flags, struct ecryptfs_daemon *daemon)
193
{
194
int rc = 0;
195
196
mutex_lock(&msg_ctx->mux);
197
msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
198
GFP_KERNEL);
199
if (!msg_ctx->msg) {
200
rc = -ENOMEM;
201
printk(KERN_ERR "%s: Out of memory whilst attempting "
202
"to kmalloc(%zd, GFP_KERNEL)\n", __func__,
203
(sizeof(*msg_ctx->msg) + data_size));
204
goto out_unlock;
205
}
206
msg_ctx->msg->index = msg_ctx->index;
207
msg_ctx->msg->data_len = data_size;
208
msg_ctx->type = msg_type;
209
memcpy(msg_ctx->msg->data, data, data_size);
210
msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
211
mutex_lock(&daemon->mux);
212
list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
213
daemon->num_queued_msg_ctx++;
214
wake_up_interruptible(&daemon->wait);
215
mutex_unlock(&daemon->mux);
216
out_unlock:
217
mutex_unlock(&msg_ctx->mux);
218
return rc;
219
}
220
221
/**
222
* ecryptfs_miscdev_read - format and send message from queue
223
* @file: fs/ecryptfs/euid miscdevfs handle (ignored)
224
* @buf: User buffer into which to copy the next message on the daemon queue
225
* @count: Amount of space available in @buf
226
* @ppos: Offset in file (ignored)
227
*
228
* Pulls the most recent message from the daemon queue, formats it for
229
* being sent via a miscdevfs handle, and copies it into @buf
230
*
231
* Returns the number of bytes copied into the user buffer
232
*/
233
static ssize_t
234
ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
235
loff_t *ppos)
236
{
237
struct ecryptfs_daemon *daemon;
238
struct ecryptfs_msg_ctx *msg_ctx;
239
size_t packet_length_size;
240
char packet_length[3];
241
size_t i;
242
size_t total_length;
243
uid_t euid = current_euid();
244
int rc;
245
246
mutex_lock(&ecryptfs_daemon_hash_mux);
247
/* TODO: Just use file->private_data? */
248
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
249
BUG_ON(rc || !daemon);
250
mutex_lock(&daemon->mux);
251
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
252
rc = 0;
253
mutex_unlock(&ecryptfs_daemon_hash_mux);
254
printk(KERN_WARNING "%s: Attempt to read from zombified "
255
"daemon\n", __func__);
256
goto out_unlock_daemon;
257
}
258
if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) {
259
rc = 0;
260
mutex_unlock(&ecryptfs_daemon_hash_mux);
261
goto out_unlock_daemon;
262
}
263
/* This daemon will not go away so long as this flag is set */
264
daemon->flags |= ECRYPTFS_DAEMON_IN_READ;
265
mutex_unlock(&ecryptfs_daemon_hash_mux);
266
check_list:
267
if (list_empty(&daemon->msg_ctx_out_queue)) {
268
mutex_unlock(&daemon->mux);
269
rc = wait_event_interruptible(
270
daemon->wait, !list_empty(&daemon->msg_ctx_out_queue));
271
mutex_lock(&daemon->mux);
272
if (rc < 0) {
273
rc = 0;
274
goto out_unlock_daemon;
275
}
276
}
277
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
278
rc = 0;
279
goto out_unlock_daemon;
280
}
281
if (list_empty(&daemon->msg_ctx_out_queue)) {
282
/* Something else jumped in since the
283
* wait_event_interruptable() and removed the
284
* message from the queue; try again */
285
goto check_list;
286
}
287
BUG_ON(euid != daemon->euid);
288
BUG_ON(current_user_ns() != daemon->user_ns);
289
BUG_ON(task_pid(current) != daemon->pid);
290
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
291
struct ecryptfs_msg_ctx, daemon_out_list);
292
BUG_ON(!msg_ctx);
293
mutex_lock(&msg_ctx->mux);
294
if (msg_ctx->msg) {
295
rc = ecryptfs_write_packet_length(packet_length,
296
msg_ctx->msg_size,
297
&packet_length_size);
298
if (rc) {
299
rc = 0;
300
printk(KERN_WARNING "%s: Error writing packet length; "
301
"rc = [%d]\n", __func__, rc);
302
goto out_unlock_msg_ctx;
303
}
304
} else {
305
packet_length_size = 0;
306
msg_ctx->msg_size = 0;
307
}
308
/* miscdevfs packet format:
309
* Octet 0: Type
310
* Octets 1-4: network byte order msg_ctx->counter
311
* Octets 5-N0: Size of struct ecryptfs_message to follow
312
* Octets N0-N1: struct ecryptfs_message (including data)
313
*
314
* Octets 5-N1 not written if the packet type does not
315
* include a message */
316
total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
317
if (count < total_length) {
318
rc = 0;
319
printk(KERN_WARNING "%s: Only given user buffer of "
320
"size [%zd], but we need [%zd] to read the "
321
"pending message\n", __func__, count, total_length);
322
goto out_unlock_msg_ctx;
323
}
324
rc = -EFAULT;
325
if (put_user(msg_ctx->type, buf))
326
goto out_unlock_msg_ctx;
327
if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1)))
328
goto out_unlock_msg_ctx;
329
i = 5;
330
if (msg_ctx->msg) {
331
if (copy_to_user(&buf[i], packet_length, packet_length_size))
332
goto out_unlock_msg_ctx;
333
i += packet_length_size;
334
if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size))
335
goto out_unlock_msg_ctx;
336
i += msg_ctx->msg_size;
337
}
338
rc = i;
339
list_del(&msg_ctx->daemon_out_list);
340
kfree(msg_ctx->msg);
341
msg_ctx->msg = NULL;
342
/* We do not expect a reply from the userspace daemon for any
343
* message type other than ECRYPTFS_MSG_REQUEST */
344
if (msg_ctx->type != ECRYPTFS_MSG_REQUEST)
345
ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
346
out_unlock_msg_ctx:
347
mutex_unlock(&msg_ctx->mux);
348
out_unlock_daemon:
349
daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ;
350
mutex_unlock(&daemon->mux);
351
return rc;
352
}
353
354
/**
355
* ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon
356
* @data: Bytes comprising struct ecryptfs_message
357
* @data_size: sizeof(struct ecryptfs_message) + data len
358
* @euid: Effective user id of miscdevess sending the miscdev response
359
* @user_ns: The namespace in which @euid applies
360
* @pid: Miscdevess id of miscdevess sending the miscdev response
361
* @seq: Sequence number for miscdev response packet
362
*
363
* Returns zero on success; non-zero otherwise
364
*/
365
static int ecryptfs_miscdev_response(char *data, size_t data_size,
366
uid_t euid, struct user_namespace *user_ns,
367
struct pid *pid, u32 seq)
368
{
369
struct ecryptfs_message *msg = (struct ecryptfs_message *)data;
370
int rc;
371
372
if ((sizeof(*msg) + msg->data_len) != data_size) {
373
printk(KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = "
374
"[%zd]; data_size = [%zd]. Invalid packet.\n", __func__,
375
(sizeof(*msg) + msg->data_len), data_size);
376
rc = -EINVAL;
377
goto out;
378
}
379
rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq);
380
if (rc)
381
printk(KERN_ERR
382
"Error processing response message; rc = [%d]\n", rc);
383
out:
384
return rc;
385
}
386
387
/**
388
* ecryptfs_miscdev_write - handle write to daemon miscdev handle
389
* @file: File for misc dev handle (ignored)
390
* @buf: Buffer containing user data
391
* @count: Amount of data in @buf
392
* @ppos: Pointer to offset in file (ignored)
393
*
394
* miscdevfs packet format:
395
* Octet 0: Type
396
* Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
397
* Octets 5-N0: Size of struct ecryptfs_message to follow
398
* Octets N0-N1: struct ecryptfs_message (including data)
399
*
400
* Returns the number of bytes read from @buf
401
*/
402
static ssize_t
403
ecryptfs_miscdev_write(struct file *file, const char __user *buf,
404
size_t count, loff_t *ppos)
405
{
406
__be32 counter_nbo;
407
u32 seq;
408
size_t packet_size, packet_size_length, i;
409
ssize_t sz = 0;
410
char *data;
411
uid_t euid = current_euid();
412
int rc;
413
414
if (count == 0)
415
goto out;
416
417
data = memdup_user(buf, count);
418
if (IS_ERR(data)) {
419
printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
420
__func__, PTR_ERR(data));
421
goto out;
422
}
423
sz = count;
424
i = 0;
425
switch (data[i++]) {
426
case ECRYPTFS_MSG_RESPONSE:
427
if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
428
printk(KERN_WARNING "%s: Minimum acceptable packet "
429
"size is [%zd], but amount of data written is "
430
"only [%zd]. Discarding response packet.\n",
431
__func__,
432
(1 + 4 + 1 + sizeof(struct ecryptfs_message)),
433
count);
434
goto out_free;
435
}
436
memcpy(&counter_nbo, &data[i], 4);
437
seq = be32_to_cpu(counter_nbo);
438
i += 4;
439
rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
440
&packet_size_length);
441
if (rc) {
442
printk(KERN_WARNING "%s: Error parsing packet length; "
443
"rc = [%d]\n", __func__, rc);
444
goto out_free;
445
}
446
i += packet_size_length;
447
if ((1 + 4 + packet_size_length + packet_size) != count) {
448
printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
449
" + packet_size([%zd]))([%zd]) != "
450
"count([%zd]). Invalid packet format.\n",
451
__func__, packet_size_length, packet_size,
452
(1 + packet_size_length + packet_size), count);
453
goto out_free;
454
}
455
rc = ecryptfs_miscdev_response(&data[i], packet_size,
456
euid, current_user_ns(),
457
task_pid(current), seq);
458
if (rc)
459
printk(KERN_WARNING "%s: Failed to deliver miscdev "
460
"response to requesting operation; rc = [%d]\n",
461
__func__, rc);
462
break;
463
case ECRYPTFS_MSG_HELO:
464
case ECRYPTFS_MSG_QUIT:
465
break;
466
default:
467
ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
468
"message of unrecognized type [%d]\n",
469
data[0]);
470
break;
471
}
472
out_free:
473
kfree(data);
474
out:
475
return sz;
476
}
477
478
479
static const struct file_operations ecryptfs_miscdev_fops = {
480
.open = ecryptfs_miscdev_open,
481
.poll = ecryptfs_miscdev_poll,
482
.read = ecryptfs_miscdev_read,
483
.write = ecryptfs_miscdev_write,
484
.release = ecryptfs_miscdev_release,
485
.llseek = noop_llseek,
486
};
487
488
static struct miscdevice ecryptfs_miscdev = {
489
.minor = MISC_DYNAMIC_MINOR,
490
.name = "ecryptfs",
491
.fops = &ecryptfs_miscdev_fops
492
};
493
494
/**
495
* ecryptfs_init_ecryptfs_miscdev
496
*
497
* Messages sent to the userspace daemon from the kernel are placed on
498
* a queue associated with the daemon. The next read against the
499
* miscdev handle by that daemon will return the oldest message placed
500
* on the message queue for the daemon.
501
*
502
* Returns zero on success; non-zero otherwise
503
*/
504
int __init ecryptfs_init_ecryptfs_miscdev(void)
505
{
506
int rc;
507
508
atomic_set(&ecryptfs_num_miscdev_opens, 0);
509
rc = misc_register(&ecryptfs_miscdev);
510
if (rc)
511
printk(KERN_ERR "%s: Failed to register miscellaneous device "
512
"for communications with userspace daemons; rc = [%d]\n",
513
__func__, rc);
514
return rc;
515
}
516
517
/**
518
* ecryptfs_destroy_ecryptfs_miscdev
519
*
520
* All of the daemons must be exorcised prior to calling this
521
* function.
522
*/
523
void ecryptfs_destroy_ecryptfs_miscdev(void)
524
{
525
BUG_ON(atomic_read(&ecryptfs_num_miscdev_opens) != 0);
526
misc_deregister(&ecryptfs_miscdev);
527
}
528
529