From: Cong Wang <xiyou.wangcong(a)gmail.com>
commit dbb2483b2a46fbaf833cfb5deb5ed9cace9c7399 upstream.
In commit 6a53b7593233 ("xfrm: check id proto in validate_tmpl()")
I introduced a check for xfrm protocol, but according to Herbert
IPSEC_PROTO_ANY should only be used as a wildcard for lookup, so
it should be removed from validate_tmpl().
And, IPSEC_PROTO_ANY is expected to only match 3 IPSec-specific
protocols, this is why xfrm_state_flush() could still miss
IPPROTO_ROUTING, which leads that those entries are left in
net->xfrm.state_all before exit net. Fix this by replacing
IPSEC_PROTO_ANY with zero.
This patch also extracts the check from validate_tmpl() to
xfrm_id_proto_valid() and uses it in parse_ipsecrequest().
With this, no other protocols should be added into xfrm.
Fixes: 6a53b7593233 ("xfrm: check id proto in validate_tmpl()")
Reported-by: syzbot+0bf0519d6e0de15914fe(a)syzkaller.appspotmail.com
Cc: Steffen Klassert <steffen.klassert(a)secunet.com>
Cc: Herbert Xu <herbert(a)gondor.apana.org.au>
Signed-off-by: Cong Wang <xiyou.wangcong(a)gmail.com>
Acked-by: Herbert Xu <herbert(a)gondor.apana.org.au>
Signed-off-by: Steffen Klassert <steffen.klassert(a)secunet.com>
Signed-off-by: Zubin Mithra <zsm(a)chromium.org>
---
Notes:
* Syzkaller triggered a WARNING with the following stacktrace:
__dump_stack lib/dump_stack.c:17 [inline]
dump_stack+0x114/0x1cf lib/dump_stack.c:53
panic+0x1bb/0x3a0 kernel/panic.c:181
__warn.cold.9+0x149/0x186 kernel/panic.c:542
report_bug+0x1f7/0x272 lib/bug.c:186
fixup_bug arch/x86/kernel/traps.c:177 [inline]
do_error_trap+0x1c1/0x430 arch/x86/kernel/traps.c:295
do_invalid_op+0x20/0x30 arch/x86/kernel/traps.c:314
invalid_op+0x1b/0x40 arch/x86/entry/entry_64.S:944
xfrm_net_exit+0x2a/0x30 net/xfrm/xfrm_policy.c:2971
ops_exit_list.isra.11+0xb5/0x160 net/core/net_namespace.c:142
cleanup_net+0x575/0xab0 net/core/net_namespace.c:483
process_one_work+0xb5c/0x1950 kernel/workqueue.c:2114
worker_thread+0x224/0x18c0 kernel/workqueue.c:2248
kthread+0x359/0x430 kernel/kthread.c:231
ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:402
* The commit is present in linux-4.19.y. A backport for linux-4.4.y will
be sent separately.
* The patch resolves the following conflicts:
- conflicts in content of xfrm6_tunnel_net_exit()
- changes in the prototype of xfrm_state_flush()
- ordering of xfrm_state_flush(...) and flush_work(&xfrm_state_gc_work)
inside xfrm_state_fini.
* Tests run: Chrome OS tryjobs, syzkaller reproducer
include/net/xfrm.h | 17 +++++++++++++++++
net/key/af_key.c | 4 +++-
net/xfrm/xfrm_state.c | 2 +-
net/xfrm/xfrm_user.c | 14 +-------------
4 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bdf185ae93db..57b8b11cf7d4 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1366,6 +1366,23 @@ static inline int xfrm_state_kern(const struct xfrm_state *x)
return atomic_read(&x->tunnel_users);
}
+static inline bool xfrm_id_proto_valid(u8 proto)
+{
+ switch (proto) {
+ case IPPROTO_AH:
+ case IPPROTO_ESP:
+ case IPPROTO_COMP:
+#if IS_ENABLED(CONFIG_IPV6)
+ case IPPROTO_ROUTING:
+ case IPPROTO_DSTOPTS:
+#endif
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* IPSEC_PROTO_ANY only matches 3 IPsec protocols, 0 could match all. */
static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
{
return (!userproto || proto == userproto ||
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ac38b47e9f86..f8f7065f7b62 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1951,8 +1951,10 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
if (rq->sadb_x_ipsecrequest_mode == 0)
return -EINVAL;
+ if (!xfrm_id_proto_valid(rq->sadb_x_ipsecrequest_proto))
+ return -EINVAL;
- t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */
+ t->id.proto = rq->sadb_x_ipsecrequest_proto;
if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
return -EINVAL;
t->mode = mode;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 7c093de68780..bd16e6882017 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2330,7 +2330,7 @@ void xfrm_state_fini(struct net *net)
unsigned int sz;
flush_work(&net->xfrm.state_hash_work);
- xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
+ xfrm_state_flush(net, 0, false);
flush_work(&xfrm_state_gc_work);
WARN_ON(!list_empty(&net->xfrm.state_all));
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 150c58dc8a7b..339a070da597 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1489,20 +1489,8 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
return -EINVAL;
}
- switch (ut[i].id.proto) {
- case IPPROTO_AH:
- case IPPROTO_ESP:
- case IPPROTO_COMP:
-#if IS_ENABLED(CONFIG_IPV6)
- case IPPROTO_ROUTING:
- case IPPROTO_DSTOPTS:
-#endif
- case IPSEC_PROTO_ANY:
- break;
- default:
+ if (!xfrm_id_proto_valid(ut[i].id.proto))
return -EINVAL;
- }
-
}
return 0;
--
2.23.0.162.g0b9fbb3734-goog
2 bytes in MSB of register for clock status is zero during intermediate
state after changing status of sampling clock in models of TASCAM FireWire
series. The duration of this state differs depending on cases. During the
state, it's better to retry reading the register for current status of
the clock.
In current implementation, the intermediate state is checked only when
getting current sampling transmission frequency, then retry reading.
This care is required for the other operations to read the register.
This commit moves the codes of check and retry into helper function
commonly used for operations to read the register.
Fixes: e453df44f0d6 ("ALSA: firewire-tascam: add PCM functionality")
Cc: <stable(a)vger.kernel.org> # v4.4+
Signed-off-by: Takashi Sakamoto <o-takashi(a)sakamocchi.jp>
---
sound/firewire/tascam/tascam-stream.c | 42 ++++++++++++++++++---------
1 file changed, 28 insertions(+), 14 deletions(-)
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c
index 9e2dc2fe3271..adf69a520b80 100644
--- a/sound/firewire/tascam/tascam-stream.c
+++ b/sound/firewire/tascam/tascam-stream.c
@@ -8,20 +8,37 @@
#include <linux/delay.h>
#include "tascam.h"
+#define CLOCK_STATUS_MASK 0xffff0000
+#define CLOCK_CONFIG_MASK 0x0000ffff
+
#define CALLBACK_TIMEOUT 500
static int get_clock(struct snd_tscm *tscm, u32 *data)
{
+ int trial = 0;
__be32 reg;
int err;
- err = snd_fw_transaction(tscm->unit, TCODE_READ_QUADLET_REQUEST,
- TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
- ®, sizeof(reg), 0);
- if (err >= 0)
+ while (trial++ < 5) {
+ err = snd_fw_transaction(tscm->unit, TCODE_READ_QUADLET_REQUEST,
+ TSCM_ADDR_BASE + TSCM_OFFSET_CLOCK_STATUS,
+ ®, sizeof(reg), 0);
+ if (err < 0)
+ return err;
+
*data = be32_to_cpu(reg);
+ if (*data & CLOCK_STATUS_MASK)
+ break;
- return err;
+ // In intermediate state after changing clock status.
+ msleep(50);
+ }
+
+ // Still in the intermediate state.
+ if (trial >= 5)
+ return -EAGAIN;
+
+ return 0;
}
static int set_clock(struct snd_tscm *tscm, unsigned int rate,
@@ -34,7 +51,7 @@ static int set_clock(struct snd_tscm *tscm, unsigned int rate,
err = get_clock(tscm, &data);
if (err < 0)
return err;
- data &= 0x0000ffff;
+ data &= CLOCK_CONFIG_MASK;
if (rate > 0) {
data &= 0x000000ff;
@@ -79,17 +96,14 @@ static int set_clock(struct snd_tscm *tscm, unsigned int rate,
int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate)
{
- u32 data = 0x0;
- unsigned int trials = 0;
+ u32 data;
int err;
- while (data == 0x0 || trials++ < 5) {
- err = get_clock(tscm, &data);
- if (err < 0)
- return err;
+ err = get_clock(tscm, &data);
+ if (err < 0)
+ return err;
- data = (data & 0xff000000) >> 24;
- }
+ data = (data & 0xff000000) >> 24;
/* Check base rate. */
if ((data & 0x0f) == 0x01)
--
2.20.1
The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From b9ee5e04fd77898208c51b1395fa0b5e8536f9b6 Mon Sep 17 00:00:00 2001
From: Christophe Leroy <christophe.leroy(a)c-s.fr>
Date: Thu, 8 Aug 2019 12:48:26 +0000
Subject: [PATCH] powerpc/64e: Drop stale call to smp_processor_id() which
hangs SMP startup
Commit ebb9d30a6a74 ("powerpc/mm: any thread in one core can be the
first to setup TLB1") removed the need to know the cpu_id in
early_init_this_mmu(), but the call to smp_processor_id() which was
marked __maybe_used remained.
Since commit ed1cd6deb013 ("powerpc: Activate CONFIG_THREAD_INFO_IN_TASK")
thread_info cannot be reached before MMU is properly set up.
Drop this stale call to smp_processor_id() which makes SMP hang when
CONFIG_PREEMPT is set.
Fixes: ebb9d30a6a74 ("powerpc/mm: any thread in one core can be the first to setup TLB1")
Fixes: ed1cd6deb013 ("powerpc: Activate CONFIG_THREAD_INFO_IN_TASK")
Cc: stable(a)vger.kernel.org # v5.1+
Reported-by: Chris Packham <Chris.Packham(a)alliedtelesis.co.nz>
Signed-off-by: Christophe Leroy <christophe.leroy(a)c-s.fr>
Tested-by: Chris Packham <chris.packham(a)alliedtelesis.co.nz>
Signed-off-by: Michael Ellerman <mpe(a)ellerman.id.au>
Link: https://lore.kernel.org/r/bef479514f4c08329fa649f67735df8918bc0976.15652682…
diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
index d4acf6fa0596..bf60983a58c7 100644
--- a/arch/powerpc/mm/nohash/tlb.c
+++ b/arch/powerpc/mm/nohash/tlb.c
@@ -630,7 +630,6 @@ static void early_init_this_mmu(void)
#ifdef CONFIG_PPC_FSL_BOOK3E
if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
unsigned int num_cams;
- int __maybe_unused cpu = smp_processor_id();
bool map = true;
/* use a quarter of the TLBCAM for bolted linear map */
The patch below does not apply to the 4.14-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From b9ee5e04fd77898208c51b1395fa0b5e8536f9b6 Mon Sep 17 00:00:00 2001
From: Christophe Leroy <christophe.leroy(a)c-s.fr>
Date: Thu, 8 Aug 2019 12:48:26 +0000
Subject: [PATCH] powerpc/64e: Drop stale call to smp_processor_id() which
hangs SMP startup
Commit ebb9d30a6a74 ("powerpc/mm: any thread in one core can be the
first to setup TLB1") removed the need to know the cpu_id in
early_init_this_mmu(), but the call to smp_processor_id() which was
marked __maybe_used remained.
Since commit ed1cd6deb013 ("powerpc: Activate CONFIG_THREAD_INFO_IN_TASK")
thread_info cannot be reached before MMU is properly set up.
Drop this stale call to smp_processor_id() which makes SMP hang when
CONFIG_PREEMPT is set.
Fixes: ebb9d30a6a74 ("powerpc/mm: any thread in one core can be the first to setup TLB1")
Fixes: ed1cd6deb013 ("powerpc: Activate CONFIG_THREAD_INFO_IN_TASK")
Cc: stable(a)vger.kernel.org # v5.1+
Reported-by: Chris Packham <Chris.Packham(a)alliedtelesis.co.nz>
Signed-off-by: Christophe Leroy <christophe.leroy(a)c-s.fr>
Tested-by: Chris Packham <chris.packham(a)alliedtelesis.co.nz>
Signed-off-by: Michael Ellerman <mpe(a)ellerman.id.au>
Link: https://lore.kernel.org/r/bef479514f4c08329fa649f67735df8918bc0976.15652682…
diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
index d4acf6fa0596..bf60983a58c7 100644
--- a/arch/powerpc/mm/nohash/tlb.c
+++ b/arch/powerpc/mm/nohash/tlb.c
@@ -630,7 +630,6 @@ static void early_init_this_mmu(void)
#ifdef CONFIG_PPC_FSL_BOOK3E
if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
unsigned int num_cams;
- int __maybe_unused cpu = smp_processor_id();
bool map = true;
/* use a quarter of the TLBCAM for bolted linear map */
The patch below does not apply to the 4.14-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From 264b563b8675771834419057cbe076c1a41fb666 Mon Sep 17 00:00:00 2001
From: Tiwei Bie <tiwei.bie(a)intel.com>
Date: Wed, 28 Aug 2019 13:37:00 +0800
Subject: [PATCH] vhost/test: fix build for vhost test
Since vhost_exceeds_weight() was introduced, callers need to specify
the packet weight and byte weight in vhost_dev_init(). Note that, the
packet weight isn't counted in this patch to keep the original behavior
unchanged.
Fixes: e82b9b0727ff ("vhost: introduce vhost_exceeds_weight()")
Cc: stable(a)vger.kernel.org
Signed-off-by: Tiwei Bie <tiwei.bie(a)intel.com>
Signed-off-by: Michael S. Tsirkin <mst(a)redhat.com>
Acked-by: Jason Wang <jasowang(a)redhat.com>
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index ac4f762c4f65..7804869c6a31 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -22,6 +22,12 @@
* Using this limit prevents one virtqueue from starving others. */
#define VHOST_TEST_WEIGHT 0x80000
+/* Max number of packets transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others with
+ * pkts.
+ */
+#define VHOST_TEST_PKT_WEIGHT 256
+
enum {
VHOST_TEST_VQ = 0,
VHOST_TEST_VQ_MAX = 1,
@@ -80,10 +86,8 @@ static void handle_vq(struct vhost_test *n)
}
vhost_add_used_and_signal(&n->dev, vq, head, 0);
total_len += len;
- if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
- vhost_poll_queue(&vq->poll);
+ if (unlikely(vhost_exceeds_weight(vq, 0, total_len)))
break;
- }
}
mutex_unlock(&vq->mutex);
@@ -115,7 +119,8 @@ static int vhost_test_open(struct inode *inode, struct file *f)
dev = &n->dev;
vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ];
n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
- vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX, UIO_MAXIOV);
+ vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX, UIO_MAXIOV,
+ VHOST_TEST_PKT_WEIGHT, VHOST_TEST_WEIGHT);
f->private_data = n;