Commit 821404434f3324bf23f545050ff64055a149766e
Committed by
James Morris
1 parent
ced3b93018
Exists in
master
and in
4 other branches
CacheFiles: Add calls to path-based security hooks
Add calls to path-based security hooks into CacheFiles as, unlike inode-based security, these aren't implicit in the vfs_mkdir() and similar calls. Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Showing 2 changed files with 47 additions and 8 deletions Side-by-side Diff
fs/cachefiles/namei.c
... | ... | @@ -275,6 +275,7 @@ |
275 | 275 | bool preemptive) |
276 | 276 | { |
277 | 277 | struct dentry *grave, *trap; |
278 | + struct path path, path_to_graveyard; | |
278 | 279 | char nbuffer[8 + 8 + 1]; |
279 | 280 | int ret; |
280 | 281 | |
281 | 282 | |
282 | 283 | |
... | ... | @@ -287,11 +288,19 @@ |
287 | 288 | /* non-directories can just be unlinked */ |
288 | 289 | if (!S_ISDIR(rep->d_inode->i_mode)) { |
289 | 290 | _debug("unlink stale object"); |
290 | - ret = vfs_unlink(dir->d_inode, rep); | |
291 | 291 | |
292 | - if (preemptive) | |
293 | - cachefiles_mark_object_buried(cache, rep); | |
292 | + path.mnt = cache->mnt; | |
293 | + path.dentry = dir; | |
294 | + ret = security_path_unlink(&path, rep); | |
295 | + if (ret < 0) { | |
296 | + cachefiles_io_error(cache, "Unlink security error"); | |
297 | + } else { | |
298 | + ret = vfs_unlink(dir->d_inode, rep); | |
294 | 299 | |
300 | + if (preemptive) | |
301 | + cachefiles_mark_object_buried(cache, rep); | |
302 | + } | |
303 | + | |
295 | 304 | mutex_unlock(&dir->d_inode->i_mutex); |
296 | 305 | |
297 | 306 | if (ret == -EIO) |
298 | 307 | |
... | ... | @@ -379,12 +388,23 @@ |
379 | 388 | } |
380 | 389 | |
381 | 390 | /* attempt the rename */ |
382 | - ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave); | |
383 | - if (ret != 0 && ret != -ENOMEM) | |
384 | - cachefiles_io_error(cache, "Rename failed with error %d", ret); | |
391 | + path.mnt = cache->mnt; | |
392 | + path.dentry = dir; | |
393 | + path_to_graveyard.mnt = cache->mnt; | |
394 | + path_to_graveyard.dentry = cache->graveyard; | |
395 | + ret = security_path_rename(&path, rep, &path_to_graveyard, grave); | |
396 | + if (ret < 0) { | |
397 | + cachefiles_io_error(cache, "Rename security error %d", ret); | |
398 | + } else { | |
399 | + ret = vfs_rename(dir->d_inode, rep, | |
400 | + cache->graveyard->d_inode, grave); | |
401 | + if (ret != 0 && ret != -ENOMEM) | |
402 | + cachefiles_io_error(cache, | |
403 | + "Rename failed with error %d", ret); | |
385 | 404 | |
386 | - if (preemptive) | |
387 | - cachefiles_mark_object_buried(cache, rep); | |
405 | + if (preemptive) | |
406 | + cachefiles_mark_object_buried(cache, rep); | |
407 | + } | |
388 | 408 | |
389 | 409 | unlock_rename(cache->graveyard, dir); |
390 | 410 | dput(grave); |
... | ... | @@ -448,6 +468,7 @@ |
448 | 468 | { |
449 | 469 | struct cachefiles_cache *cache; |
450 | 470 | struct dentry *dir, *next = NULL; |
471 | + struct path path; | |
451 | 472 | unsigned long start; |
452 | 473 | const char *name; |
453 | 474 | int ret, nlen; |
... | ... | @@ -458,6 +479,7 @@ |
458 | 479 | |
459 | 480 | cache = container_of(parent->fscache.cache, |
460 | 481 | struct cachefiles_cache, cache); |
482 | + path.mnt = cache->mnt; | |
461 | 483 | |
462 | 484 | ASSERT(parent->dentry); |
463 | 485 | ASSERT(parent->dentry->d_inode); |
... | ... | @@ -511,6 +533,10 @@ |
511 | 533 | if (ret < 0) |
512 | 534 | goto create_error; |
513 | 535 | |
536 | + path.dentry = dir; | |
537 | + ret = security_path_mkdir(&path, next, 0); | |
538 | + if (ret < 0) | |
539 | + goto create_error; | |
514 | 540 | start = jiffies; |
515 | 541 | ret = vfs_mkdir(dir->d_inode, next, 0); |
516 | 542 | cachefiles_hist(cachefiles_mkdir_histogram, start); |
... | ... | @@ -536,6 +562,10 @@ |
536 | 562 | if (ret < 0) |
537 | 563 | goto create_error; |
538 | 564 | |
565 | + path.dentry = dir; | |
566 | + ret = security_path_mknod(&path, next, S_IFREG, 0); | |
567 | + if (ret < 0) | |
568 | + goto create_error; | |
539 | 569 | start = jiffies; |
540 | 570 | ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); |
541 | 571 | cachefiles_hist(cachefiles_create_histogram, start); |
... | ... | @@ -692,6 +722,7 @@ |
692 | 722 | { |
693 | 723 | struct dentry *subdir; |
694 | 724 | unsigned long start; |
725 | + struct path path; | |
695 | 726 | int ret; |
696 | 727 | |
697 | 728 | _enter(",,%s", dirname); |
... | ... | @@ -719,6 +750,11 @@ |
719 | 750 | |
720 | 751 | _debug("attempt mkdir"); |
721 | 752 | |
753 | + path.mnt = cache->mnt; | |
754 | + path.dentry = dir; | |
755 | + ret = security_path_mkdir(&path, subdir, 0700); | |
756 | + if (ret < 0) | |
757 | + goto mkdir_error; | |
722 | 758 | ret = vfs_mkdir(dir->d_inode, subdir, 0700); |
723 | 759 | if (ret < 0) |
724 | 760 | goto mkdir_error; |
security/security.c
... | ... | @@ -360,6 +360,7 @@ |
360 | 360 | return 0; |
361 | 361 | return security_ops->path_mkdir(dir, dentry, mode); |
362 | 362 | } |
363 | +EXPORT_SYMBOL(security_path_mkdir); | |
363 | 364 | |
364 | 365 | int security_path_rmdir(struct path *dir, struct dentry *dentry) |
365 | 366 | { |
... | ... | @@ -374,6 +375,7 @@ |
374 | 375 | return 0; |
375 | 376 | return security_ops->path_unlink(dir, dentry); |
376 | 377 | } |
378 | +EXPORT_SYMBOL(security_path_unlink); | |
377 | 379 | |
378 | 380 | int security_path_symlink(struct path *dir, struct dentry *dentry, |
379 | 381 | const char *old_name) |
... | ... | @@ -400,6 +402,7 @@ |
400 | 402 | return security_ops->path_rename(old_dir, old_dentry, new_dir, |
401 | 403 | new_dentry); |
402 | 404 | } |
405 | +EXPORT_SYMBOL(security_path_rename); | |
403 | 406 | |
404 | 407 | int security_path_truncate(struct path *path) |
405 | 408 | { |