diff options
Diffstat (limited to 'fs/cachefiles')
-rw-r--r-- | fs/cachefiles/bind.c | 11 | ||||
-rw-r--r-- | fs/cachefiles/daemon.c | 4 | ||||
-rw-r--r-- | fs/cachefiles/interface.c | 1 | ||||
-rw-r--r-- | fs/cachefiles/internal.h | 1 | ||||
-rw-r--r-- | fs/cachefiles/namei.c | 97 | ||||
-rw-r--r-- | fs/cachefiles/rdwr.c | 3 | ||||
-rw-r--r-- | fs/cachefiles/security.c | 4 | ||||
-rw-r--r-- | fs/cachefiles/xattr.c | 1 |
8 files changed, 105 insertions, 17 deletions
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c index 3797e0077b35..2906077ac798 100644 --- a/fs/cachefiles/bind.c +++ b/fs/cachefiles/bind.c | |||
@@ -84,7 +84,7 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args) | |||
84 | static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) | 84 | static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) |
85 | { | 85 | { |
86 | struct cachefiles_object *fsdef; | 86 | struct cachefiles_object *fsdef; |
87 | struct nameidata nd; | 87 | struct path path; |
88 | struct kstatfs stats; | 88 | struct kstatfs stats; |
89 | struct dentry *graveyard, *cachedir, *root; | 89 | struct dentry *graveyard, *cachedir, *root; |
90 | const struct cred *saved_cred; | 90 | const struct cred *saved_cred; |
@@ -114,15 +114,12 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) | |||
114 | _debug("- fsdef %p", fsdef); | 114 | _debug("- fsdef %p", fsdef); |
115 | 115 | ||
116 | /* look up the directory at the root of the cache */ | 116 | /* look up the directory at the root of the cache */ |
117 | memset(&nd, 0, sizeof(nd)); | 117 | ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path); |
118 | |||
119 | ret = path_lookup(cache->rootdirname, LOOKUP_DIRECTORY, &nd); | ||
120 | if (ret < 0) | 118 | if (ret < 0) |
121 | goto error_open_root; | 119 | goto error_open_root; |
122 | 120 | ||
123 | cache->mnt = mntget(nd.path.mnt); | 121 | cache->mnt = path.mnt; |
124 | root = dget(nd.path.dentry); | 122 | root = path.dentry; |
125 | path_put(&nd.path); | ||
126 | 123 | ||
127 | /* check parameters */ | 124 | /* check parameters */ |
128 | ret = -EOPNOTSUPP; | 125 | ret = -EOPNOTSUPP; |
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index 4618516dd994..c2413561ea75 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
22 | #include <linux/statfs.h> | 22 | #include <linux/statfs.h> |
23 | #include <linux/ctype.h> | 23 | #include <linux/ctype.h> |
24 | #include <linux/string.h> | ||
24 | #include <linux/fs_struct.h> | 25 | #include <linux/fs_struct.h> |
25 | #include "internal.h" | 26 | #include "internal.h" |
26 | 27 | ||
@@ -257,8 +258,7 @@ static ssize_t cachefiles_daemon_write(struct file *file, | |||
257 | if (args == data) | 258 | if (args == data) |
258 | goto error; | 259 | goto error; |
259 | *args = '\0'; | 260 | *args = '\0'; |
260 | for (args++; isspace(*args); args++) | 261 | args = skip_spaces(++args); |
261 | continue; | ||
262 | } | 262 | } |
263 | 263 | ||
264 | /* run the appropriate command handler */ | 264 | /* run the appropriate command handler */ |
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 27089311fbea..37fe101a4e0d 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/slab.h> | ||
12 | #include <linux/mount.h> | 13 | #include <linux/mount.h> |
13 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
14 | #include "internal.h" | 15 | #include "internal.h" |
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index f7c255f9c624..a8cd821226da 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h | |||
@@ -34,6 +34,7 @@ struct cachefiles_object { | |||
34 | loff_t i_size; /* object size */ | 34 | loff_t i_size; /* object size */ |
35 | unsigned long flags; | 35 | unsigned long flags; |
36 | #define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */ | 36 | #define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */ |
37 | #define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */ | ||
37 | atomic_t usage; /* object usage count */ | 38 | atomic_t usage; /* object usage count */ |
38 | uint8_t type; /* object type */ | 39 | uint8_t type; /* object type */ |
39 | uint8_t new; /* T if object new */ | 40 | uint8_t new; /* T if object new */ |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 14ac4806e291..f4a7840bf42c 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/namei.h> | 20 | #include <linux/namei.h> |
21 | #include <linux/security.h> | 21 | #include <linux/security.h> |
22 | #include <linux/slab.h> | ||
22 | #include "internal.h" | 23 | #include "internal.h" |
23 | 24 | ||
24 | #define CACHEFILES_KEYBUF_SIZE 512 | 25 | #define CACHEFILES_KEYBUF_SIZE 512 |
@@ -92,6 +93,59 @@ static noinline void cachefiles_printk_object(struct cachefiles_object *object, | |||
92 | } | 93 | } |
93 | 94 | ||
94 | /* | 95 | /* |
96 | * mark the owner of a dentry, if there is one, to indicate that that dentry | ||
97 | * has been preemptively deleted | ||
98 | * - the caller must hold the i_mutex on the dentry's parent as required to | ||
99 | * call vfs_unlink(), vfs_rmdir() or vfs_rename() | ||
100 | */ | ||
101 | static void cachefiles_mark_object_buried(struct cachefiles_cache *cache, | ||
102 | struct dentry *dentry) | ||
103 | { | ||
104 | struct cachefiles_object *object; | ||
105 | struct rb_node *p; | ||
106 | |||
107 | _enter(",'%*.*s'", | ||
108 | dentry->d_name.len, dentry->d_name.len, dentry->d_name.name); | ||
109 | |||
110 | write_lock(&cache->active_lock); | ||
111 | |||
112 | p = cache->active_nodes.rb_node; | ||
113 | while (p) { | ||
114 | object = rb_entry(p, struct cachefiles_object, active_node); | ||
115 | if (object->dentry > dentry) | ||
116 | p = p->rb_left; | ||
117 | else if (object->dentry < dentry) | ||
118 | p = p->rb_right; | ||
119 | else | ||
120 | goto found_dentry; | ||
121 | } | ||
122 | |||
123 | write_unlock(&cache->active_lock); | ||
124 | _leave(" [no owner]"); | ||
125 | return; | ||
126 | |||
127 | /* found the dentry for */ | ||
128 | found_dentry: | ||
129 | kdebug("preemptive burial: OBJ%x [%s] %p", | ||
130 | object->fscache.debug_id, | ||
131 | fscache_object_states[object->fscache.state], | ||
132 | dentry); | ||
133 | |||
134 | if (object->fscache.state < FSCACHE_OBJECT_DYING) { | ||
135 | printk(KERN_ERR "\n"); | ||
136 | printk(KERN_ERR "CacheFiles: Error:" | ||
137 | " Can't preemptively bury live object\n"); | ||
138 | cachefiles_printk_object(object, NULL); | ||
139 | } else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { | ||
140 | printk(KERN_ERR "CacheFiles: Error:" | ||
141 | " Object already preemptively buried\n"); | ||
142 | } | ||
143 | |||
144 | write_unlock(&cache->active_lock); | ||
145 | _leave(" [owner marked]"); | ||
146 | } | ||
147 | |||
148 | /* | ||
95 | * record the fact that an object is now active | 149 | * record the fact that an object is now active |
96 | */ | 150 | */ |
97 | static int cachefiles_mark_object_active(struct cachefiles_cache *cache, | 151 | static int cachefiles_mark_object_active(struct cachefiles_cache *cache, |
@@ -218,7 +272,8 @@ requeue: | |||
218 | */ | 272 | */ |
219 | static int cachefiles_bury_object(struct cachefiles_cache *cache, | 273 | static int cachefiles_bury_object(struct cachefiles_cache *cache, |
220 | struct dentry *dir, | 274 | struct dentry *dir, |
221 | struct dentry *rep) | 275 | struct dentry *rep, |
276 | bool preemptive) | ||
222 | { | 277 | { |
223 | struct dentry *grave, *trap; | 278 | struct dentry *grave, *trap; |
224 | char nbuffer[8 + 8 + 1]; | 279 | char nbuffer[8 + 8 + 1]; |
@@ -228,11 +283,16 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, | |||
228 | dir->d_name.len, dir->d_name.len, dir->d_name.name, | 283 | dir->d_name.len, dir->d_name.len, dir->d_name.name, |
229 | rep->d_name.len, rep->d_name.len, rep->d_name.name); | 284 | rep->d_name.len, rep->d_name.len, rep->d_name.name); |
230 | 285 | ||
286 | _debug("remove %p from %p", rep, dir); | ||
287 | |||
231 | /* non-directories can just be unlinked */ | 288 | /* non-directories can just be unlinked */ |
232 | if (!S_ISDIR(rep->d_inode->i_mode)) { | 289 | if (!S_ISDIR(rep->d_inode->i_mode)) { |
233 | _debug("unlink stale object"); | 290 | _debug("unlink stale object"); |
234 | ret = vfs_unlink(dir->d_inode, rep); | 291 | ret = vfs_unlink(dir->d_inode, rep); |
235 | 292 | ||
293 | if (preemptive) | ||
294 | cachefiles_mark_object_buried(cache, rep); | ||
295 | |||
236 | mutex_unlock(&dir->d_inode->i_mutex); | 296 | mutex_unlock(&dir->d_inode->i_mutex); |
237 | 297 | ||
238 | if (ret == -EIO) | 298 | if (ret == -EIO) |
@@ -324,6 +384,9 @@ try_again: | |||
324 | if (ret != 0 && ret != -ENOMEM) | 384 | if (ret != 0 && ret != -ENOMEM) |
325 | cachefiles_io_error(cache, "Rename failed with error %d", ret); | 385 | cachefiles_io_error(cache, "Rename failed with error %d", ret); |
326 | 386 | ||
387 | if (preemptive) | ||
388 | cachefiles_mark_object_buried(cache, rep); | ||
389 | |||
327 | unlock_rename(cache->graveyard, dir); | 390 | unlock_rename(cache->graveyard, dir); |
328 | dput(grave); | 391 | dput(grave); |
329 | _leave(" = 0"); | 392 | _leave(" = 0"); |
@@ -339,7 +402,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache, | |||
339 | struct dentry *dir; | 402 | struct dentry *dir; |
340 | int ret; | 403 | int ret; |
341 | 404 | ||
342 | _enter(",{%p}", object->dentry); | 405 | _enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry); |
343 | 406 | ||
344 | ASSERT(object->dentry); | 407 | ASSERT(object->dentry); |
345 | ASSERT(object->dentry->d_inode); | 408 | ASSERT(object->dentry->d_inode); |
@@ -348,7 +411,27 @@ int cachefiles_delete_object(struct cachefiles_cache *cache, | |||
348 | dir = dget_parent(object->dentry); | 411 | dir = dget_parent(object->dentry); |
349 | 412 | ||
350 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | 413 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); |
351 | ret = cachefiles_bury_object(cache, dir, object->dentry); | 414 | |
415 | if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { | ||
416 | /* object allocation for the same key preemptively deleted this | ||
417 | * object's file so that it could create its own file */ | ||
418 | _debug("object preemptively buried"); | ||
419 | mutex_unlock(&dir->d_inode->i_mutex); | ||
420 | ret = 0; | ||
421 | } else { | ||
422 | /* we need to check that our parent is _still_ our parent - it | ||
423 | * may have been renamed */ | ||
424 | if (dir == object->dentry->d_parent) { | ||
425 | ret = cachefiles_bury_object(cache, dir, | ||
426 | object->dentry, false); | ||
427 | } else { | ||
428 | /* it got moved, presumably by cachefilesd culling it, | ||
429 | * so it's no longer in the key path and we can ignore | ||
430 | * it */ | ||
431 | mutex_unlock(&dir->d_inode->i_mutex); | ||
432 | ret = 0; | ||
433 | } | ||
434 | } | ||
352 | 435 | ||
353 | dput(dir); | 436 | dput(dir); |
354 | _leave(" = %d", ret); | 437 | _leave(" = %d", ret); |
@@ -370,7 +453,9 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, | |||
370 | const char *name; | 453 | const char *name; |
371 | int ret, nlen; | 454 | int ret, nlen; |
372 | 455 | ||
373 | _enter("{%p},,%s,", parent->dentry, key); | 456 | _enter("OBJ%x{%p},OBJ%x,%s,", |
457 | parent->fscache.debug_id, parent->dentry, | ||
458 | object->fscache.debug_id, key); | ||
374 | 459 | ||
375 | cache = container_of(parent->fscache.cache, | 460 | cache = container_of(parent->fscache.cache, |
376 | struct cachefiles_cache, cache); | 461 | struct cachefiles_cache, cache); |
@@ -498,7 +583,7 @@ lookup_again: | |||
498 | * mutex) */ | 583 | * mutex) */ |
499 | object->dentry = NULL; | 584 | object->dentry = NULL; |
500 | 585 | ||
501 | ret = cachefiles_bury_object(cache, dir, next); | 586 | ret = cachefiles_bury_object(cache, dir, next, true); |
502 | dput(next); | 587 | dput(next); |
503 | next = NULL; | 588 | next = NULL; |
504 | 589 | ||
@@ -817,7 +902,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, | |||
817 | /* actually remove the victim (drops the dir mutex) */ | 902 | /* actually remove the victim (drops the dir mutex) */ |
818 | _debug("bury"); | 903 | _debug("bury"); |
819 | 904 | ||
820 | ret = cachefiles_bury_object(cache, dir, victim); | 905 | ret = cachefiles_bury_object(cache, dir, victim, false); |
821 | if (ret < 0) | 906 | if (ret < 0) |
822 | goto error; | 907 | goto error; |
823 | 908 | ||
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index a6c8c6fe8df9..0f0d41fbb03f 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c | |||
@@ -10,8 +10,8 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/mount.h> | 12 | #include <linux/mount.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/file.h> | 14 | #include <linux/file.h> |
14 | #include <linux/ima.h> | ||
15 | #include "internal.h" | 15 | #include "internal.h" |
16 | 16 | ||
17 | /* | 17 | /* |
@@ -923,7 +923,6 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page) | |||
923 | if (IS_ERR(file)) { | 923 | if (IS_ERR(file)) { |
924 | ret = PTR_ERR(file); | 924 | ret = PTR_ERR(file); |
925 | } else { | 925 | } else { |
926 | ima_counts_get(file); | ||
927 | ret = -EIO; | 926 | ret = -EIO; |
928 | if (file->f_op->write) { | 927 | if (file->f_op->write) { |
929 | pos = (loff_t) page->index << PAGE_SHIFT; | 928 | pos = (loff_t) page->index << PAGE_SHIFT; |
diff --git a/fs/cachefiles/security.c b/fs/cachefiles/security.c index b5808cdb2232..039b5011d83b 100644 --- a/fs/cachefiles/security.c +++ b/fs/cachefiles/security.c | |||
@@ -77,6 +77,8 @@ static int cachefiles_check_cache_dir(struct cachefiles_cache *cache, | |||
77 | /* | 77 | /* |
78 | * check the security details of the on-disk cache | 78 | * check the security details of the on-disk cache |
79 | * - must be called with security override in force | 79 | * - must be called with security override in force |
80 | * - must return with a security override in force - even in the case of an | ||
81 | * error | ||
80 | */ | 82 | */ |
81 | int cachefiles_determine_cache_security(struct cachefiles_cache *cache, | 83 | int cachefiles_determine_cache_security(struct cachefiles_cache *cache, |
82 | struct dentry *root, | 84 | struct dentry *root, |
@@ -99,6 +101,8 @@ int cachefiles_determine_cache_security(struct cachefiles_cache *cache, | |||
99 | * which create files */ | 101 | * which create files */ |
100 | ret = set_create_files_as(new, root->d_inode); | 102 | ret = set_create_files_as(new, root->d_inode); |
101 | if (ret < 0) { | 103 | if (ret < 0) { |
104 | abort_creds(new); | ||
105 | cachefiles_begin_secure(cache, _saved_cred); | ||
102 | _leave(" = %d [cfa]", ret); | 106 | _leave(" = %d [cfa]", ret); |
103 | return ret; | 107 | return ret; |
104 | } | 108 | } |
diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index f3e7a0bf068b..e18b183b47e1 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/fsnotify.h> | 16 | #include <linux/fsnotify.h> |
17 | #include <linux/quotaops.h> | 17 | #include <linux/quotaops.h> |
18 | #include <linux/xattr.h> | 18 | #include <linux/xattr.h> |
19 | #include <linux/slab.h> | ||
19 | #include "internal.h" | 20 | #include "internal.h" |
20 | 21 | ||
21 | static const char cachefiles_xattr_cache[] = | 22 | static const char cachefiles_xattr_cache[] = |