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>
This commit is contained in:
parent
ced3b93018
commit
821404434f
|
@ -275,6 +275,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
||||||
bool preemptive)
|
bool preemptive)
|
||||||
{
|
{
|
||||||
struct dentry *grave, *trap;
|
struct dentry *grave, *trap;
|
||||||
|
struct path path, path_to_graveyard;
|
||||||
char nbuffer[8 + 8 + 1];
|
char nbuffer[8 + 8 + 1];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -287,10 +288,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
||||||
/* non-directories can just be unlinked */
|
/* non-directories can just be unlinked */
|
||||||
if (!S_ISDIR(rep->d_inode->i_mode)) {
|
if (!S_ISDIR(rep->d_inode->i_mode)) {
|
||||||
_debug("unlink stale object");
|
_debug("unlink stale object");
|
||||||
ret = vfs_unlink(dir->d_inode, rep);
|
|
||||||
|
|
||||||
if (preemptive)
|
path.mnt = cache->mnt;
|
||||||
cachefiles_mark_object_buried(cache, rep);
|
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);
|
mutex_unlock(&dir->d_inode->i_mutex);
|
||||||
|
|
||||||
|
@ -379,12 +388,23 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* attempt the rename */
|
/* attempt the rename */
|
||||||
ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave);
|
path.mnt = cache->mnt;
|
||||||
if (ret != 0 && ret != -ENOMEM)
|
path.dentry = dir;
|
||||||
cachefiles_io_error(cache, "Rename failed with error %d", ret);
|
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)
|
if (preemptive)
|
||||||
cachefiles_mark_object_buried(cache, rep);
|
cachefiles_mark_object_buried(cache, rep);
|
||||||
|
}
|
||||||
|
|
||||||
unlock_rename(cache->graveyard, dir);
|
unlock_rename(cache->graveyard, dir);
|
||||||
dput(grave);
|
dput(grave);
|
||||||
|
@ -448,6 +468,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
|
||||||
{
|
{
|
||||||
struct cachefiles_cache *cache;
|
struct cachefiles_cache *cache;
|
||||||
struct dentry *dir, *next = NULL;
|
struct dentry *dir, *next = NULL;
|
||||||
|
struct path path;
|
||||||
unsigned long start;
|
unsigned long start;
|
||||||
const char *name;
|
const char *name;
|
||||||
int ret, nlen;
|
int ret, nlen;
|
||||||
|
@ -458,6 +479,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
|
||||||
|
|
||||||
cache = container_of(parent->fscache.cache,
|
cache = container_of(parent->fscache.cache,
|
||||||
struct cachefiles_cache, cache);
|
struct cachefiles_cache, cache);
|
||||||
|
path.mnt = cache->mnt;
|
||||||
|
|
||||||
ASSERT(parent->dentry);
|
ASSERT(parent->dentry);
|
||||||
ASSERT(parent->dentry->d_inode);
|
ASSERT(parent->dentry->d_inode);
|
||||||
|
@ -511,6 +533,10 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto create_error;
|
goto create_error;
|
||||||
|
|
||||||
|
path.dentry = dir;
|
||||||
|
ret = security_path_mkdir(&path, next, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto create_error;
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
ret = vfs_mkdir(dir->d_inode, next, 0);
|
ret = vfs_mkdir(dir->d_inode, next, 0);
|
||||||
cachefiles_hist(cachefiles_mkdir_histogram, start);
|
cachefiles_hist(cachefiles_mkdir_histogram, start);
|
||||||
|
@ -536,6 +562,10 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto create_error;
|
goto create_error;
|
||||||
|
|
||||||
|
path.dentry = dir;
|
||||||
|
ret = security_path_mknod(&path, next, S_IFREG, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto create_error;
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
ret = vfs_create(dir->d_inode, next, S_IFREG, NULL);
|
ret = vfs_create(dir->d_inode, next, S_IFREG, NULL);
|
||||||
cachefiles_hist(cachefiles_create_histogram, start);
|
cachefiles_hist(cachefiles_create_histogram, start);
|
||||||
|
@ -692,6 +722,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
{
|
{
|
||||||
struct dentry *subdir;
|
struct dentry *subdir;
|
||||||
unsigned long start;
|
unsigned long start;
|
||||||
|
struct path path;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_enter(",,%s", dirname);
|
_enter(",,%s", dirname);
|
||||||
|
@ -719,6 +750,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
|
|
||||||
_debug("attempt mkdir");
|
_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);
|
ret = vfs_mkdir(dir->d_inode, subdir, 0700);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto mkdir_error;
|
goto mkdir_error;
|
||||||
|
|
|
@ -360,6 +360,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
|
||||||
return 0;
|
return 0;
|
||||||
return security_ops->path_mkdir(dir, dentry, mode);
|
return security_ops->path_mkdir(dir, dentry, mode);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(security_path_mkdir);
|
||||||
|
|
||||||
int security_path_rmdir(struct path *dir, struct dentry *dentry)
|
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 0;
|
||||||
return security_ops->path_unlink(dir, dentry);
|
return security_ops->path_unlink(dir, dentry);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(security_path_unlink);
|
||||||
|
|
||||||
int security_path_symlink(struct path *dir, struct dentry *dentry,
|
int security_path_symlink(struct path *dir, struct dentry *dentry,
|
||||||
const char *old_name)
|
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,
|
return security_ops->path_rename(old_dir, old_dentry, new_dir,
|
||||||
new_dentry);
|
new_dentry);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(security_path_rename);
|
||||||
|
|
||||||
int security_path_truncate(struct path *path)
|
int security_path_truncate(struct path *path)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user