ovl: Revert changes in 4.1.5-1 due to regression (Reopens: #786925)
In particular, "fix a braino in ovl_d_select_inode()" introduced a type error and potential crash because we still have ovl_dentry_open() not ovl_d_select_inode(). Doing this properly requires an ABI change.
This commit is contained in:
parent
006ca00729
commit
ee3a08efd5
|
@ -53,6 +53,7 @@ linux (4.1.6-1) UNRELEASED; urgency=medium
|
||||||
* [i386] udeb: Make gpio_keys_polled and leds-gpio optional in input-modules
|
* [i386] udeb: Make gpio_keys_polled and leds-gpio optional in input-modules
|
||||||
as they are not built for the 686-pae flavour (fixes FTBFS)
|
as they are not built for the 686-pae flavour (fixes FTBFS)
|
||||||
* perf: Fix AUX buffer refcounting
|
* perf: Fix AUX buffer refcounting
|
||||||
|
* ovl: Revert changes in 4.1.5-1 due to regression (Reopens: #786925)
|
||||||
|
|
||||||
-- Aurelien Jarno <aurel32@debian.org> Tue, 18 Aug 2015 11:35:05 +0200
|
-- Aurelien Jarno <aurel32@debian.org> Tue, 18 Aug 2015 11:35:05 +0200
|
||||||
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
From: Miklos Szeredi <mszeredi@suse.cz>
|
|
||||||
Date: Mon, 22 Jun 2015 13:53:48 +0200
|
|
||||||
Subject: ovl: don't traverse automount points
|
|
||||||
Origin: https://git.kernel.org/linus/a6f15d9a756571babbb2b2cd4fdd1b64a5de232b
|
|
||||||
Bug-Debian: https://bugs.debian.org/786925
|
|
||||||
|
|
||||||
NFS and other distributed filesystems may place automount points in the
|
|
||||||
tree. Previoulsy overlayfs refused to mount such filesystems types (based
|
|
||||||
on the existence of the .d_automount callback), even if the actual export
|
|
||||||
didn't have any automount points.
|
|
||||||
|
|
||||||
It cannot be determined in advance whether the filesystem has automount
|
|
||||||
points or not. The solution is to allow fs with .d_automount but refuse to
|
|
||||||
traverse any automount points encountered.
|
|
||||||
|
|
||||||
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
|
|
||||||
---
|
|
||||||
fs/overlayfs/super.c | 8 ++++++--
|
|
||||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
|
|
||||||
index bf8537c..de9d2ee 100644
|
|
||||||
--- a/fs/overlayfs/super.c
|
|
||||||
+++ b/fs/overlayfs/super.c
|
|
||||||
@@ -303,6 +303,10 @@ static inline struct dentry *ovl_lookup_real(struct dentry *dir,
|
|
||||||
} else if (!dentry->d_inode) {
|
|
||||||
dput(dentry);
|
|
||||||
dentry = NULL;
|
|
||||||
+ } else if (dentry->d_flags & DCACHE_MANAGED_DENTRY) {
|
|
||||||
+ dput(dentry);
|
|
||||||
+ /* Don't support traversing automounts */
|
|
||||||
+ dentry = ERR_PTR(-EREMOTE);
|
|
||||||
}
|
|
||||||
return dentry;
|
|
||||||
}
|
|
||||||
@@ -700,12 +704,12 @@ static bool ovl_is_allowed_fs_type(struct dentry *root)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't support:
|
|
||||||
- * - automount filesystems
|
|
||||||
+ * - autofs
|
|
||||||
* - filesystems with revalidate (FIXME for lower layer)
|
|
||||||
* - filesystems with case insensitive names
|
|
||||||
*/
|
|
||||||
if (dop &&
|
|
||||||
- (dop->d_manage || dop->d_automount ||
|
|
||||||
+ (dop->d_manage ||
|
|
||||||
dop->d_revalidate || dop->d_weak_revalidate ||
|
|
||||||
dop->d_compare || dop->d_hash)) {
|
|
||||||
return false;
|
|
|
@ -1,28 +0,0 @@
|
||||||
From: Al Viro <viro@zeniv.linux.org.uk>
|
|
||||||
Date: Sun, 12 Jul 2015 10:39:45 -0400
|
|
||||||
Subject: fix a braino in ovl_d_select_inode()
|
|
||||||
Origin: https://git.kernel.org/linus/9391dd00d13c853ab4f2a85435288ae2202e0e43
|
|
||||||
Bug-Debian: https://bugs.debian.org/786925
|
|
||||||
|
|
||||||
when opening a directory we want the overlayfs inode, not one from
|
|
||||||
the topmost layer.
|
|
||||||
|
|
||||||
Reported-By: Andrey Jr. Melnikov <temnota.am@gmail.com>
|
|
||||||
Tested-By: Andrey Jr. Melnikov <temnota.am@gmail.com>
|
|
||||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
|
||||||
---
|
|
||||||
fs/overlayfs/inode.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
--- a/fs/overlayfs/inode.c
|
|
||||||
+++ b/fs/overlayfs/inode.c
|
|
||||||
@@ -344,6 +344,9 @@ static int ovl_dentry_open(struct dentry
|
|
||||||
enum ovl_path_type type;
|
|
||||||
bool want_write = false;
|
|
||||||
|
|
||||||
+ if (d_is_dir(dentry))
|
|
||||||
+ return d_backing_inode(dentry);
|
|
||||||
+
|
|
||||||
type = ovl_path_real(dentry, &realpath);
|
|
||||||
if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) {
|
|
||||||
want_write = true;
|
|
|
@ -1,227 +0,0 @@
|
||||||
From: Miklos Szeredi <mszeredi@suse.cz>
|
|
||||||
Date: Mon, 22 Jun 2015 13:53:48 +0200
|
|
||||||
Subject: ovl: allow distributed fs as lower layer
|
|
||||||
Origin: https://git.kernel.org/linus/7c03b5d45b8eebf0111125053d8fe887cc262ba6
|
|
||||||
Bug-Debian: https://bugs.debian.org/786925
|
|
||||||
|
|
||||||
Allow filesystems with .d_revalidate as lower layer(s), but not as upper
|
|
||||||
layer.
|
|
||||||
|
|
||||||
For local filesystems the rule was that modifications on the layers
|
|
||||||
directly while being part of the overlay results in undefined behavior.
|
|
||||||
|
|
||||||
This can easily be extended to distributed filesystems: we assume the tree
|
|
||||||
used as lower layer is static, which means ->d_revalidate() should always
|
|
||||||
return "1". If that is not the case, return -ESTALE, don't try to work
|
|
||||||
around the modification.
|
|
||||||
|
|
||||||
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
|
|
||||||
---
|
|
||||||
fs/overlayfs/super.c | 113 +++++++++++++++++++++++++++++++++++++++------------
|
|
||||||
1 file changed, 88 insertions(+), 25 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
|
|
||||||
index de9d2ee..8a08c58 100644
|
|
||||||
--- a/fs/overlayfs/super.c
|
|
||||||
+++ b/fs/overlayfs/super.c
|
|
||||||
@@ -273,10 +273,57 @@ static void ovl_dentry_release(struct dentry *dentry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int ovl_dentry_revalidate(struct dentry *dentry, unsigned int flags)
|
|
||||||
+{
|
|
||||||
+ struct ovl_entry *oe = dentry->d_fsdata;
|
|
||||||
+ unsigned int i;
|
|
||||||
+ int ret = 1;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < oe->numlower; i++) {
|
|
||||||
+ struct dentry *d = oe->lowerstack[i].dentry;
|
|
||||||
+
|
|
||||||
+ if (d->d_flags & DCACHE_OP_REVALIDATE) {
|
|
||||||
+ ret = d->d_op->d_revalidate(d, flags);
|
|
||||||
+ if (ret < 0)
|
|
||||||
+ return ret;
|
|
||||||
+ if (!ret) {
|
|
||||||
+ if (!(flags & LOOKUP_RCU))
|
|
||||||
+ d_invalidate(d);
|
|
||||||
+ return -ESTALE;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
|
|
||||||
+{
|
|
||||||
+ struct ovl_entry *oe = dentry->d_fsdata;
|
|
||||||
+ unsigned int i;
|
|
||||||
+ int ret = 1;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < oe->numlower; i++) {
|
|
||||||
+ struct dentry *d = oe->lowerstack[i].dentry;
|
|
||||||
+
|
|
||||||
+ if (d->d_flags & DCACHE_OP_WEAK_REVALIDATE) {
|
|
||||||
+ ret = d->d_op->d_weak_revalidate(d, flags);
|
|
||||||
+ if (ret <= 0)
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static const struct dentry_operations ovl_dentry_operations = {
|
|
||||||
.d_release = ovl_dentry_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
+static const struct dentry_operations ovl_reval_dentry_operations = {
|
|
||||||
+ .d_release = ovl_dentry_release,
|
|
||||||
+ .d_revalidate = ovl_dentry_revalidate,
|
|
||||||
+ .d_weak_revalidate = ovl_dentry_weak_revalidate,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
static struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
|
|
||||||
{
|
|
||||||
size_t size = offsetof(struct ovl_entry, lowerstack[numlower]);
|
|
||||||
@@ -288,6 +335,20 @@ static struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
|
|
||||||
return oe;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static bool ovl_dentry_remote(struct dentry *dentry)
|
|
||||||
+{
|
|
||||||
+ return dentry->d_flags &
|
|
||||||
+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static bool ovl_dentry_weird(struct dentry *dentry)
|
|
||||||
+{
|
|
||||||
+ return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
|
|
||||||
+ DCACHE_MANAGE_TRANSIT |
|
|
||||||
+ DCACHE_OP_HASH |
|
|
||||||
+ DCACHE_OP_COMPARE);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static inline struct dentry *ovl_lookup_real(struct dentry *dir,
|
|
||||||
struct qstr *name)
|
|
||||||
{
|
|
||||||
@@ -303,9 +364,9 @@ static inline struct dentry *ovl_lookup_real(struct dentry *dir,
|
|
||||||
} else if (!dentry->d_inode) {
|
|
||||||
dput(dentry);
|
|
||||||
dentry = NULL;
|
|
||||||
- } else if (dentry->d_flags & DCACHE_MANAGED_DENTRY) {
|
|
||||||
+ } else if (ovl_dentry_weird(dentry)) {
|
|
||||||
dput(dentry);
|
|
||||||
- /* Don't support traversing automounts */
|
|
||||||
+ /* Don't support traversing automounts and other weirdness */
|
|
||||||
dentry = ERR_PTR(-EREMOTE);
|
|
||||||
}
|
|
||||||
return dentry;
|
|
||||||
@@ -354,6 +415,11 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (this) {
|
|
||||||
+ if (unlikely(ovl_dentry_remote(this))) {
|
|
||||||
+ dput(this);
|
|
||||||
+ err = -EREMOTE;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
if (ovl_is_whiteout(this)) {
|
|
||||||
dput(this);
|
|
||||||
this = NULL;
|
|
||||||
@@ -698,25 +764,6 @@ static void ovl_unescape(char *s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-static bool ovl_is_allowed_fs_type(struct dentry *root)
|
|
||||||
-{
|
|
||||||
- const struct dentry_operations *dop = root->d_op;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * We don't support:
|
|
||||||
- * - autofs
|
|
||||||
- * - filesystems with revalidate (FIXME for lower layer)
|
|
||||||
- * - filesystems with case insensitive names
|
|
||||||
- */
|
|
||||||
- if (dop &&
|
|
||||||
- (dop->d_manage ||
|
|
||||||
- dop->d_revalidate || dop->d_weak_revalidate ||
|
|
||||||
- dop->d_compare || dop->d_hash)) {
|
|
||||||
- return false;
|
|
||||||
- }
|
|
||||||
- return true;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int ovl_mount_dir_noesc(const char *name, struct path *path)
|
|
||||||
{
|
|
||||||
int err = -EINVAL;
|
|
||||||
@@ -731,7 +778,7 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
err = -EINVAL;
|
|
||||||
- if (!ovl_is_allowed_fs_type(path->dentry)) {
|
|
||||||
+ if (ovl_dentry_weird(path->dentry)) {
|
|
||||||
pr_err("overlayfs: filesystem on '%s' not supported\n", name);
|
|
||||||
goto out_put;
|
|
||||||
}
|
|
||||||
@@ -755,13 +802,21 @@ static int ovl_mount_dir(const char *name, struct path *path)
|
|
||||||
if (tmp) {
|
|
||||||
ovl_unescape(tmp);
|
|
||||||
err = ovl_mount_dir_noesc(tmp, path);
|
|
||||||
+
|
|
||||||
+ if (!err)
|
|
||||||
+ if (ovl_dentry_remote(path->dentry)) {
|
|
||||||
+ pr_err("overlayfs: filesystem on '%s' not supported as upperdir\n",
|
|
||||||
+ tmp);
|
|
||||||
+ path_put(path);
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ }
|
|
||||||
kfree(tmp);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ovl_lower_dir(const char *name, struct path *path, long *namelen,
|
|
||||||
- int *stack_depth)
|
|
||||||
+ int *stack_depth, bool *remote)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
struct kstatfs statfs;
|
|
||||||
@@ -778,6 +833,9 @@ static int ovl_lower_dir(const char *name, struct path *path, long *namelen,
|
|
||||||
*namelen = max(*namelen, statfs.f_namelen);
|
|
||||||
*stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth);
|
|
||||||
|
|
||||||
+ if (ovl_dentry_remote(path->dentry))
|
|
||||||
+ *remote = true;
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_put:
|
|
||||||
@@ -831,6 +889,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
|
||||||
unsigned int numlower;
|
|
||||||
unsigned int stacklen = 0;
|
|
||||||
unsigned int i;
|
|
||||||
+ bool remote = false;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = -ENOMEM;
|
|
||||||
@@ -904,7 +963,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
|
||||||
lower = lowertmp;
|
|
||||||
for (numlower = 0; numlower < stacklen; numlower++) {
|
|
||||||
err = ovl_lower_dir(lower, &stack[numlower],
|
|
||||||
- &ufs->lower_namelen, &sb->s_stack_depth);
|
|
||||||
+ &ufs->lower_namelen, &sb->s_stack_depth,
|
|
||||||
+ &remote);
|
|
||||||
if (err)
|
|
||||||
goto out_put_lowerpath;
|
|
||||||
|
|
||||||
@@ -962,7 +1022,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
|
||||||
if (!ufs->upper_mnt)
|
|
||||||
sb->s_flags |= MS_RDONLY;
|
|
||||||
|
|
||||||
- sb->s_d_op = &ovl_dentry_operations;
|
|
||||||
+ if (remote)
|
|
||||||
+ sb->s_d_op = &ovl_reval_dentry_operations;
|
|
||||||
+ else
|
|
||||||
+ sb->s_d_op = &ovl_dentry_operations;
|
|
||||||
|
|
||||||
err = -ENOMEM;
|
|
||||||
oe = ovl_alloc_entry(numlower);
|
|
|
@ -87,8 +87,5 @@ features/all/grsecurity/grsecurity-kconfig.patch
|
||||||
#features/all/grsecurity/grsecurity-kbuild.patch
|
#features/all/grsecurity/grsecurity-kbuild.patch
|
||||||
features/all/grsecurity/grkernsec_perf_harden.patch
|
features/all/grsecurity/grkernsec_perf_harden.patch
|
||||||
bugfix/all/virtio-net-drop-netif_f_fraglist.patch
|
bugfix/all/virtio-net-drop-netif_f_fraglist.patch
|
||||||
bugfix/all/-ovl-don-t-traverse-automount-points.patch
|
|
||||||
bugfix/all/ovl-allow-distributed-fs-as-lower-layer.patch
|
|
||||||
bugfix/all/fix-a-braino-in-ovl_d_select_inode.patch
|
|
||||||
bugfix/all/perf-fix-aux-buffer-refcounting.patch
|
bugfix/all/perf-fix-aux-buffer-refcounting.patch
|
||||||
bugfix/all/perf-fix-double-free-of-the-aux-buffer.patch
|
bugfix/all/perf-fix-double-free-of-the-aux-buffer.patch
|
||||||
|
|
Loading…
Reference in New Issue