diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-02-28 05:29:16 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-02-28 05:29:16 -0300 |
commit | 844e3cded9c8665e95b1e43b707a6c3adcbc901f (patch) | |
tree | dd9cccb325c949319a9de3e0cabad91d6261fa75 /fs/aufs | |
parent | 6d461a4fe7896faa1aec5a5417888cf179e46b9f (diff) |
Linux-libre 4.4.3-gnu
Diffstat (limited to 'fs/aufs')
-rw-r--r-- | fs/aufs/cpup.c | 66 | ||||
-rw-r--r-- | fs/aufs/dir.c | 5 | ||||
-rw-r--r-- | fs/aufs/export.c | 2 | ||||
-rw-r--r-- | fs/aufs/f_op.c | 16 | ||||
-rw-r--r-- | fs/aufs/fstype.h | 1 | ||||
-rw-r--r-- | fs/aufs/i_op.c | 6 | ||||
-rw-r--r-- | fs/aufs/module.c | 2 | ||||
-rw-r--r-- | fs/aufs/module.h | 1 | ||||
-rw-r--r-- | fs/aufs/posix_acl.c | 1 | ||||
-rw-r--r-- | fs/aufs/vfsub.c | 18 | ||||
-rw-r--r-- | fs/aufs/vfsub.h | 21 |
11 files changed, 120 insertions, 19 deletions
diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c index a34648874..d34a6d283 100644 --- a/fs/aufs/cpup.c +++ b/fs/aufs/cpup.c @@ -512,6 +512,55 @@ out: return err; } +/* + * regardless 'acl' option, reset all ACL. + * All ACL will be copied up later from the original entry on the lower branch. + */ +static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode) +{ + int err; + struct dentry *h_dentry; + struct inode *h_inode; + + h_dentry = h_path->dentry; + h_inode = d_inode(h_dentry); + /* forget_all_cached_acls(h_inode)); */ + err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); + AuTraceErr(err); + if (!err) + err = vfsub_acl_chmod(h_inode, mode); + + AuTraceErr(err); + return err; +} + +static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent, + struct inode *h_dir, struct path *h_path) +{ + int err; + struct inode *dir, *inode; + + err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); + AuTraceErr(err); + if (err == -EOPNOTSUPP) + err = 0; + if (unlikely(err)) + goto out; + + /* + * strange behaviour from the users view, + * particularry setattr case + */ + dir = d_inode(dst_parent); + if (au_ibstart(dir) == cpg->bdst) + au_cpup_attr_nlink(dir, /*force*/1); + inode = d_inode(cpg->dentry); + au_cpup_attr_nlink(inode, /*force*/1); + +out: + return err; +} + static noinline_for_stack int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, struct au_cpup_reg_attr *h_src_attr) @@ -524,7 +573,7 @@ int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, struct au_dtime dt; struct path h_path; struct dentry *h_src, *h_dst, *h_parent; - struct inode *h_inode, *h_dir, *dir, *inode; + struct inode *h_inode, *h_dir; struct super_block *sb; /* bsrc branch can be ro/rw. */ @@ -564,17 +613,8 @@ int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, case S_IFDIR: isdir = 1; err = vfsub_mkdir(h_dir, &h_path, mode); - if (!err) { - /* - * strange behaviour from the users view, - * particularry setattr case - */ - dir = d_inode(dst_parent); - if (au_ibstart(dir) == cpg->bdst) - au_cpup_attr_nlink(dir, /*force*/1); - inode = d_inode(cpg->dentry); - au_cpup_attr_nlink(inode, /*force*/1); - } + if (!err) + err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path); break; case S_IFLNK: err = au_do_cpup_symlink(&h_path, h_src, h_dir); @@ -591,6 +631,8 @@ int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, AuIOErr("Unknown inode type 0%o\n", mode); err = -EIO; } + if (!err) + err = au_reset_acl(h_dir, &h_path, mode); mnt_flags = au_mntflags(sb); if (!au_opt_test(mnt_flags, UDBA_NONE) diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c index 8a619062a..a994e0862 100644 --- a/fs/aufs/dir.c +++ b/fs/aufs/dir.c @@ -237,11 +237,13 @@ static int do_open_dir(struct file *file, int flags, struct file *h_file) int err; aufs_bindex_t bindex, btail; struct dentry *dentry, *h_dentry; + struct vfsmount *mnt; FiMustWriteLock(file); AuDebugOn(h_file); err = 0; + mnt = file->f_path.mnt; dentry = file->f_path.dentry; file->f_version = d_inode(dentry)->i_version; bindex = au_dbstart(dentry); @@ -253,6 +255,9 @@ static int do_open_dir(struct file *file, int flags, struct file *h_file) if (!h_dentry) continue; + err = vfsub_test_mntns(mnt, h_dentry->d_sb); + if (unlikely(err)) + break; h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); if (IS_ERR(h_file)) { err = PTR_ERR(h_file); diff --git a/fs/aufs/export.c b/fs/aufs/export.c index 4ce7732b7..7f6fec61f 100644 --- a/fs/aufs/export.c +++ b/fs/aufs/export.c @@ -597,7 +597,7 @@ aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, ino = decode_ino(fh + Fh_ino); /* it should never happen */ if (unlikely(ino == AUFS_ROOT_INO)) - goto out; + goto out_unlock; dir_ino = decode_ino(fh + Fh_dir_ino); dentry = decode_by_ino(sb, ino, dir_ino); diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c index c1be75cb0..2baacd7a6 100644 --- a/fs/aufs/f_op.c +++ b/fs/aufs/f_op.c @@ -16,7 +16,7 @@ int au_do_open_nondir(struct file *file, int flags, struct file *h_file) { int err; aufs_bindex_t bindex; - struct dentry *dentry; + struct dentry *dentry, *h_dentry; struct au_finfo *finfo; struct inode *h_inode; @@ -29,10 +29,19 @@ int au_do_open_nondir(struct file *file, int flags, struct file *h_file) memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); atomic_set(&finfo->fi_mmapped, 0); bindex = au_dbstart(dentry); - if (!h_file) + if (!h_file) { + h_dentry = au_h_dptr(dentry, bindex); + err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); + if (unlikely(err)) + goto out; h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); - else + } else { + h_dentry = h_file->f_path.dentry; + err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); + if (unlikely(err)) + goto out; get_file(h_file); + } if (IS_ERR(h_file)) err = PTR_ERR(h_file); else { @@ -50,6 +59,7 @@ int au_do_open_nondir(struct file *file, int flags, struct file *h_file) /* file->f_ra = h_file->f_ra; */ } +out: return err; } diff --git a/fs/aufs/fstype.h b/fs/aufs/fstype.h index e429a8b17..725b2ffff 100644 --- a/fs/aufs/fstype.h +++ b/fs/aufs/fstype.h @@ -240,7 +240,6 @@ static inline int au_test_hfsplus(struct super_block *sb __maybe_unused) static inline int au_test_fs_unsuppoted(struct super_block *sb) { return - au_test_fuse(sb) || /* for a security reason, temporarily */ #ifndef CONFIG_AUFS_BR_RAMFS au_test_ramfs(sb) || #endif diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c index 1c634bab9..6e50526d8 100644 --- a/fs/aufs/i_op.c +++ b/fs/aufs/i_op.c @@ -963,6 +963,12 @@ static int aufs_setattr(struct dentry *dentry, struct iattr *ia) break; } } + /* + * regardless aufs 'acl' option setting. + * why don't all acl-aware fs call this func from their ->setattr()? + */ + if (!err && (ia->ia_valid & ATTR_MODE)) + err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); if (!err) au_cpup_attr_changeable(inode); diff --git a/fs/aufs/module.c b/fs/aufs/module.c index ec12f2e66..8a28377c5 100644 --- a/fs/aufs/module.c +++ b/fs/aufs/module.c @@ -95,7 +95,7 @@ MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN"); module_param_named(brs, sysaufs_brs, int, S_IRUGO); /* this module parameter has no meaning when USER_NS is disabled */ -static bool au_userns; +bool au_userns; MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns"); module_param_named(allow_userns, au_userns, bool, S_IRUGO); diff --git a/fs/aufs/module.h b/fs/aufs/module.h index b129ad4b6..bb8644730 100644 --- a/fs/aufs/module.h +++ b/fs/aufs/module.h @@ -18,6 +18,7 @@ struct seq_file; /* module parameters */ extern int sysaufs_brs; +extern bool au_userns; /* ---------------------------------------------------------------------- */ diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c index 1c19e629b..a3c442c08 100644 --- a/fs/aufs/posix_acl.c +++ b/fs/aufs/posix_acl.c @@ -7,7 +7,6 @@ */ #include <linux/fs.h> -#include <linux/posix_acl.h> #include "aufs.h" struct posix_acl *aufs_get_acl(struct inode *inode, int type) diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c index f072c59c0..89f999c97 100644 --- a/fs/aufs/vfsub.c +++ b/fs/aufs/vfsub.c @@ -7,10 +7,28 @@ */ #include <linux/namei.h> +#include <linux/nsproxy.h> #include <linux/security.h> #include <linux/splice.h> +#include "../fs/mount.h" #include "aufs.h" +#ifdef CONFIG_AUFS_BR_FUSE +int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb) +{ + struct nsproxy *ns; + + if (!au_test_fuse(h_sb) || !au_userns) + return 0; + + ns = current->nsproxy; + /* no {get,put}_nsproxy(ns) */ + return real_mount(mnt)->mnt_ns == ns->mnt_ns ? 0 : -EACCES; +} +#endif + +/* ---------------------------------------------------------------------- */ + int vfsub_update_h_iattr(struct path *h_path, int *did) { int err; diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h index a7d8a1cf9..f2e1c49af 100644 --- a/fs/aufs/vfsub.h +++ b/fs/aufs/vfsub.h @@ -13,6 +13,7 @@ #include <linux/fs.h> #include <linux/mount.h> +#include <linux/posix_acl.h> #include <linux/xattr.h> #include "debug.h" @@ -63,6 +64,12 @@ static inline int vfsub_native_ro(struct inode *inode) || IS_IMMUTABLE(inode); } +#ifdef CONFIG_AUFS_BR_FUSE +int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb); +#else +AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); +#endif + /* ---------------------------------------------------------------------- */ int vfsub_update_h_iattr(struct path *h_path, int *did); @@ -202,6 +209,20 @@ static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts, /* no vfsub_update_h_iattr() since we don't have struct path */ } +#ifdef CONFIG_FS_POSIX_ACL +static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) +{ + int err; + + err = posix_acl_chmod(h_inode, h_mode); + if (err == -EOPNOTSUPP) + err = 0; + return err; +} +#else +AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); +#endif + long vfsub_splice_to(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); |