Commit 66dbfabf authored by Miklos Szeredi's avatar Miklos Szeredi

ovl: stack fileattr ops

Add stacking for the fileattr operations.

Add hack for calling security_file_ioctl() for now.  Probably better to
have a pair of specific hooks for these operations.
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 97e2dee9
...@@ -1301,4 +1301,6 @@ const struct inode_operations ovl_dir_inode_operations = { ...@@ -1301,4 +1301,6 @@ const struct inode_operations ovl_dir_inode_operations = {
.listxattr = ovl_listxattr, .listxattr = ovl_listxattr,
.get_acl = ovl_get_acl, .get_acl = ovl_get_acl,
.update_time = ovl_update_time, .update_time = ovl_update_time,
.fileattr_get = ovl_fileattr_get,
.fileattr_set = ovl_fileattr_set,
}; };
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <linux/posix_acl.h> #include <linux/posix_acl.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/fiemap.h> #include <linux/fiemap.h>
#include <linux/fileattr.h>
#include <linux/security.h>
#include "overlayfs.h" #include "overlayfs.h"
...@@ -500,6 +502,79 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, ...@@ -500,6 +502,79 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
return err; return err;
} }
/*
* Work around the fact that security_file_ioctl() takes a file argument.
* Introducing security_inode_fileattr_get/set() hooks would solve this issue
* properly.
*/
static int ovl_security_fileattr(struct dentry *dentry, struct fileattr *fa,
bool set)
{
struct path realpath;
struct file *file;
unsigned int cmd;
int err;
ovl_path_real(dentry, &realpath);
file = dentry_open(&realpath, O_RDONLY, current_cred());
if (IS_ERR(file))
return PTR_ERR(file);
if (set)
cmd = fa->fsx_valid ? FS_IOC_FSSETXATTR : FS_IOC_SETFLAGS;
else
cmd = fa->fsx_valid ? FS_IOC_FSGETXATTR : FS_IOC_GETFLAGS;
err = security_file_ioctl(file, cmd, 0);
fput(file);
return err;
}
int ovl_fileattr_set(struct user_namespace *mnt_userns,
struct dentry *dentry, struct fileattr *fa)
{
struct inode *inode = d_inode(dentry);
struct dentry *upperdentry;
const struct cred *old_cred;
int err;
err = ovl_want_write(dentry);
if (err)
goto out;
err = ovl_copy_up(dentry);
if (!err) {
upperdentry = ovl_dentry_upper(dentry);
old_cred = ovl_override_creds(inode->i_sb);
err = ovl_security_fileattr(dentry, fa, true);
if (!err)
err = vfs_fileattr_set(&init_user_ns, upperdentry, fa);
revert_creds(old_cred);
ovl_copyflags(ovl_inode_real(inode), inode);
}
ovl_drop_write(dentry);
out:
return err;
}
int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa)
{
struct inode *inode = d_inode(dentry);
struct dentry *realdentry = ovl_dentry_real(dentry);
const struct cred *old_cred;
int err;
old_cred = ovl_override_creds(inode->i_sb);
err = ovl_security_fileattr(dentry, fa, false);
if (!err)
err = vfs_fileattr_get(realdentry, fa);
revert_creds(old_cred);
return err;
}
static const struct inode_operations ovl_file_inode_operations = { static const struct inode_operations ovl_file_inode_operations = {
.setattr = ovl_setattr, .setattr = ovl_setattr,
.permission = ovl_permission, .permission = ovl_permission,
...@@ -508,6 +583,8 @@ static const struct inode_operations ovl_file_inode_operations = { ...@@ -508,6 +583,8 @@ static const struct inode_operations ovl_file_inode_operations = {
.get_acl = ovl_get_acl, .get_acl = ovl_get_acl,
.update_time = ovl_update_time, .update_time = ovl_update_time,
.fiemap = ovl_fiemap, .fiemap = ovl_fiemap,
.fileattr_get = ovl_fileattr_get,
.fileattr_set = ovl_fileattr_set,
}; };
static const struct inode_operations ovl_symlink_inode_operations = { static const struct inode_operations ovl_symlink_inode_operations = {
......
...@@ -521,6 +521,9 @@ int __init ovl_aio_request_cache_init(void); ...@@ -521,6 +521,9 @@ int __init ovl_aio_request_cache_init(void);
void ovl_aio_request_cache_destroy(void); void ovl_aio_request_cache_destroy(void);
long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg); long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
long ovl_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); long ovl_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa);
int ovl_fileattr_set(struct user_namespace *mnt_userns,
struct dentry *dentry, struct fileattr *fa);
/* copy_up.c */ /* copy_up.c */
int ovl_copy_up(struct dentry *dentry); int ovl_copy_up(struct dentry *dentry);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment