diff options
author | David Howells <dhowells@redhat.com> | 2010-12-24 14:48:35 +0000 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-01-24 10:49:45 +1100 |
commit | 821404434f3324bf23f545050ff64055a149766e (patch) | |
tree | 619847c1b4c101da7eddee2cc920af329829847f | |
parent | ced3b93018a9633447ddeb12a96f25e08154cbe7 (diff) |
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>
-rw-r--r-- | fs/cachefiles/namei.c | 52 | ||||
-rw-r--r-- | security/security.c | 3 |
2 files changed, 47 insertions, 8 deletions
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 42c7fafc8bfe..a0358c2189cb 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -275,6 +275,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, bool preemptive) { struct dentry *grave, *trap; + struct path path, path_to_graveyard; char nbuffer[8 + 8 + 1]; int ret; @@ -287,10 +288,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, /* non-directories can just be unlinked */ if (!S_ISDIR(rep->d_inode->i_mode)) { _debug("unlink stale object"); - ret = vfs_unlink(dir->d_inode, rep); - if (preemptive) - cachefiles_mark_object_buried(cache, rep); + path.mnt = cache->mnt; + path.dentry = dir; + ret = security_path_unlink(&path, rep); + if (ret < 0) { + cachefiles_io_error(cache, "Unlink security error"); + } else { + ret = vfs_unlink(dir->d_inode, rep); + + if (preemptive) + cachefiles_mark_object_buried(cache, rep); + } mutex_unlock(&dir->d_inode->i_mutex); @@ -379,12 +388,23 @@ try_again: } /* attempt the rename */ - ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave); - if (ret != 0 && ret != -ENOMEM) - cachefiles_io_error(cache, "Rename failed with error %d", ret); + path.mnt = cache->mnt; + path.dentry = dir; + path_to_graveyard.mnt = cache->mnt; + path_to_graveyard.dentry = cache->graveyard; + ret = security_path_rename(&path, rep, &path_to_graveyard, grave); + if (ret < 0) { + cachefiles_io_error(cache, "Rename security error %d", ret); + } else { + ret = vfs_rename(dir->d_inode, rep, + cache->graveyard->d_inode, grave); + if (ret != 0 && ret != -ENOMEM) + cachefiles_io_error(cache, + "Rename failed with error %d", ret); - if (preemptive) - cachefiles_mark_object_buried(cache, rep); + if (preemptive) + cachefiles_mark_object_buried(cache, rep); + } unlock_rename(cache->graveyard, dir); dput(grave); @@ -448,6 +468,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, { struct cachefiles_cache *cache; struct dentry *dir, *next = NULL; + struct path path; unsigned long start; const char *name; int ret, nlen; @@ -458,6 +479,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, cache = container_of(parent->fscache.cache, struct cachefiles_cache, cache); + path.mnt = cache->mnt; ASSERT(parent->dentry); ASSERT(parent->dentry->d_inode); @@ -511,6 +533,10 @@ lookup_again: if (ret < 0) goto create_error; + path.dentry = dir; + ret = security_path_mkdir(&path, next, 0); + if (ret < 0) + goto create_error; start = jiffies; ret = vfs_mkdir(dir->d_inode, next, 0); cachefiles_hist(cachefiles_mkdir_histogram, start); @@ -536,6 +562,10 @@ lookup_again: if (ret < 0) goto create_error; + path.dentry = dir; + ret = security_path_mknod(&path, next, S_IFREG, 0); + if (ret < 0) + goto create_error; start = jiffies; ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); cachefiles_hist(cachefiles_create_histogram, start); @@ -692,6 +722,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, { struct dentry *subdir; unsigned long start; + struct path path; int ret; _enter(",,%s", dirname); @@ -719,6 +750,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, _debug("attempt mkdir"); + path.mnt = cache->mnt; + path.dentry = dir; + ret = security_path_mkdir(&path, subdir, 0700); + if (ret < 0) + goto mkdir_error; ret = vfs_mkdir(dir->d_inode, subdir, 0700); if (ret < 0) goto mkdir_error; diff --git a/security/security.c b/security/security.c index 739e40362f44..b84a89dd59c6 100644 --- a/security/security.c +++ b/security/security.c @@ -360,6 +360,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode) return 0; return security_ops->path_mkdir(dir, dentry, mode); } +EXPORT_SYMBOL(security_path_mkdir); int security_path_rmdir(struct path *dir, struct dentry *dentry) { @@ -374,6 +375,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry) return 0; return security_ops->path_unlink(dir, dentry); } +EXPORT_SYMBOL(security_path_unlink); int security_path_symlink(struct path *dir, struct dentry *dentry, const char *old_name) @@ -400,6 +402,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry, return security_ops->path_rename(old_dir, old_dentry, new_dir, new_dentry); } +EXPORT_SYMBOL(security_path_rename); int security_path_truncate(struct path *path) { |