CacheFiles: Add calls to path-based security hooks
authorDavid Howells <dhowells@redhat.com>
Fri, 24 Dec 2010 14:48:35 +0000 (14:48 +0000)
committerJames Morris <jmorris@namei.org>
Sun, 23 Jan 2011 23:49:45 +0000 (10:49 +1100)
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>
fs/cachefiles/namei.c
security/security.c

index 42c7fafc8bfeff5d33e8ccf36a039323f851d12f..a0358c2189cb5aba26de002d93727dedd5b7a3fe 100644 (file)
@@ -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;
index 739e40362f44fab2a8fa4a0f4b1310ec14f8bb65..b84a89dd59c6d3a7360b0e9480dcae3e13b9367f 100644 (file)
@@ -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)
 {