summaryrefslogtreecommitdiff
path: root/fs/aufs
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-02-28 05:29:16 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-02-28 05:29:16 -0300
commit844e3cded9c8665e95b1e43b707a6c3adcbc901f (patch)
treedd9cccb325c949319a9de3e0cabad91d6261fa75 /fs/aufs
parent6d461a4fe7896faa1aec5a5417888cf179e46b9f (diff)
Linux-libre 4.4.3-gnu
Diffstat (limited to 'fs/aufs')
-rw-r--r--fs/aufs/cpup.c66
-rw-r--r--fs/aufs/dir.c5
-rw-r--r--fs/aufs/export.c2
-rw-r--r--fs/aufs/f_op.c16
-rw-r--r--fs/aufs/fstype.h1
-rw-r--r--fs/aufs/i_op.c6
-rw-r--r--fs/aufs/module.c2
-rw-r--r--fs/aufs/module.h1
-rw-r--r--fs/aufs/posix_acl.c1
-rw-r--r--fs/aufs/vfsub.c18
-rw-r--r--fs/aufs/vfsub.h21
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);