Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1587605 > unrolled thread
| Started by | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| First post | 2017-02-24 14:10 +0100 |
| Last post | 2017-02-24 17:30 +0100 |
| Articles | 9 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 3.16 00/12] 3.16.41-rc1 review Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:10 +0100
[PATCH 3.16 12/12] tcp: avoid infinite loop in tcp_splice_read() Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:20 +0100
[PATCH 3.16 04/12] KVM: x86: fix emulation of "MOV SS, null selector" Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:20 +0100
[PATCH 3.16 07/12] USB: serial: kl5kusb105: fix line-state error handling Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:20 +0100
[PATCH 3.16 06/12] selinux: fix off-by-one in setprocattr Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:20 +0100
[PATCH 3.16 02/12] kvm: nVMX: Allow L1 to intercept software exceptions (#BP and #OF) Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:20 +0100
[PATCH 3.16 01/12] mnt: Add a per mount namespace limit on the number of mounts Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:20 +0100
[PATCH 3.16 03/12] ext4: validate s_first_meta_bg at mount time Ben Hutchings <ben@decadent.org.uk> - 2017-02-24 14:20 +0100
Re: [PATCH 3.16 00/12] 3.16.41-rc1 review Guenter Roeck <linux@roeck-us.net> - 2017-02-24 17:30 +0100
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:10 +0100 |
| Subject | [PATCH 3.16 00/12] 3.16.41-rc1 review |
| Message-ID | <ten0R-8s6-3@gated-at.bofh.it> |
This is the start of the stable review cycle for the 3.16.41 release.
There are 12 patches in this series, which will be posted as responses
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Sun Feb 26 12:10:01 UTC 2017.
Anything received after that time might be too late.
A combined patch relative to 3.16.40 will be posted as an additional
response to this. A shortlog and diffstat can be found below.
Ben.
-------------
Andrey Konovalov (1):
dccp: fix freeing skb too early for IPV6_RECVPKTINFO
[5edabca9d4cff7f1f2b68f0bac55ef99d9798ba4]
Eric Dumazet (3):
ip6_gre: fix ip6gre_err() invalid reads
[7892032cfe67f4bde6fc2ee967e45a8fbaf33756]
ipv4: keep skb->dst around in presence of IP options
[34b2cef20f19c87999fff3da4071e66937db9644]
tcp: avoid infinite loop in tcp_splice_read()
[ccf7abb93af09ad0868ae9033d1ca8108bdaec82]
Eric W. Biederman (1):
mnt: Add a per mount namespace limit on the number of mounts
[d29216842a85c7970c536108e093963f02714498]
Eryu Guan (1):
ext4: validate s_first_meta_bg at mount time
[3a4b77cd47bb837b8557595ec7425f281f2ca1fe]
Gu Zheng (1):
tmpfs: clear S_ISGID when setting posix ACLs
[497de07d89c1410d76a15bec2bb41f24a2a89f31]
Jim Mattson (1):
kvm: nVMX: Allow L1 to intercept software exceptions (#BP and #OF)
[ef85b67385436ddc1998f45f1d6a210f935b3388]
Johan Hovold (1):
USB: serial: kl5kusb105: fix line-state error handling
[146cc8a17a3b4996f6805ee5c080e7101277c410]
Paolo Bonzini (1):
KVM: x86: fix emulation of "MOV SS, null selector"
[33ab91103b3415e12457e3104f0e4517ce12d0f3]
Stephen Smalley (1):
selinux: fix off-by-one in setprocattr
[0c461cb727d146c9ef2d3e86214f498b78b7d125]
Steve Rutherford (1):
KVM: x86: Introduce segmented_write_std
[129a72a0d3c8e139a04512325384fe5ac119e74d]
Documentation/sysctl/fs.txt | 7 +++++
Makefile | 4 +--
arch/x86/kvm/emulate.c | 66 +++++++++++++++++++++++++++++++++--------
arch/x86/kvm/vmx.c | 11 ++++---
drivers/usb/serial/kl5kusb105.c | 9 +++---
fs/ext4/super.c | 9 ++++++
fs/mount.h | 2 ++
fs/namespace.c | 49 +++++++++++++++++++++++++++++-
fs/pnode.c | 2 +-
fs/pnode.h | 1 +
fs/posix_acl.c | 9 +++---
include/linux/mount.h | 2 ++
kernel/sysctl.c | 9 ++++++
net/dccp/input.c | 3 +-
net/ipv4/ip_sockglue.c | 9 +++++-
net/ipv4/tcp.c | 6 ++++
net/ipv6/ip6_gre.c | 41 +++++++++++++------------
security/selinux/hooks.c | 2 +-
18 files changed, 188 insertions(+), 53 deletions(-)
--
Ben Hutchings
All the simple programs have been written, and all the good names taken.
[toc] | [next] | [standalone]
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:20 +0100 |
| Subject | [PATCH 3.16 12/12] tcp: avoid infinite loop in tcp_splice_read() |
| Message-ID | <tenWV-FB-7@gated-at.bofh.it> |
| In reply to | #1587605 |
3.16.41-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <edumazet@google.com>
commit ccf7abb93af09ad0868ae9033d1ca8108bdaec82 upstream.
Splicing from TCP socket is vulnerable when a packet with URG flag is
received and stored into receive queue.
__tcp_splice_read() returns 0, and sk_wait_data() immediately
returns since there is the problematic skb in queue.
This is a nice way to burn cpu (aka infinite loop) and trigger
soft lockups.
Again, this gem was found by syzkaller tool.
Fixes: 9c55e01c0cc8 ("[TCP]: Splice receive support.")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Willy Tarreau <w@1wt.eu>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
net/ipv4/tcp.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -765,6 +765,12 @@ ssize_t tcp_splice_read(struct socket *s
ret = -EAGAIN;
break;
}
+ /* if __tcp_splice_read() got nothing while we have
+ * an skb in receive queue, we do not want to loop.
+ * This might happen with URG data.
+ */
+ if (!skb_queue_empty(&sk->sk_receive_queue))
+ break;
sk_wait_data(sk, &timeo);
if (signal_pending(current)) {
ret = sock_intr_errno(timeo);
[toc] | [prev] | [next] | [standalone]
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:20 +0100 |
| Subject | [PATCH 3.16 04/12] KVM: x86: fix emulation of "MOV SS, null selector" |
| Message-ID | <tenWV-FB-11@gated-at.bofh.it> |
| In reply to | #1587605 |
3.16.41-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Bonzini <pbonzini@redhat.com>
commit 33ab91103b3415e12457e3104f0e4517ce12d0f3 upstream.
This is CVE-2017-2583. On Intel this causes a failed vmentry because
SS's type is neither 3 nor 7 (even though the manual says this check is
only done for usable SS, and the dmesg splat says that SS is unusable!).
On AMD it's worse: svm.c is confused and sets CPL to 0 in the vmcb.
The fix fabricates a data segment descriptor when SS is set to a null
selector, so that CPL and SS.DPL are set correctly in the VMCS/vmcb.
Furthermore, only allow setting SS to a NULL selector if SS.RPL < 3;
this in turn ensures CPL < 3 because RPL must be equal to CPL.
Thanks to Andy Lutomirski and Willy Tarreau for help in analyzing
the bug and deciphering the manuals.
Reported-by: Xiaohan Zhang <zhangxiaohan1@huawei.com>
Fixes: 79d5b4c3cd809c770d4bf9812635647016c56011
Cc: stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
arch/x86/kvm/emulate.c | 48 ++++++++++++++++++++++++++++++++++++++----------
1 file changed, 38 insertions(+), 10 deletions(-)
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1439,7 +1439,6 @@ static int write_segment_descriptor(stru
&ctxt->exception);
}
-/* Does not support long mode */
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
u16 selector, int seg, u8 cpl,
bool in_task_switch,
@@ -1475,20 +1474,34 @@ static int __load_segment_descriptor(str
rpl = selector & 3;
- /* NULL selector is not valid for TR, CS and SS (except for long mode) */
- if ((seg == VCPU_SREG_CS
- || (seg == VCPU_SREG_SS
- && (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl))
- || seg == VCPU_SREG_TR)
- && null_selector)
- goto exception;
-
/* TR should be in GDT only */
if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
goto exception;
- if (null_selector) /* for NULL selector skip all following checks */
+ /* NULL selector is not valid for TR, CS and (except for long mode) SS */
+ if (null_selector) {
+ if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR)
+ goto exception;
+
+ if (seg == VCPU_SREG_SS) {
+ if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)
+ goto exception;
+
+ /*
+ * ctxt->ops->set_segment expects the CPL to be in
+ * SS.DPL, so fake an expand-up 32-bit data segment.
+ */
+ seg_desc.type = 3;
+ seg_desc.p = 1;
+ seg_desc.s = 1;
+ seg_desc.dpl = cpl;
+ seg_desc.d = 1;
+ seg_desc.g = 1;
+ }
+
+ /* Skip all following checks */
goto load;
+ }
ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
if (ret != X86EMUL_CONTINUE)
@@ -1584,6 +1597,21 @@ static int load_segment_descriptor(struc
u16 selector, int seg)
{
u8 cpl = ctxt->ops->cpl(ctxt);
+
+ /*
+ * None of MOV, POP and LSS can load a NULL selector in CPL=3, but
+ * they can load it at CPL<3 (Intel's manual says only LSS can,
+ * but it's wrong).
+ *
+ * However, the Intel manual says that putting IST=1/DPL=3 in
+ * an interrupt gate will result in SS=3 (the AMD manual instead
+ * says it doesn't), so allow SS=3 in __load_segment_descriptor
+ * and only forbid it here.
+ */
+ if (seg == VCPU_SREG_SS && selector == 3 &&
+ ctxt->mode == X86EMUL_MODE_PROT64)
+ return emulate_exception(ctxt, GP_VECTOR, 0, true);
+
return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL);
}
[toc] | [prev] | [next] | [standalone]
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:20 +0100 |
| Subject | [PATCH 3.16 07/12] USB: serial: kl5kusb105: fix line-state error handling |
| Message-ID | <tenWW-FB-37@gated-at.bofh.it> |
| In reply to | #1587605 |
3.16.41-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 146cc8a17a3b4996f6805ee5c080e7101277c410 upstream.
The current implementation failed to detect short transfers when
attempting to read the line state, and also, to make things worse,
logged the content of the uninitialised heap transfer buffer.
Fixes: abf492e7b3ae ("USB: kl5kusb105: fix DMA buffers on stack")
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
drivers/usb/serial/kl5kusb105.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -195,10 +195,11 @@ static int klsi_105_get_line_state(struc
status_buf, KLSI_STATUSBUF_LEN,
10000
);
- if (rc < 0)
- dev_err(&port->dev, "Reading line status failed (error = %d)\n",
- rc);
- else {
+ if (rc != KLSI_STATUSBUF_LEN) {
+ dev_err(&port->dev, "reading line status failed: %d\n", rc);
+ if (rc >= 0)
+ rc = -EIO;
+ } else {
status = get_unaligned_le16(status_buf);
dev_info(&port->serial->dev->dev, "read status %x %x\n",
[toc] | [prev] | [next] | [standalone]
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:20 +0100 |
| Subject | [PATCH 3.16 06/12] selinux: fix off-by-one in setprocattr |
| Message-ID | <tenWX-FB-59@gated-at.bofh.it> |
| In reply to | #1587605 |
3.16.41-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Smalley <sds@tycho.nsa.gov>
commit 0c461cb727d146c9ef2d3e86214f498b78b7d125 upstream.
SELinux tries to support setting/clearing of /proc/pid/attr attributes
from the shell by ignoring terminating newlines and treating an
attribute value that begins with a NUL or newline as an attempt to
clear the attribute. However, the test for clearing attributes has
always been wrong; it has an off-by-one error, and this could further
lead to reading past the end of the allocated buffer since commit
bb646cdb12e75d82258c2f2e7746d5952d3e321a ("proc_pid_attr_write():
switch to memdup_user()"). Fix the off-by-one error.
Even with this fix, setting and clearing /proc/pid/attr attributes
from the shell is not straightforward since the interface does not
support multiple write() calls (so shells that write the value and
newline separately will set and then immediately clear the attribute,
requiring use of echo -n to set the attribute), whereas trying to use
echo -n "" to clear the attribute causes the shell to skip the
write() call altogether since POSIX says that a zero-length write
causes no side effects. Thus, one must use echo -n to set and echo
without -n to clear, as in the following example:
$ echo -n unconfined_u:object_r:user_home_t:s0 > /proc/$$/attr/fscreate
$ cat /proc/$$/attr/fscreate
unconfined_u:object_r:user_home_t:s0
$ echo "" > /proc/$$/attr/fscreate
$ cat /proc/$$/attr/fscreate
Note the use of /proc/$$ rather than /proc/self, as otherwise
the cat command will read its own attribute value, not that of the shell.
There are no users of this facility to my knowledge; possibly we
should just get rid of it.
UPDATE: Upon further investigation it appears that a local process
with the process:setfscreate permission can cause a kernel panic as a
result of this bug. This patch fixes CVE-2017-2618.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
[PM: added the update about CVE-2017-2618 to the commit description]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
security/selinux/hooks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5546,7 +5546,7 @@ static int selinux_setprocattr(struct ta
return error;
/* Obtain a SID for the context, if one was specified. */
- if (size && str[1] && str[1] != '\n') {
+ if (size && str[0] && str[0] != '\n') {
if (str[size-1] == '\n') {
str[size-1] = 0;
size--;
[toc] | [prev] | [next] | [standalone]
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:20 +0100 |
| Subject | [PATCH 3.16 02/12] kvm: nVMX: Allow L1 to intercept software exceptions (#BP and #OF) |
| Message-ID | <tenWY-FB-79@gated-at.bofh.it> |
| In reply to | #1587605 |
3.16.41-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jim Mattson <jmattson@google.com>
commit ef85b67385436ddc1998f45f1d6a210f935b3388 upstream.
When L2 exits to L0 due to "exception or NMI", software exceptions
(#BP and #OF) for which L1 has requested an intercept should be
handled by L1 rather than L0. Previously, only hardware exceptions
were forwarded to L1.
Signed-off-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
arch/x86/kvm/vmx.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1073,10 +1073,10 @@ static inline int nested_cpu_has_ept(str
return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT);
}
-static inline bool is_exception(u32 intr_info)
+static inline bool is_nmi(u32 intr_info)
{
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
- == (INTR_TYPE_HARD_EXCEPTION | INTR_INFO_VALID_MASK);
+ == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
}
static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
@@ -4838,7 +4838,7 @@ static int handle_exception(struct kvm_v
if (is_machine_check(intr_info))
return handle_machine_check(vcpu);
- if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
+ if (is_nmi(intr_info))
return 1; /* already handled by vmx_vcpu_run() */
if (is_no_device(intr_info)) {
@@ -6888,7 +6888,7 @@ static bool nested_vmx_exit_handled(stru
switch (exit_reason) {
case EXIT_REASON_EXCEPTION_NMI:
- if (!is_exception(intr_info))
+ if (is_nmi(intr_info))
return 0;
else if (is_page_fault(intr_info))
return enable_ept;
@@ -7185,8 +7185,7 @@ static void vmx_complete_atomic_exit(str
kvm_machine_check();
/* We need to handle NMIs before interrupts are enabled */
- if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
- (exit_intr_info & INTR_INFO_VALID_MASK)) {
+ if (is_nmi(exit_intr_info)) {
kvm_before_handle_nmi(&vmx->vcpu);
asm("int $2");
kvm_after_handle_nmi(&vmx->vcpu);
[toc] | [prev] | [next] | [standalone]
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:20 +0100 |
| Subject | [PATCH 3.16 01/12] mnt: Add a per mount namespace limit on the number of mounts |
| Message-ID | <tenWY-FB-93@gated-at.bofh.it> |
| In reply to | #1587605 |
3.16.41-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: "Eric W. Biederman" <ebiederm@xmission.com>
commit d29216842a85c7970c536108e093963f02714498 upstream.
CAI Qian <caiqian@redhat.com> pointed out that the semantics
of shared subtrees make it possible to create an exponentially
increasing number of mounts in a mount namespace.
mkdir /tmp/1 /tmp/2
mount --make-rshared /
for i in $(seq 1 20) ; do mount --bind /tmp/1 /tmp/2 ; done
Will create create 2^20 or 1048576 mounts, which is a practical problem
as some people have managed to hit this by accident.
As such CVE-2016-6213 was assigned.
Ian Kent <raven@themaw.net> described the situation for autofs users
as follows:
> The number of mounts for direct mount maps is usually not very large because of
> the way they are implemented, large direct mount maps can have performance
> problems. There can be anywhere from a few (likely case a few hundred) to less
> than 10000, plus mounts that have been triggered and not yet expired.
>
> Indirect mounts have one autofs mount at the root plus the number of mounts that
> have been triggered and not yet expired.
>
> The number of autofs indirect map entries can range from a few to the common
> case of several thousand and in rare cases up to between 30000 and 50000. I've
> not heard of people with maps larger than 50000 entries.
>
> The larger the number of map entries the greater the possibility for a large
> number of active mounts so it's not hard to expect cases of a 1000 or somewhat
> more active mounts.
So I am setting the default number of mounts allowed per mount
namespace at 100,000. This is more than enough for any use case I
know of, but small enough to quickly stop an exponential increase
in mounts. Which should be perfect to catch misconfigurations and
malfunctioning programs.
For anyone who needs a higher limit this can be changed by writing
to the new /proc/sys/fs/mount-max sysctl.
Tested-by: CAI Qian <caiqian@redhat.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
[bwh: Backported to 3.16:
- Use ACCESS_ONCE() instead of READ_ONCE()
- Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
Documentation/sysctl/fs.txt | 7 +++++++
fs/mount.h | 2 ++
fs/namespace.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-
fs/pnode.c | 2 +-
fs/pnode.h | 1 +
include/linux/mount.h | 2 ++
kernel/sysctl.c | 9 +++++++++
7 files changed, 70 insertions(+), 2 deletions(-)
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -265,6 +265,13 @@ aio-nr can grow to.
==============================================================
+mount-max:
+
+This denotes the maximum number of mounts that may exist
+in a mount namespace.
+
+==============================================================
+
2. /proc/sys/fs/binfmt_misc
----------------------------------------------------------
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -11,6 +11,8 @@ struct mnt_namespace {
u64 seq; /* Sequence number to prevent loops */
wait_queue_head_t poll;
u64 event;
+ unsigned int mounts; /* # of mounts in the namespace */
+ unsigned int pending_mounts;
};
struct mnt_pcp {
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -27,6 +27,9 @@
#include "pnode.h"
#include "internal.h"
+/* Maximum number of mounts in a mount namespace */
+unsigned int sysctl_mount_max __read_mostly = 100000;
+
static unsigned int m_hash_mask __read_mostly;
static unsigned int m_hash_shift __read_mostly;
static unsigned int mp_hash_mask __read_mostly;
@@ -811,6 +814,9 @@ static void commit_tree(struct mount *mn
list_splice(&head, n->list.prev);
+ n->mounts += n->pending_mounts;
+ n->pending_mounts = 0;
+
attach_shadowed(mnt, parent, shadows);
touch_mnt_namespace(n);
}
@@ -1284,9 +1290,14 @@ static void umount_tree(struct mount *mn
propagate_umount(&tmp_list);
hlist_for_each_entry(p, &tmp_list, mnt_hash) {
+ struct mnt_namespace *ns;
list_del_init(&p->mnt_expire);
list_del_init(&p->mnt_list);
- __touch_mnt_namespace(p->mnt_ns);
+ ns = p->mnt_ns;
+ if (ns) {
+ ns->mounts--;
+ __touch_mnt_namespace(ns);
+ }
p->mnt_ns = NULL;
if (how & UMOUNT_SYNC)
p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
@@ -1641,6 +1652,28 @@ static int invent_group_ids(struct mount
return 0;
}
+int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
+{
+ unsigned int max = ACCESS_ONCE(sysctl_mount_max);
+ unsigned int mounts = 0, old, pending, sum;
+ struct mount *p;
+
+ for (p = mnt; p; p = next_mnt(p, mnt))
+ mounts++;
+
+ old = ns->mounts;
+ pending = ns->pending_mounts;
+ sum = old + pending;
+ if ((old > sum) ||
+ (pending > sum) ||
+ (max < sum) ||
+ (mounts > (max - sum)))
+ return -ENOSPC;
+
+ ns->pending_mounts = pending + mounts;
+ return 0;
+}
+
/*
* @source_mnt : mount tree to be attached
* @nd : place the mount tree @source_mnt is attached
@@ -1710,10 +1743,18 @@ static int attach_recursive_mnt(struct m
struct path *parent_path)
{
HLIST_HEAD(tree_list);
+ struct mnt_namespace *ns = dest_mnt->mnt_ns;
struct mount *child, *p;
struct hlist_node *n;
int err;
+ /* Is there space to add these mounts to the mount namespace? */
+ if (!parent_path) {
+ err = count_mounts(ns, source_mnt);
+ if (err)
+ goto out;
+ }
+
if (IS_MNT_SHARED(dest_mnt)) {
err = invent_group_ids(source_mnt, true);
if (err)
@@ -1750,11 +1791,13 @@ static int attach_recursive_mnt(struct m
out_cleanup_ids:
while (!hlist_empty(&tree_list)) {
child = hlist_entry(tree_list.first, struct mount, mnt_hash);
+ child->mnt_parent->mnt_ns->pending_mounts = 0;
umount_tree(child, UMOUNT_SYNC);
}
unlock_mount_hash();
cleanup_group_ids(source_mnt, NULL);
out:
+ ns->pending_mounts = 0;
return err;
}
@@ -2586,6 +2629,8 @@ static struct mnt_namespace *alloc_mnt_n
init_waitqueue_head(&new_ns->poll);
new_ns->event = 0;
new_ns->user_ns = get_user_ns(user_ns);
+ new_ns->mounts = 0;
+ new_ns->pending_mounts = 0;
return new_ns;
}
@@ -2635,6 +2680,7 @@ struct mnt_namespace *copy_mnt_ns(unsign
q = new;
while (p) {
q->mnt_ns = new_ns;
+ new_ns->mounts++;
if (new_fs) {
if (&p->mnt == new_fs->root.mnt) {
new_fs->root.mnt = mntget(&q->mnt);
@@ -2673,6 +2719,7 @@ static struct mnt_namespace *create_mnt_
struct mount *mnt = real_mount(m);
mnt->mnt_ns = new_ns;
new_ns->root = mnt;
+ new_ns->mounts++;
list_add(&mnt->mnt_list, &new_ns->list);
} else {
mntput(m);
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -258,7 +258,7 @@ static int propagate_one(struct mount *m
read_sequnlock_excl(&mount_lock);
}
hlist_add_head(&child->mnt_hash, list);
- return 0;
+ return count_mounts(m->mnt_ns, child);
}
/*
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -50,4 +50,5 @@ void mnt_set_mountpoint(struct mount *,
struct mount *copy_tree(struct mount *, struct dentry *, int);
bool is_path_reachable(struct mount *, struct dentry *,
const struct path *root);
+int count_mounts(struct mnt_namespace *ns, struct mount *mnt);
#endif /* _LINUX_PNODE_H */
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -91,4 +91,6 @@ extern void mark_mounts_for_expiry(struc
extern dev_t name_to_dev_t(char *name);
+extern unsigned int sysctl_mount_max;
+
#endif /* _LINUX_MOUNT_H */
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -63,6 +63,7 @@
#include <linux/binfmts.h>
#include <linux/sched/sysctl.h>
#include <linux/kexec.h>
+#include <linux/mount.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
@@ -1685,6 +1686,14 @@ static struct ctl_table fs_table[] = {
.mode = 0644,
.proc_handler = proc_doulongvec_minmax,
},
+ {
+ .procname = "mount-max",
+ .data = &sysctl_mount_max,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &one,
+ },
{ }
};
[toc] | [prev] | [next] | [standalone]
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Date | 2017-02-24 14:20 +0100 |
| Subject | [PATCH 3.16 03/12] ext4: validate s_first_meta_bg at mount time |
| Message-ID | <tenWY-FB-95@gated-at.bofh.it> |
| In reply to | #1587605 |
3.16.41-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eryu Guan <guaneryu@gmail.com>
commit 3a4b77cd47bb837b8557595ec7425f281f2ca1fe upstream.
Ralf Spenneberg reported that he hit a kernel crash when mounting a
modified ext4 image. And it turns out that kernel crashed when
calculating fs overhead (ext4_calculate_overhead()), this is because
the image has very large s_first_meta_bg (debug code shows it's
842150400), and ext4 overruns the memory in count_overhead() when
setting bitmap buffer, which is PAGE_SIZE.
ext4_calculate_overhead():
buf = get_zeroed_page(GFP_NOFS); <=== PAGE_SIZE buffer
blks = count_overhead(sb, i, buf);
count_overhead():
for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { <=== j = 842150400
ext4_set_bit(EXT4_B2C(sbi, s++), buf); <=== buffer overrun
count++;
}
This can be reproduced easily for me by this script:
#!/bin/bash
rm -f fs.img
mkdir -p /mnt/ext4
fallocate -l 16M fs.img
mke2fs -t ext4 -O bigalloc,meta_bg,^resize_inode -F fs.img
debugfs -w -R "ssv first_meta_bg 842150400" fs.img
mount -o loop fs.img /mnt/ext4
Fix it by validating s_first_meta_bg first at mount time, and
refusing to mount if its value exceeds the largest possible meta_bg
number.
Reported-by: Ralf Spenneberg <ralf@os-t.de>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
[bwh: Backported to 3.16: use EXT4_HAS_INCOMPAT_FEATURE()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
fs/ext4/super.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3905,6 +3905,15 @@ static int ext4_fill_super(struct super_
(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
EXT4_DESC_PER_BLOCK(sb);
+ if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG)) {
+ if (le32_to_cpu(es->s_first_meta_bg) >= db_count) {
+ ext4_msg(sb, KERN_WARNING,
+ "first meta block group too large: %u "
+ "(group descriptor block count %u)",
+ le32_to_cpu(es->s_first_meta_bg), db_count);
+ goto failed_mount;
+ }
+ }
sbi->s_group_desc = ext4_kvmalloc(db_count *
sizeof(struct buffer_head *),
GFP_KERNEL);
[toc] | [prev] | [next] | [standalone]
| From | Guenter Roeck <linux@roeck-us.net> |
|---|---|
| Date | 2017-02-24 17:30 +0100 |
| Message-ID | <teqUO-2GV-9@gated-at.bofh.it> |
| In reply to | #1587605 |
On 02/24/2017 04:10 AM, Ben Hutchings wrote: > This is the start of the stable review cycle for the 3.16.41 release. > There are 12 patches in this series, which will be posted as responses > to this one. If anyone has any issues with these being applied, please > let me know. > > Responses should be made by Sun Feb 26 12:10:01 UTC 2017. > Anything received after that time might be too late. > Build results: total: 140 pass: 140 fail: 0 Qemu test results: total: 107 pass: 107 fail: 0 Details are available at http://kerneltests.org/builders. Guenter
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web