blob: a449ee661987ce75bcacd846758267dc37330c58 [file] [log] [blame]
David Howells8667d432021-11-26 15:12:07 +00001// SPDX-License-Identifier: GPL-2.0-or-later
2/* Daemon interface
3 *
4 * Copyright (C) 2007, 2021 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 */
7
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/sched.h>
11#include <linux/completion.h>
12#include <linux/slab.h>
13#include <linux/fs.h>
14#include <linux/file.h>
15#include <linux/namei.h>
16#include <linux/poll.h>
17#include <linux/mount.h>
18#include <linux/statfs.h>
19#include <linux/ctype.h>
20#include <linux/string.h>
21#include <linux/fs_struct.h>
22#include "internal.h"
23
24static int cachefiles_daemon_open(struct inode *, struct file *);
25static int cachefiles_daemon_release(struct inode *, struct file *);
26static ssize_t cachefiles_daemon_read(struct file *, char __user *, size_t,
27 loff_t *);
28static ssize_t cachefiles_daemon_write(struct file *, const char __user *,
29 size_t, loff_t *);
30static __poll_t cachefiles_daemon_poll(struct file *,
31 struct poll_table_struct *);
32static int cachefiles_daemon_frun(struct cachefiles_cache *, char *);
33static int cachefiles_daemon_fcull(struct cachefiles_cache *, char *);
34static int cachefiles_daemon_fstop(struct cachefiles_cache *, char *);
35static int cachefiles_daemon_brun(struct cachefiles_cache *, char *);
36static int cachefiles_daemon_bcull(struct cachefiles_cache *, char *);
37static int cachefiles_daemon_bstop(struct cachefiles_cache *, char *);
38static int cachefiles_daemon_cull(struct cachefiles_cache *, char *);
39static int cachefiles_daemon_debug(struct cachefiles_cache *, char *);
40static int cachefiles_daemon_dir(struct cachefiles_cache *, char *);
41static int cachefiles_daemon_inuse(struct cachefiles_cache *, char *);
42static int cachefiles_daemon_secctx(struct cachefiles_cache *, char *);
43static int cachefiles_daemon_tag(struct cachefiles_cache *, char *);
44static int cachefiles_daemon_bind(struct cachefiles_cache *, char *);
45static void cachefiles_daemon_unbind(struct cachefiles_cache *);
46
47static unsigned long cachefiles_open;
48
49const struct file_operations cachefiles_daemon_fops = {
50 .owner = THIS_MODULE,
51 .open = cachefiles_daemon_open,
52 .release = cachefiles_daemon_release,
53 .read = cachefiles_daemon_read,
54 .write = cachefiles_daemon_write,
55 .poll = cachefiles_daemon_poll,
56 .llseek = noop_llseek,
57};
58
59struct cachefiles_daemon_cmd {
60 char name[8];
61 int (*handler)(struct cachefiles_cache *cache, char *args);
62};
63
64static const struct cachefiles_daemon_cmd cachefiles_daemon_cmds[] = {
65 { "bind", cachefiles_daemon_bind },
66 { "brun", cachefiles_daemon_brun },
67 { "bcull", cachefiles_daemon_bcull },
68 { "bstop", cachefiles_daemon_bstop },
69 { "cull", cachefiles_daemon_cull },
70 { "debug", cachefiles_daemon_debug },
71 { "dir", cachefiles_daemon_dir },
72 { "frun", cachefiles_daemon_frun },
73 { "fcull", cachefiles_daemon_fcull },
74 { "fstop", cachefiles_daemon_fstop },
75 { "inuse", cachefiles_daemon_inuse },
76 { "secctx", cachefiles_daemon_secctx },
77 { "tag", cachefiles_daemon_tag },
78 { "", NULL }
79};
80
81
82/*
83 * Prepare a cache for caching.
84 */
85static int cachefiles_daemon_open(struct inode *inode, struct file *file)
86{
87 struct cachefiles_cache *cache;
88
89 _enter("");
90
91 /* only the superuser may do this */
92 if (!capable(CAP_SYS_ADMIN))
93 return -EPERM;
94
95 /* the cachefiles device may only be open once at a time */
96 if (xchg(&cachefiles_open, 1) == 1)
97 return -EBUSY;
98
99 /* allocate a cache record */
100 cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL);
101 if (!cache) {
102 cachefiles_open = 0;
103 return -ENOMEM;
104 }
105
106 mutex_init(&cache->daemon_mutex);
107 init_waitqueue_head(&cache->daemon_pollwq);
108
109 /* set default caching limits
110 * - limit at 1% free space and/or free files
111 * - cull below 5% free space and/or free files
112 * - cease culling above 7% free space and/or free files
113 */
114 cache->frun_percent = 7;
115 cache->fcull_percent = 5;
116 cache->fstop_percent = 1;
117 cache->brun_percent = 7;
118 cache->bcull_percent = 5;
119 cache->bstop_percent = 1;
120
121 file->private_data = cache;
122 cache->cachefilesd = file;
123 return 0;
124}
125
126/*
127 * Release a cache.
128 */
129static int cachefiles_daemon_release(struct inode *inode, struct file *file)
130{
131 struct cachefiles_cache *cache = file->private_data;
132
133 _enter("");
134
135 ASSERT(cache);
136
137 set_bit(CACHEFILES_DEAD, &cache->flags);
138
139 cachefiles_daemon_unbind(cache);
140
141 /* clean up the control file interface */
142 cache->cachefilesd = NULL;
143 file->private_data = NULL;
144 cachefiles_open = 0;
145
146 kfree(cache);
147
148 _leave("");
149 return 0;
150}
151
152/*
153 * Read the cache state.
154 */
155static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer,
156 size_t buflen, loff_t *pos)
157{
158 struct cachefiles_cache *cache = file->private_data;
159 unsigned long long b_released;
160 unsigned f_released;
161 char buffer[256];
162 int n;
163
164 //_enter(",,%zu,", buflen);
165
166 if (!test_bit(CACHEFILES_READY, &cache->flags))
167 return 0;
168
169 /* check how much space the cache has */
David Howells80f94f22021-10-21 08:59:46 +0100170 cachefiles_has_space(cache, 0, 0);
David Howells8667d432021-11-26 15:12:07 +0000171
172 /* summarise */
173 f_released = atomic_xchg(&cache->f_released, 0);
174 b_released = atomic_long_xchg(&cache->b_released, 0);
175 clear_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
176
177 n = snprintf(buffer, sizeof(buffer),
178 "cull=%c"
179 " frun=%llx"
180 " fcull=%llx"
181 " fstop=%llx"
182 " brun=%llx"
183 " bcull=%llx"
184 " bstop=%llx"
185 " freleased=%x"
186 " breleased=%llx",
187 test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0',
188 (unsigned long long) cache->frun,
189 (unsigned long long) cache->fcull,
190 (unsigned long long) cache->fstop,
191 (unsigned long long) cache->brun,
192 (unsigned long long) cache->bcull,
193 (unsigned long long) cache->bstop,
194 f_released,
195 b_released);
196
197 if (n > buflen)
198 return -EMSGSIZE;
199
200 if (copy_to_user(_buffer, buffer, n) != 0)
201 return -EFAULT;
202
203 return n;
204}
205
206/*
207 * Take a command from cachefilesd, parse it and act on it.
208 */
209static ssize_t cachefiles_daemon_write(struct file *file,
210 const char __user *_data,
211 size_t datalen,
212 loff_t *pos)
213{
214 const struct cachefiles_daemon_cmd *cmd;
215 struct cachefiles_cache *cache = file->private_data;
216 ssize_t ret;
217 char *data, *args, *cp;
218
219 //_enter(",,%zu,", datalen);
220
221 ASSERT(cache);
222
223 if (test_bit(CACHEFILES_DEAD, &cache->flags))
224 return -EIO;
225
226 if (datalen > PAGE_SIZE - 1)
227 return -EOPNOTSUPP;
228
229 /* drag the command string into the kernel so we can parse it */
230 data = memdup_user_nul(_data, datalen);
231 if (IS_ERR(data))
232 return PTR_ERR(data);
233
234 ret = -EINVAL;
235 if (memchr(data, '\0', datalen))
236 goto error;
237
238 /* strip any newline */
239 cp = memchr(data, '\n', datalen);
240 if (cp) {
241 if (cp == data)
242 goto error;
243
244 *cp = '\0';
245 }
246
247 /* parse the command */
248 ret = -EOPNOTSUPP;
249
250 for (args = data; *args; args++)
251 if (isspace(*args))
252 break;
253 if (*args) {
254 if (args == data)
255 goto error;
256 *args = '\0';
257 args = skip_spaces(++args);
258 }
259
260 /* run the appropriate command handler */
261 for (cmd = cachefiles_daemon_cmds; cmd->name[0]; cmd++)
262 if (strcmp(cmd->name, data) == 0)
263 goto found_command;
264
265error:
266 kfree(data);
267 //_leave(" = %zd", ret);
268 return ret;
269
270found_command:
271 mutex_lock(&cache->daemon_mutex);
272
273 ret = -EIO;
274 if (!test_bit(CACHEFILES_DEAD, &cache->flags))
275 ret = cmd->handler(cache, args);
276
277 mutex_unlock(&cache->daemon_mutex);
278
279 if (ret == 0)
280 ret = datalen;
281 goto error;
282}
283
284/*
285 * Poll for culling state
286 * - use EPOLLOUT to indicate culling state
287 */
288static __poll_t cachefiles_daemon_poll(struct file *file,
289 struct poll_table_struct *poll)
290{
291 struct cachefiles_cache *cache = file->private_data;
292 __poll_t mask;
293
294 poll_wait(file, &cache->daemon_pollwq, poll);
295 mask = 0;
296
297 if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags))
298 mask |= EPOLLIN;
299
300 if (test_bit(CACHEFILES_CULLING, &cache->flags))
301 mask |= EPOLLOUT;
302
303 return mask;
304}
305
306/*
307 * Give a range error for cache space constraints
308 * - can be tail-called
309 */
310static int cachefiles_daemon_range_error(struct cachefiles_cache *cache,
311 char *args)
312{
313 pr_err("Free space limits must be in range 0%%<=stop<cull<run<100%%\n");
314
315 return -EINVAL;
316}
317
318/*
319 * Set the percentage of files at which to stop culling
320 * - command: "frun <N>%"
321 */
322static int cachefiles_daemon_frun(struct cachefiles_cache *cache, char *args)
323{
324 unsigned long frun;
325
326 _enter(",%s", args);
327
328 if (!*args)
329 return -EINVAL;
330
331 frun = simple_strtoul(args, &args, 10);
332 if (args[0] != '%' || args[1] != '\0')
333 return -EINVAL;
334
335 if (frun <= cache->fcull_percent || frun >= 100)
336 return cachefiles_daemon_range_error(cache, args);
337
338 cache->frun_percent = frun;
339 return 0;
340}
341
342/*
343 * Set the percentage of files at which to start culling
344 * - command: "fcull <N>%"
345 */
346static int cachefiles_daemon_fcull(struct cachefiles_cache *cache, char *args)
347{
348 unsigned long fcull;
349
350 _enter(",%s", args);
351
352 if (!*args)
353 return -EINVAL;
354
355 fcull = simple_strtoul(args, &args, 10);
356 if (args[0] != '%' || args[1] != '\0')
357 return -EINVAL;
358
359 if (fcull <= cache->fstop_percent || fcull >= cache->frun_percent)
360 return cachefiles_daemon_range_error(cache, args);
361
362 cache->fcull_percent = fcull;
363 return 0;
364}
365
366/*
367 * Set the percentage of files at which to stop allocating
368 * - command: "fstop <N>%"
369 */
370static int cachefiles_daemon_fstop(struct cachefiles_cache *cache, char *args)
371{
372 unsigned long fstop;
373
374 _enter(",%s", args);
375
376 if (!*args)
377 return -EINVAL;
378
379 fstop = simple_strtoul(args, &args, 10);
380 if (args[0] != '%' || args[1] != '\0')
381 return -EINVAL;
382
383 if (fstop >= cache->fcull_percent)
384 return cachefiles_daemon_range_error(cache, args);
385
386 cache->fstop_percent = fstop;
387 return 0;
388}
389
390/*
391 * Set the percentage of blocks at which to stop culling
392 * - command: "brun <N>%"
393 */
394static int cachefiles_daemon_brun(struct cachefiles_cache *cache, char *args)
395{
396 unsigned long brun;
397
398 _enter(",%s", args);
399
400 if (!*args)
401 return -EINVAL;
402
403 brun = simple_strtoul(args, &args, 10);
404 if (args[0] != '%' || args[1] != '\0')
405 return -EINVAL;
406
407 if (brun <= cache->bcull_percent || brun >= 100)
408 return cachefiles_daemon_range_error(cache, args);
409
410 cache->brun_percent = brun;
411 return 0;
412}
413
414/*
415 * Set the percentage of blocks at which to start culling
416 * - command: "bcull <N>%"
417 */
418static int cachefiles_daemon_bcull(struct cachefiles_cache *cache, char *args)
419{
420 unsigned long bcull;
421
422 _enter(",%s", args);
423
424 if (!*args)
425 return -EINVAL;
426
427 bcull = simple_strtoul(args, &args, 10);
428 if (args[0] != '%' || args[1] != '\0')
429 return -EINVAL;
430
431 if (bcull <= cache->bstop_percent || bcull >= cache->brun_percent)
432 return cachefiles_daemon_range_error(cache, args);
433
434 cache->bcull_percent = bcull;
435 return 0;
436}
437
438/*
439 * Set the percentage of blocks at which to stop allocating
440 * - command: "bstop <N>%"
441 */
442static int cachefiles_daemon_bstop(struct cachefiles_cache *cache, char *args)
443{
444 unsigned long bstop;
445
446 _enter(",%s", args);
447
448 if (!*args)
449 return -EINVAL;
450
451 bstop = simple_strtoul(args, &args, 10);
452 if (args[0] != '%' || args[1] != '\0')
453 return -EINVAL;
454
455 if (bstop >= cache->bcull_percent)
456 return cachefiles_daemon_range_error(cache, args);
457
458 cache->bstop_percent = bstop;
459 return 0;
460}
461
462/*
463 * Set the cache directory
464 * - command: "dir <name>"
465 */
466static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)
467{
468 char *dir;
469
470 _enter(",%s", args);
471
472 if (!*args) {
473 pr_err("Empty directory specified\n");
474 return -EINVAL;
475 }
476
477 if (cache->rootdirname) {
478 pr_err("Second cache directory specified\n");
479 return -EEXIST;
480 }
481
482 dir = kstrdup(args, GFP_KERNEL);
483 if (!dir)
484 return -ENOMEM;
485
486 cache->rootdirname = dir;
487 return 0;
488}
489
490/*
491 * Set the cache security context
492 * - command: "secctx <ctx>"
493 */
494static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
495{
496 char *secctx;
497
498 _enter(",%s", args);
499
500 if (!*args) {
501 pr_err("Empty security context specified\n");
502 return -EINVAL;
503 }
504
505 if (cache->secctx) {
506 pr_err("Second security context specified\n");
507 return -EINVAL;
508 }
509
510 secctx = kstrdup(args, GFP_KERNEL);
511 if (!secctx)
512 return -ENOMEM;
513
514 cache->secctx = secctx;
515 return 0;
516}
517
518/*
519 * Set the cache tag
520 * - command: "tag <name>"
521 */
522static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args)
523{
524 char *tag;
525
526 _enter(",%s", args);
527
528 if (!*args) {
529 pr_err("Empty tag specified\n");
530 return -EINVAL;
531 }
532
533 if (cache->tag)
534 return -EEXIST;
535
536 tag = kstrdup(args, GFP_KERNEL);
537 if (!tag)
538 return -ENOMEM;
539
540 cache->tag = tag;
541 return 0;
542}
543
544/*
545 * Request a node in the cache be culled from the current working directory
546 * - command: "cull <name>"
547 */
548static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
549{
550 struct path path;
551 const struct cred *saved_cred;
552 int ret;
553
554 _enter(",%s", args);
555
556 if (strchr(args, '/'))
557 goto inval;
558
559 if (!test_bit(CACHEFILES_READY, &cache->flags)) {
560 pr_err("cull applied to unready cache\n");
561 return -EIO;
562 }
563
564 if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
565 pr_err("cull applied to dead cache\n");
566 return -EIO;
567 }
568
569 get_fs_pwd(current->fs, &path);
570
571 if (!d_can_lookup(path.dentry))
572 goto notdir;
573
574 cachefiles_begin_secure(cache, &saved_cred);
575 ret = -ENOANO; // PLACEHOLDER: Do culling
576 cachefiles_end_secure(cache, saved_cred);
577
578 path_put(&path);
579 _leave(" = %d", ret);
580 return ret;
581
582notdir:
583 path_put(&path);
584 pr_err("cull command requires dirfd to be a directory\n");
585 return -ENOTDIR;
586
587inval:
588 pr_err("cull command requires dirfd and filename\n");
589 return -EINVAL;
590}
591
592/*
593 * Set debugging mode
594 * - command: "debug <mask>"
595 */
596static int cachefiles_daemon_debug(struct cachefiles_cache *cache, char *args)
597{
598 unsigned long mask;
599
600 _enter(",%s", args);
601
602 mask = simple_strtoul(args, &args, 0);
603 if (args[0] != '\0')
604 goto inval;
605
606 cachefiles_debug = mask;
607 _leave(" = 0");
608 return 0;
609
610inval:
611 pr_err("debug command requires mask\n");
612 return -EINVAL;
613}
614
615/*
616 * Find out whether an object in the current working directory is in use or not
617 * - command: "inuse <name>"
618 */
619static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
620{
621 struct path path;
622 const struct cred *saved_cred;
623 int ret;
624
625 //_enter(",%s", args);
626
627 if (strchr(args, '/'))
628 goto inval;
629
630 if (!test_bit(CACHEFILES_READY, &cache->flags)) {
631 pr_err("inuse applied to unready cache\n");
632 return -EIO;
633 }
634
635 if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
636 pr_err("inuse applied to dead cache\n");
637 return -EIO;
638 }
639
640 get_fs_pwd(current->fs, &path);
641
642 if (!d_can_lookup(path.dentry))
643 goto notdir;
644
645 cachefiles_begin_secure(cache, &saved_cred);
646 ret = -ENOANO; // PLACEHOLDER: Check if in use
647 cachefiles_end_secure(cache, saved_cred);
648
649 path_put(&path);
650 //_leave(" = %d", ret);
651 return ret;
652
653notdir:
654 path_put(&path);
655 pr_err("inuse command requires dirfd to be a directory\n");
656 return -ENOTDIR;
657
658inval:
659 pr_err("inuse command requires dirfd and filename\n");
660 return -EINVAL;
661}
662
663/*
664 * Bind a directory as a cache
665 */
666static int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
667{
668 _enter("{%u,%u,%u,%u,%u,%u},%s",
669 cache->frun_percent,
670 cache->fcull_percent,
671 cache->fstop_percent,
672 cache->brun_percent,
673 cache->bcull_percent,
674 cache->bstop_percent,
675 args);
676
677 if (cache->fstop_percent >= cache->fcull_percent ||
678 cache->fcull_percent >= cache->frun_percent ||
679 cache->frun_percent >= 100)
680 return -ERANGE;
681
682 if (cache->bstop_percent >= cache->bcull_percent ||
683 cache->bcull_percent >= cache->brun_percent ||
684 cache->brun_percent >= 100)
685 return -ERANGE;
686
687 if (*args) {
688 pr_err("'bind' command doesn't take an argument\n");
689 return -EINVAL;
690 }
691
692 if (!cache->rootdirname) {
693 pr_err("No cache directory specified\n");
694 return -EINVAL;
695 }
696
697 /* Don't permit already bound caches to be re-bound */
698 if (test_bit(CACHEFILES_READY, &cache->flags)) {
699 pr_err("Cache already bound\n");
700 return -EBUSY;
701 }
702
703 pr_warn("Cache is disabled for development\n");
704 return -ENOANO; // Don't allow the cache to operate yet
David Howellsd1065b02021-11-26 14:29:06 +0000705 //return cachefiles_add_cache(cache);
David Howells8667d432021-11-26 15:12:07 +0000706}
707
708/*
709 * Unbind a cache.
710 */
711static void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
712{
713 _enter("");
714
David Howellsd1065b02021-11-26 14:29:06 +0000715 if (test_bit(CACHEFILES_READY, &cache->flags))
716 cachefiles_withdraw_cache(cache);
David Howells8667d432021-11-26 15:12:07 +0000717
David Howellsd1065b02021-11-26 14:29:06 +0000718 cachefiles_put_directory(cache->graveyard);
719 cachefiles_put_directory(cache->store);
David Howells8667d432021-11-26 15:12:07 +0000720 mntput(cache->mnt);
721
722 kfree(cache->rootdirname);
723 kfree(cache->secctx);
724 kfree(cache->tag);
725
726 _leave("");
727}