CVE-2015-2925 Don't allow bind mount escape (rhbz 1209367 1209373)
Also fixup some patch stuff from the 4.2 rebase
This commit is contained in:
parent
774ec9b607
commit
a95bfb8427
|
@ -0,0 +1,65 @@
|
||||||
|
From c0ea161a6e7158281f64bc6d41126da43cb08f14 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||||
|
Date: Sat, 15 Aug 2015 13:36:12 -0500
|
||||||
|
Subject: [PATCH 1/2] dcache: Handle escaped paths in prepend_path
|
||||||
|
|
||||||
|
commit cde93be45a8a90d8c264c776fab63487b5038a65 upstream.
|
||||||
|
|
||||||
|
A rename can result in a dentry that by walking up d_parent
|
||||||
|
will never reach it's mnt_root. For lack of a better term
|
||||||
|
I call this an escaped path.
|
||||||
|
|
||||||
|
prepend_path is called by four different functions __d_path,
|
||||||
|
d_absolute_path, d_path, and getcwd.
|
||||||
|
|
||||||
|
__d_path only wants to see paths are connected to the root it passes
|
||||||
|
in. So __d_path needs prepend_path to return an error.
|
||||||
|
|
||||||
|
d_absolute_path similarly wants to see paths that are connected to
|
||||||
|
some root. Escaped paths are not connected to any mnt_root so
|
||||||
|
d_absolute_path needs prepend_path to return an error greater
|
||||||
|
than 1. So escaped paths will be treated like paths on lazily
|
||||||
|
unmounted mounts.
|
||||||
|
|
||||||
|
getcwd needs to prepend "(unreachable)" so getcwd also needs
|
||||||
|
prepend_path to return an error.
|
||||||
|
|
||||||
|
d_path is the interesting hold out. d_path just wants to print
|
||||||
|
something, and does not care about the weird cases. Which raises
|
||||||
|
the question what should be printed?
|
||||||
|
|
||||||
|
Given that <escaped_path>/<anything> should result in -ENOENT I
|
||||||
|
believe it is desirable for escaped paths to be printed as empty
|
||||||
|
paths. As there are not really any meaninful path components when
|
||||||
|
considered from the perspective of a mount tree.
|
||||||
|
|
||||||
|
So tweak prepend_path to return an empty path with an new error
|
||||||
|
code of 3 when it encounters an escaped path.
|
||||||
|
|
||||||
|
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||||
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||||
|
---
|
||||||
|
fs/dcache.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/fs/dcache.c b/fs/dcache.c
|
||||||
|
index 9b5fe503f6cb..e3b44ca75a1b 100644
|
||||||
|
--- a/fs/dcache.c
|
||||||
|
+++ b/fs/dcache.c
|
||||||
|
@@ -2926,6 +2926,13 @@ restart:
|
||||||
|
|
||||||
|
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
|
||||||
|
struct mount *parent = ACCESS_ONCE(mnt->mnt_parent);
|
||||||
|
+ /* Escaped? */
|
||||||
|
+ if (dentry != vfsmnt->mnt_root) {
|
||||||
|
+ bptr = *buffer;
|
||||||
|
+ blen = *buflen;
|
||||||
|
+ error = 3;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
/* Global root? */
|
||||||
|
if (mnt != parent) {
|
||||||
|
dentry = ACCESS_ONCE(mnt->mnt_mountpoint);
|
||||||
|
--
|
||||||
|
2.4.3
|
||||||
|
|
23
kernel.spec
23
kernel.spec
|
@ -610,9 +610,6 @@ Patch509: ideapad-laptop-Add-Lenovo-Yoga-3-14-to-no_hw_rfkill-.patch
|
||||||
#rhbz 1253789
|
#rhbz 1253789
|
||||||
Patch511: iSCSI-let-session-recovery_tmo-sysfs-writes-persist.patch
|
Patch511: iSCSI-let-session-recovery_tmo-sysfs-writes-persist.patch
|
||||||
|
|
||||||
#rhbz 1256281
|
|
||||||
Patch26265: mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch
|
|
||||||
|
|
||||||
#rhbz 1257534
|
#rhbz 1257534
|
||||||
Patch515: nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch
|
Patch515: nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch
|
||||||
|
|
||||||
|
@ -632,6 +629,10 @@ Patch526: 0001-x86-cpu-cacheinfo-Fix-teardown-path.patch
|
||||||
#CVE-2015-5257 rhbz 1265607 1265612
|
#CVE-2015-5257 rhbz 1265607 1265612
|
||||||
Patch527: USB-whiteheat-fix-potential-null-deref-at-probe.patch
|
Patch527: USB-whiteheat-fix-potential-null-deref-at-probe.patch
|
||||||
|
|
||||||
|
#CVE-2015-2925 rhbz 1209367 1209373
|
||||||
|
Patch528: dcache-Handle-escaped-paths-in-prepend_path.patch
|
||||||
|
Patch529: vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch
|
||||||
|
|
||||||
# END OF PATCH DEFINITIONS
|
# END OF PATCH DEFINITIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
|
@ -1359,12 +1360,6 @@ ApplyPatch ideapad-laptop-Add-Lenovo-Yoga-3-14-to-no_hw_rfkill-.patch
|
||||||
#rhbz 1253789
|
#rhbz 1253789
|
||||||
ApplyPatch iSCSI-let-session-recovery_tmo-sysfs-writes-persist.patch
|
ApplyPatch iSCSI-let-session-recovery_tmo-sysfs-writes-persist.patch
|
||||||
|
|
||||||
#rhbz 1250717
|
|
||||||
ApplyPatch ext4-dont-manipulate-recovery-flag-when-freezing.patch
|
|
||||||
|
|
||||||
#rhbz 1256281
|
|
||||||
ApplyPatch mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch
|
|
||||||
|
|
||||||
#rhbz 1257534
|
#rhbz 1257534
|
||||||
ApplyPatch nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch
|
ApplyPatch nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch
|
||||||
|
|
||||||
|
@ -1372,9 +1367,6 @@ ApplyPatch nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch
|
||||||
ApplyPatch vmwgfx-Rework-device-initialization.patch
|
ApplyPatch vmwgfx-Rework-device-initialization.patch
|
||||||
ApplyPatch drm-vmwgfx-Allow-dropped-masters-render-node-like-ac.patch
|
ApplyPatch drm-vmwgfx-Allow-dropped-masters-render-node-like-ac.patch
|
||||||
|
|
||||||
#rhbz 1259231
|
|
||||||
ApplyPatch make-flush-workqueue-available-to-non-GPL-modules.patch
|
|
||||||
|
|
||||||
#rhbz 1237136
|
#rhbz 1237136
|
||||||
ApplyPatch block-blkg_destroy_all-should-clear-q-root_blkg-and-.patch
|
ApplyPatch block-blkg_destroy_all-should-clear-q-root_blkg-and-.patch
|
||||||
|
|
||||||
|
@ -1389,6 +1381,10 @@ ApplyPatch USB-whiteheat-fix-potential-null-deref-at-probe.patch
|
||||||
|
|
||||||
ApplyPatch regulator-axp20x-module-alias.patch
|
ApplyPatch regulator-axp20x-module-alias.patch
|
||||||
|
|
||||||
|
#CVE-2015-2925 rhbz 1209367 1209373
|
||||||
|
ApplyPatch dcache-Handle-escaped-paths-in-prepend_path.patch
|
||||||
|
ApplyPatch vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch
|
||||||
|
|
||||||
# END OF PATCH APPLICATIONS
|
# END OF PATCH APPLICATIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
|
@ -2239,6 +2235,9 @@ fi
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Oct 01 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||||
|
- CVE-2015-2925 Don't allow bind mount escape (rhbz 1209367 1209373)
|
||||||
|
|
||||||
* Tue Sep 29 2015 Justin M. Forbes <jforbes@fedoraproject.org>
|
* Tue Sep 29 2015 Justin M. Forbes <jforbes@fedoraproject.org>
|
||||||
- - Linux v4.2.2
|
- - Linux v4.2.2
|
||||||
|
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
From: Haibo Chen <haibo.chen@freescale.com>
|
|
||||||
Date: Tue, 25 Aug 2015 10:02:11 +0800
|
|
||||||
Subject: [PATCH] mmc: sdhci: fix dma memory leak in sdhci_pre_req()
|
|
||||||
|
|
||||||
Currently one mrq->data maybe execute dma_map_sg() twice
|
|
||||||
when mmc subsystem prepare over one new request, and the
|
|
||||||
following log show up:
|
|
||||||
sdhci[sdhci_pre_dma_transfer] invalid cookie: 24, next-cookie 25
|
|
||||||
|
|
||||||
In this condition, mrq->date map a dma-memory(1) in sdhci_pre_req
|
|
||||||
for the first time, and map another dma-memory(2) in sdhci_prepare_data
|
|
||||||
for the second time. But driver only unmap the dma-memory(2), and
|
|
||||||
dma-memory(1) never unmapped, which cause the dma memory leak issue.
|
|
||||||
|
|
||||||
This patch use another method to map the dma memory for the mrq->data
|
|
||||||
which can fix this dma memory leak issue.
|
|
||||||
|
|
||||||
Fixes: commit 348487cb28e66b0 ("mmc: sdhci: use pipeline mmc requests to improve performance")
|
|
||||||
Cc: stable@vger.kernel.org # 4.0+
|
|
||||||
Reported-and-tested-by: Jiri Slaby <jslaby@suse.cz>
|
|
||||||
Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
|
|
||||||
---
|
|
||||||
drivers/mmc/host/sdhci.c | 67 ++++++++++++++++++------------------------------
|
|
||||||
drivers/mmc/host/sdhci.h | 8 +++---
|
|
||||||
2 files changed, 29 insertions(+), 46 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
|
|
||||||
index 1dbe932..ea10ebc 100644
|
|
||||||
--- a/drivers/mmc/host/sdhci.c
|
|
||||||
+++ b/drivers/mmc/host/sdhci.c
|
|
||||||
@@ -54,8 +54,7 @@ static void sdhci_finish_command(struct sdhci_host *);
|
|
||||||
static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
|
|
||||||
static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
|
|
||||||
static int sdhci_pre_dma_transfer(struct sdhci_host *host,
|
|
||||||
- struct mmc_data *data,
|
|
||||||
- struct sdhci_host_next *next);
|
|
||||||
+ struct mmc_data *data);
|
|
||||||
static int sdhci_do_get_cd(struct sdhci_host *host);
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
|
||||||
@@ -496,7 +495,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
|
|
||||||
goto fail;
|
|
||||||
BUG_ON(host->align_addr & host->align_mask);
|
|
||||||
|
|
||||||
- host->sg_count = sdhci_pre_dma_transfer(host, data, NULL);
|
|
||||||
+ host->sg_count = sdhci_pre_dma_transfer(host, data);
|
|
||||||
if (host->sg_count < 0)
|
|
||||||
goto unmap_align;
|
|
||||||
|
|
||||||
@@ -635,9 +634,11 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (!data->host_cookie)
|
|
||||||
+ if (data->host_cookie == COOKIE_MAPPED) {
|
|
||||||
dma_unmap_sg(mmc_dev(host->mmc), data->sg,
|
|
||||||
data->sg_len, direction);
|
|
||||||
+ data->host_cookie = COOKIE_UNMAPPED;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
|
|
||||||
@@ -833,7 +834,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
|
|
||||||
} else {
|
|
||||||
int sg_cnt;
|
|
||||||
|
|
||||||
- sg_cnt = sdhci_pre_dma_transfer(host, data, NULL);
|
|
||||||
+ sg_cnt = sdhci_pre_dma_transfer(host, data);
|
|
||||||
if (sg_cnt <= 0) {
|
|
||||||
/*
|
|
||||||
* This only happens when someone fed
|
|
||||||
@@ -949,11 +950,13 @@ static void sdhci_finish_data(struct sdhci_host *host)
|
|
||||||
if (host->flags & SDHCI_USE_ADMA)
|
|
||||||
sdhci_adma_table_post(host, data);
|
|
||||||
else {
|
|
||||||
- if (!data->host_cookie)
|
|
||||||
+ if (data->host_cookie == COOKIE_MAPPED) {
|
|
||||||
dma_unmap_sg(mmc_dev(host->mmc),
|
|
||||||
data->sg, data->sg_len,
|
|
||||||
(data->flags & MMC_DATA_READ) ?
|
|
||||||
DMA_FROM_DEVICE : DMA_TO_DEVICE);
|
|
||||||
+ data->host_cookie = COOKIE_UNMAPPED;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2097,49 +2100,36 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
|
|
||||||
struct mmc_data *data = mrq->data;
|
|
||||||
|
|
||||||
if (host->flags & SDHCI_REQ_USE_DMA) {
|
|
||||||
- if (data->host_cookie)
|
|
||||||
+ if (data->host_cookie == COOKIE_GIVEN ||
|
|
||||||
+ data->host_cookie == COOKIE_MAPPED)
|
|
||||||
dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
|
|
||||||
data->flags & MMC_DATA_WRITE ?
|
|
||||||
DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
|
||||||
- mrq->data->host_cookie = 0;
|
|
||||||
+ data->host_cookie = COOKIE_UNMAPPED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sdhci_pre_dma_transfer(struct sdhci_host *host,
|
|
||||||
- struct mmc_data *data,
|
|
||||||
- struct sdhci_host_next *next)
|
|
||||||
+ struct mmc_data *data)
|
|
||||||
{
|
|
||||||
int sg_count;
|
|
||||||
|
|
||||||
- if (!next && data->host_cookie &&
|
|
||||||
- data->host_cookie != host->next_data.cookie) {
|
|
||||||
- pr_debug(DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n",
|
|
||||||
- __func__, data->host_cookie, host->next_data.cookie);
|
|
||||||
- data->host_cookie = 0;
|
|
||||||
+ if (data->host_cookie == COOKIE_MAPPED) {
|
|
||||||
+ data->host_cookie = COOKIE_GIVEN;
|
|
||||||
+ return data->sg_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Check if next job is already prepared */
|
|
||||||
- if (next ||
|
|
||||||
- (!next && data->host_cookie != host->next_data.cookie)) {
|
|
||||||
- sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg,
|
|
||||||
- data->sg_len,
|
|
||||||
- data->flags & MMC_DATA_WRITE ?
|
|
||||||
- DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
|
||||||
-
|
|
||||||
- } else {
|
|
||||||
- sg_count = host->next_data.sg_count;
|
|
||||||
- host->next_data.sg_count = 0;
|
|
||||||
- }
|
|
||||||
+ WARN_ON(data->host_cookie == COOKIE_GIVEN);
|
|
||||||
|
|
||||||
+ sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
|
|
||||||
+ data->flags & MMC_DATA_WRITE ?
|
|
||||||
+ DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
|
||||||
|
|
||||||
if (sg_count == 0)
|
|
||||||
- return -EINVAL;
|
|
||||||
+ return -ENOSPC;
|
|
||||||
|
|
||||||
- if (next) {
|
|
||||||
- next->sg_count = sg_count;
|
|
||||||
- data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
|
|
||||||
- } else
|
|
||||||
- host->sg_count = sg_count;
|
|
||||||
+ data->sg_count = sg_count;
|
|
||||||
+ data->host_cookie = COOKIE_MAPPED;
|
|
||||||
|
|
||||||
return sg_count;
|
|
||||||
}
|
|
||||||
@@ -2149,16 +2139,10 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
|
|
||||||
{
|
|
||||||
struct sdhci_host *host = mmc_priv(mmc);
|
|
||||||
|
|
||||||
- if (mrq->data->host_cookie) {
|
|
||||||
- mrq->data->host_cookie = 0;
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
+ mrq->data->host_cookie = COOKIE_UNMAPPED;
|
|
||||||
|
|
||||||
if (host->flags & SDHCI_REQ_USE_DMA)
|
|
||||||
- if (sdhci_pre_dma_transfer(host,
|
|
||||||
- mrq->data,
|
|
||||||
- &host->next_data) < 0)
|
|
||||||
- mrq->data->host_cookie = 0;
|
|
||||||
+ sdhci_pre_dma_transfer(host, mrq->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sdhci_card_event(struct mmc_host *mmc)
|
|
||||||
@@ -3030,7 +3014,6 @@ int sdhci_add_host(struct sdhci_host *host)
|
|
||||||
host->max_clk = host->ops->get_max_clock(host);
|
|
||||||
}
|
|
||||||
|
|
||||||
- host->next_data.cookie = 1;
|
|
||||||
/*
|
|
||||||
* In case of Host Controller v3.00, find out whether clock
|
|
||||||
* multiplier is supported.
|
|
||||||
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
|
|
||||||
index 5521d29..a9512a4 100644
|
|
||||||
--- a/drivers/mmc/host/sdhci.h
|
|
||||||
+++ b/drivers/mmc/host/sdhci.h
|
|
||||||
@@ -309,9 +309,10 @@ struct sdhci_adma2_64_desc {
|
|
||||||
*/
|
|
||||||
#define SDHCI_MAX_SEGS 128
|
|
||||||
|
|
||||||
-struct sdhci_host_next {
|
|
||||||
- unsigned int sg_count;
|
|
||||||
- s32 cookie;
|
|
||||||
+enum sdhci_cookie {
|
|
||||||
+ COOKIE_UNMAPPED,
|
|
||||||
+ COOKIE_MAPPED,
|
|
||||||
+ COOKIE_GIVEN,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sdhci_host {
|
|
||||||
@@ -503,7 +504,6 @@ struct sdhci_host {
|
|
||||||
unsigned int tuning_mode; /* Re-tuning mode supported by host */
|
|
||||||
#define SDHCI_TUNING_MODE_1 0
|
|
||||||
|
|
||||||
- struct sdhci_host_next next_data;
|
|
||||||
unsigned long private[0] ____cacheline_aligned;
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
From 14588dfe2e411056df5ba85ef88ad51730a2fa0a Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||||
|
Date: Sat, 15 Aug 2015 20:27:13 -0500
|
||||||
|
Subject: [PATCH 2/2] vfs: Test for and handle paths that are unreachable from
|
||||||
|
their mnt_root
|
||||||
|
|
||||||
|
commit 397d425dc26da728396e66d392d5dcb8dac30c37 upstream.
|
||||||
|
|
||||||
|
In rare cases a directory can be renamed out from under a bind mount.
|
||||||
|
In those cases without special handling it becomes possible to walk up
|
||||||
|
the directory tree to the root dentry of the filesystem and down
|
||||||
|
from the root dentry to every other file or directory on the filesystem.
|
||||||
|
|
||||||
|
Like division by zero .. from an unconnected path can not be given
|
||||||
|
a useful semantic as there is no predicting at which path component
|
||||||
|
the code will realize it is unconnected. We certainly can not match
|
||||||
|
the current behavior as the current behavior is a security hole.
|
||||||
|
|
||||||
|
Therefore when encounting .. when following an unconnected path
|
||||||
|
return -ENOENT.
|
||||||
|
|
||||||
|
- Add a function path_connected to verify path->dentry is reachable
|
||||||
|
from path->mnt.mnt_root. AKA to validate that rename did not do
|
||||||
|
something nasty to the bind mount.
|
||||||
|
|
||||||
|
To avoid races path_connected must be called after following a path
|
||||||
|
component to it's next path component.
|
||||||
|
|
||||||
|
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
|
||||||
|
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||||
|
---
|
||||||
|
fs/namei.c | 27 +++++++++++++++++++++++++--
|
||||||
|
1 file changed, 25 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/fs/namei.c b/fs/namei.c
|
||||||
|
index 1c2105ed20c5..29b927938b8c 100644
|
||||||
|
--- a/fs/namei.c
|
||||||
|
+++ b/fs/namei.c
|
||||||
|
@@ -560,6 +560,24 @@ static int __nd_alloc_stack(struct nameidata *nd)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * path_connected - Verify that a path->dentry is below path->mnt.mnt_root
|
||||||
|
+ * @path: nameidate to verify
|
||||||
|
+ *
|
||||||
|
+ * Rename can sometimes move a file or directory outside of a bind
|
||||||
|
+ * mount, path_connected allows those cases to be detected.
|
||||||
|
+ */
|
||||||
|
+static bool path_connected(const struct path *path)
|
||||||
|
+{
|
||||||
|
+ struct vfsmount *mnt = path->mnt;
|
||||||
|
+
|
||||||
|
+ /* Only bind mounts can have disconnected paths */
|
||||||
|
+ if (mnt->mnt_root == mnt->mnt_sb->s_root)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return is_subdir(path->dentry, mnt->mnt_root);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static inline int nd_alloc_stack(struct nameidata *nd)
|
||||||
|
{
|
||||||
|
if (likely(nd->depth != EMBEDDED_LEVELS))
|
||||||
|
@@ -1296,6 +1314,8 @@ static int follow_dotdot_rcu(struct nameidata *nd)
|
||||||
|
return -ECHILD;
|
||||||
|
nd->path.dentry = parent;
|
||||||
|
nd->seq = seq;
|
||||||
|
+ if (unlikely(!path_connected(&nd->path)))
|
||||||
|
+ return -ENOENT;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
struct mount *mnt = real_mount(nd->path.mnt);
|
||||||
|
@@ -1396,7 +1416,7 @@ static void follow_mount(struct path *path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void follow_dotdot(struct nameidata *nd)
|
||||||
|
+static int follow_dotdot(struct nameidata *nd)
|
||||||
|
{
|
||||||
|
if (!nd->root.mnt)
|
||||||
|
set_root(nd);
|
||||||
|
@@ -1412,6 +1432,8 @@ static void follow_dotdot(struct nameidata *nd)
|
||||||
|
/* rare case of legitimate dget_parent()... */
|
||||||
|
nd->path.dentry = dget_parent(nd->path.dentry);
|
||||||
|
dput(old);
|
||||||
|
+ if (unlikely(!path_connected(&nd->path)))
|
||||||
|
+ return -ENOENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!follow_up(&nd->path))
|
||||||
|
@@ -1419,6 +1441,7 @@ static void follow_dotdot(struct nameidata *nd)
|
||||||
|
}
|
||||||
|
follow_mount(&nd->path);
|
||||||
|
nd->inode = nd->path.dentry->d_inode;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1634,7 +1657,7 @@ static inline int handle_dots(struct nameidata *nd, int type)
|
||||||
|
if (nd->flags & LOOKUP_RCU) {
|
||||||
|
return follow_dotdot_rcu(nd);
|
||||||
|
} else
|
||||||
|
- follow_dotdot(nd);
|
||||||
|
+ return follow_dotdot(nd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.4.3
|
||||||
|
|
Loading…
Reference in New Issue