]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Dec 2021 11:42:48 +0000 (12:42 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Dec 2021 11:42:48 +0000 (12:42 +0100)
added patches:
arm-dts-imx6ull-pinfunc-fix-csi_data07__esai_tx0-pad-name.patch
bpf-fix-extable-address-check.patch
bpf-x64-factor-out-emission-of-rex-byte-in-more-cases.patch
media-mxl111sf-change-mutex_init-location.patch
mptcp-add-missing-documented-nl-params.patch
usb-core-make-do_proc_control-and-do_proc_bulk-killable.patch
xsk-do-not-sleep-in-poll-when-need_wakeup-set.patch

queue-5.15/arm-dts-imx6ull-pinfunc-fix-csi_data07__esai_tx0-pad-name.patch [new file with mode: 0644]
queue-5.15/bpf-fix-extable-address-check.patch [new file with mode: 0644]
queue-5.15/bpf-x64-factor-out-emission-of-rex-byte-in-more-cases.patch [new file with mode: 0644]
queue-5.15/btrfs-fix-invalid-delayed-ref-after-subvolume-creation-failure.patch [deleted file]
queue-5.15/media-mxl111sf-change-mutex_init-location.patch [new file with mode: 0644]
queue-5.15/mptcp-add-missing-documented-nl-params.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/usb-core-make-do_proc_control-and-do_proc_bulk-killable.patch [new file with mode: 0644]
queue-5.15/xsk-do-not-sleep-in-poll-when-need_wakeup-set.patch [new file with mode: 0644]

diff --git a/queue-5.15/arm-dts-imx6ull-pinfunc-fix-csi_data07__esai_tx0-pad-name.patch b/queue-5.15/arm-dts-imx6ull-pinfunc-fix-csi_data07__esai_tx0-pad-name.patch
new file mode 100644 (file)
index 0000000..40d0dbf
--- /dev/null
@@ -0,0 +1,37 @@
+From 737e65c7956795b3553781fb7bc82fce1c39503f Mon Sep 17 00:00:00 2001
+From: Fabio Estevam <festevam@gmail.com>
+Date: Wed, 24 Nov 2021 15:45:41 -0300
+Subject: ARM: dts: imx6ull-pinfunc: Fix CSI_DATA07__ESAI_TX0 pad name
+
+From: Fabio Estevam <festevam@gmail.com>
+
+commit 737e65c7956795b3553781fb7bc82fce1c39503f upstream.
+
+According to the i.MX6ULL Reference Manual, pad CSI_DATA07 may
+have the ESAI_TX0 functionality, not ESAI_T0.
+
+Also, NXP's i.MX Config Tools 10.0 generates dtsi with the
+MX6ULL_PAD_CSI_DATA07__ESAI_TX0 naming, so fix it accordingly.
+
+There are no devicetree users in mainline that use the old name,
+so just remove the old entry.
+
+Fixes: c201369d4aa5 ("ARM: dts: imx6ull: add imx6ull support")
+Reported-by: George Makarov <georgemakarov1@gmail.com>
+Signed-off-by: Fabio Estevam <festevam@gmail.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/boot/dts/imx6ull-pinfunc.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/imx6ull-pinfunc.h
++++ b/arch/arm/boot/dts/imx6ull-pinfunc.h
+@@ -82,6 +82,6 @@
+ #define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS                         0x01F4 0x0480 0x0000 0x9 0x0
+ #define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK                        0x01F8 0x0484 0x0000 0x9 0x0
+ #define MX6ULL_PAD_CSI_DATA06__ESAI_TX5_RX0                       0x01FC 0x0488 0x0000 0x9 0x0
+-#define MX6ULL_PAD_CSI_DATA07__ESAI_T0                            0x0200 0x048C 0x0000 0x9 0x0
++#define MX6ULL_PAD_CSI_DATA07__ESAI_TX0                           0x0200 0x048C 0x0000 0x9 0x0
+ #endif /* __DTS_IMX6ULL_PINFUNC_H */
diff --git a/queue-5.15/bpf-fix-extable-address-check.patch b/queue-5.15/bpf-fix-extable-address-check.patch
new file mode 100644 (file)
index 0000000..8c71e45
--- /dev/null
@@ -0,0 +1,92 @@
+From 588a25e92458c6efeb7a261d5ca5726f5de89184 Mon Sep 17 00:00:00 2001
+From: Alexei Starovoitov <ast@kernel.org>
+Date: Tue, 14 Dec 2021 19:25:13 -0800
+Subject: bpf: Fix extable address check.
+
+From: Alexei Starovoitov <ast@kernel.org>
+
+commit 588a25e92458c6efeb7a261d5ca5726f5de89184 upstream.
+
+The verifier checks that PTR_TO_BTF_ID pointer is either valid or NULL,
+but it cannot distinguish IS_ERR pointer from valid one.
+
+When offset is added to IS_ERR pointer it may become small positive
+value which is a user address that is not handled by extable logic
+and has to be checked for at the runtime.
+
+Tighten BPF_PROBE_MEM pointer check code to prevent this case.
+
+Fixes: 4c5de127598e ("bpf: Emit explicit NULL pointer checks for PROBE_LDX instructions.")
+Reported-by: Lorenzo Fontana <lorenzo.fontana@elastic.co>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/net/bpf_jit_comp.c |   49 +++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 42 insertions(+), 7 deletions(-)
+
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -1280,19 +1280,54 @@ st:                    if (is_imm8(insn->off))
+               case BPF_LDX | BPF_MEM | BPF_DW:
+               case BPF_LDX | BPF_PROBE_MEM | BPF_DW:
+                       if (BPF_MODE(insn->code) == BPF_PROBE_MEM) {
+-                              /* test src_reg, src_reg */
+-                              maybe_emit_mod(&prog, src_reg, src_reg, true); /* always 1 byte */
+-                              EMIT2(0x85, add_2reg(0xC0, src_reg, src_reg));
+-                              /* jne start_of_ldx */
+-                              EMIT2(X86_JNE, 0);
++                              /* Though the verifier prevents negative insn->off in BPF_PROBE_MEM
++                               * add abs(insn->off) to the limit to make sure that negative
++                               * offset won't be an issue.
++                               * insn->off is s16, so it won't affect valid pointers.
++                               */
++                              u64 limit = TASK_SIZE_MAX + PAGE_SIZE + abs(insn->off);
++                              u8 *end_of_jmp1, *end_of_jmp2;
++
++                              /* Conservatively check that src_reg + insn->off is a kernel address:
++                               * 1. src_reg + insn->off >= limit
++                               * 2. src_reg + insn->off doesn't become small positive.
++                               * Cannot do src_reg + insn->off >= limit in one branch,
++                               * since it needs two spare registers, but JIT has only one.
++                               */
++
++                              /* movabsq r11, limit */
++                              EMIT2(add_1mod(0x48, AUX_REG), add_1reg(0xB8, AUX_REG));
++                              EMIT((u32)limit, 4);
++                              EMIT(limit >> 32, 4);
++                              /* cmp src_reg, r11 */
++                              maybe_emit_mod(&prog, src_reg, AUX_REG, true);
++                              EMIT2(0x39, add_2reg(0xC0, src_reg, AUX_REG));
++                              /* if unsigned '<' goto end_of_jmp2 */
++                              EMIT2(X86_JB, 0);
++                              end_of_jmp1 = prog;
++
++                              /* mov r11, src_reg */
++                              emit_mov_reg(&prog, true, AUX_REG, src_reg);
++                              /* add r11, insn->off */
++                              maybe_emit_1mod(&prog, AUX_REG, true);
++                              EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off);
++                              /* jmp if not carry to start_of_ldx
++                               * Otherwise ERR_PTR(-EINVAL) + 128 will be the user addr
++                               * that has to be rejected.
++                               */
++                              EMIT2(0x73 /* JNC */, 0);
++                              end_of_jmp2 = prog;
++
+                               /* xor dst_reg, dst_reg */
+                               emit_mov_imm32(&prog, false, dst_reg, 0);
+                               /* jmp byte_after_ldx */
+                               EMIT2(0xEB, 0);
+-                              /* populate jmp_offset for JNE above */
+-                              temp[4] = prog - temp - 5 /* sizeof(test + jne) */;
++                              /* populate jmp_offset for JB above to jump to xor dst_reg */
++                              end_of_jmp1[-1] = end_of_jmp2 - end_of_jmp1;
++                              /* populate jmp_offset for JNC above to jump to start_of_ldx */
+                               start_of_ldx = prog;
++                              end_of_jmp2[-1] = start_of_ldx - end_of_jmp2;
+                       }
+                       emit_ldx(&prog, BPF_SIZE(insn->code), dst_reg, src_reg, insn->off);
+                       if (BPF_MODE(insn->code) == BPF_PROBE_MEM) {
diff --git a/queue-5.15/bpf-x64-factor-out-emission-of-rex-byte-in-more-cases.patch b/queue-5.15/bpf-x64-factor-out-emission-of-rex-byte-in-more-cases.patch
new file mode 100644 (file)
index 0000000..e3b6a2c
--- /dev/null
@@ -0,0 +1,122 @@
+From 6364d7d75a0e015a405d1f8a07f267f076c36ca6 Mon Sep 17 00:00:00 2001
+From: Jie Meng <jmeng@fb.com>
+Date: Wed, 6 Oct 2021 12:41:35 -0700
+Subject: bpf, x64: Factor out emission of REX byte in more cases
+
+From: Jie Meng <jmeng@fb.com>
+
+commit 6364d7d75a0e015a405d1f8a07f267f076c36ca6 upstream.
+
+Introduce a single reg version of maybe_emit_mod() and factor out
+common code in more cases.
+
+Signed-off-by: Jie Meng <jmeng@fb.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Song Liu <songliubraving@fb.com>
+Link: https://lore.kernel.org/bpf/20211006194135.608932-1-jmeng@fb.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/net/bpf_jit_comp.c |   50 ++++++++++++++++++++++----------------------
+ 1 file changed, 26 insertions(+), 24 deletions(-)
+
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -721,6 +721,20 @@ static void maybe_emit_mod(u8 **pprog, u
+       *pprog = prog;
+ }
++/*
++ * Similar version of maybe_emit_mod() for a single register
++ */
++static void maybe_emit_1mod(u8 **pprog, u32 reg, bool is64)
++{
++      u8 *prog = *pprog;
++
++      if (is64)
++              EMIT1(add_1mod(0x48, reg));
++      else if (is_ereg(reg))
++              EMIT1(add_1mod(0x40, reg));
++      *pprog = prog;
++}
++
+ /* LDX: dst_reg = *(u8*)(src_reg + off) */
+ static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
+ {
+@@ -951,10 +965,8 @@ static int do_jit(struct bpf_prog *bpf_p
+                       /* neg dst */
+               case BPF_ALU | BPF_NEG:
+               case BPF_ALU64 | BPF_NEG:
+-                      if (BPF_CLASS(insn->code) == BPF_ALU64)
+-                              EMIT1(add_1mod(0x48, dst_reg));
+-                      else if (is_ereg(dst_reg))
+-                              EMIT1(add_1mod(0x40, dst_reg));
++                      maybe_emit_1mod(&prog, dst_reg,
++                                      BPF_CLASS(insn->code) == BPF_ALU64);
+                       EMIT2(0xF7, add_1reg(0xD8, dst_reg));
+                       break;
+@@ -968,10 +980,8 @@ static int do_jit(struct bpf_prog *bpf_p
+               case BPF_ALU64 | BPF_AND | BPF_K:
+               case BPF_ALU64 | BPF_OR | BPF_K:
+               case BPF_ALU64 | BPF_XOR | BPF_K:
+-                      if (BPF_CLASS(insn->code) == BPF_ALU64)
+-                              EMIT1(add_1mod(0x48, dst_reg));
+-                      else if (is_ereg(dst_reg))
+-                              EMIT1(add_1mod(0x40, dst_reg));
++                      maybe_emit_1mod(&prog, dst_reg,
++                                      BPF_CLASS(insn->code) == BPF_ALU64);
+                       /*
+                        * b3 holds 'normal' opcode, b2 short form only valid
+@@ -1112,10 +1122,8 @@ static int do_jit(struct bpf_prog *bpf_p
+               case BPF_ALU64 | BPF_LSH | BPF_K:
+               case BPF_ALU64 | BPF_RSH | BPF_K:
+               case BPF_ALU64 | BPF_ARSH | BPF_K:
+-                      if (BPF_CLASS(insn->code) == BPF_ALU64)
+-                              EMIT1(add_1mod(0x48, dst_reg));
+-                      else if (is_ereg(dst_reg))
+-                              EMIT1(add_1mod(0x40, dst_reg));
++                      maybe_emit_1mod(&prog, dst_reg,
++                                      BPF_CLASS(insn->code) == BPF_ALU64);
+                       b3 = simple_alu_opcodes[BPF_OP(insn->code)];
+                       if (imm32 == 1)
+@@ -1146,10 +1154,8 @@ static int do_jit(struct bpf_prog *bpf_p
+                       }
+                       /* shl %rax, %cl | shr %rax, %cl | sar %rax, %cl */
+-                      if (BPF_CLASS(insn->code) == BPF_ALU64)
+-                              EMIT1(add_1mod(0x48, dst_reg));
+-                      else if (is_ereg(dst_reg))
+-                              EMIT1(add_1mod(0x40, dst_reg));
++                      maybe_emit_1mod(&prog, dst_reg,
++                                      BPF_CLASS(insn->code) == BPF_ALU64);
+                       b3 = simple_alu_opcodes[BPF_OP(insn->code)];
+                       EMIT2(0xD3, add_1reg(b3, dst_reg));
+@@ -1459,10 +1465,8 @@ st:                     if (is_imm8(insn->off))
+               case BPF_JMP | BPF_JSET | BPF_K:
+               case BPF_JMP32 | BPF_JSET | BPF_K:
+                       /* test dst_reg, imm32 */
+-                      if (BPF_CLASS(insn->code) == BPF_JMP)
+-                              EMIT1(add_1mod(0x48, dst_reg));
+-                      else if (is_ereg(dst_reg))
+-                              EMIT1(add_1mod(0x40, dst_reg));
++                      maybe_emit_1mod(&prog, dst_reg,
++                                      BPF_CLASS(insn->code) == BPF_JMP);
+                       EMIT2_off32(0xF7, add_1reg(0xC0, dst_reg), imm32);
+                       goto emit_cond_jmp;
+@@ -1495,10 +1499,8 @@ st:                     if (is_imm8(insn->off))
+                       }
+                       /* cmp dst_reg, imm8/32 */
+-                      if (BPF_CLASS(insn->code) == BPF_JMP)
+-                              EMIT1(add_1mod(0x48, dst_reg));
+-                      else if (is_ereg(dst_reg))
+-                              EMIT1(add_1mod(0x40, dst_reg));
++                      maybe_emit_1mod(&prog, dst_reg,
++                                      BPF_CLASS(insn->code) == BPF_JMP);
+                       if (is_imm8(imm32))
+                               EMIT3(0x83, add_1reg(0xF8, dst_reg), imm32);
diff --git a/queue-5.15/btrfs-fix-invalid-delayed-ref-after-subvolume-creation-failure.patch b/queue-5.15/btrfs-fix-invalid-delayed-ref-after-subvolume-creation-failure.patch
deleted file mode 100644 (file)
index a27e55d..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-From 7a1636089acfee7562fe79aff7d1b4c57869896d Mon Sep 17 00:00:00 2001
-From: Filipe Manana <fdmanana@suse.com>
-Date: Mon, 13 Dec 2021 08:45:12 +0000
-Subject: btrfs: fix invalid delayed ref after subvolume creation failure
-
-From: Filipe Manana <fdmanana@suse.com>
-
-commit 7a1636089acfee7562fe79aff7d1b4c57869896d upstream.
-
-When creating a subvolume, at ioctl.c:create_subvol(), if we fail to
-insert the new root's root item into the root tree, we are freeing the
-metadata extent we reserved for the new root to prevent a metadata
-extent leak, as we don't abort the transaction at that point (since
-there is nothing at that point that is irreversible).
-
-However we allocated the metadata extent for the new root which we are
-creating for the new subvolume, so its delayed reference refers to the
-ID of this new root. But when we free the metadata extent we pass the
-root of the subvolume where the new subvolume is located to
-btrfs_free_tree_block() - this is incorrect because this will generate
-a delayed reference that refers to the ID of the parent subvolume's root,
-and not to ID of the new root.
-
-This results in a failure when running delayed references that leads to
-a transaction abort and a trace like the following:
-
-[3868.738042] RIP: 0010:__btrfs_free_extent+0x709/0x950 [btrfs]
-[3868.739857] Code: 68 0f 85 e6 fb ff (...)
-[3868.742963] RSP: 0018:ffffb0e9045cf910 EFLAGS: 00010246
-[3868.743908] RAX: 00000000fffffffe RBX: 00000000fffffffe RCX: 0000000000000002
-[3868.745312] RDX: 00000000fffffffe RSI: 0000000000000002 RDI: ffff90b0cd793b88
-[3868.746643] RBP: 000000000e5d8000 R08: 0000000000000000 R09: ffff90b0cd793b88
-[3868.747979] R10: 0000000000000002 R11: 00014ded97944d68 R12: 0000000000000000
-[3868.749373] R13: ffff90b09afe4a28 R14: 0000000000000000 R15: ffff90b0cd793b88
-[3868.750725] FS:  00007f281c4a8b80(0000) GS:ffff90b3ada00000(0000) knlGS:0000000000000000
-[3868.752275] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
-[3868.753515] CR2: 00007f281c6a5000 CR3: 0000000108a42006 CR4: 0000000000370ee0
-[3868.754869] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
-[3868.756228] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
-[3868.757803] Call Trace:
-[3868.758281]  <TASK>
-[3868.758655]  ? btrfs_merge_delayed_refs+0x178/0x1c0 [btrfs]
-[3868.759827]  __btrfs_run_delayed_refs+0x2b1/0x1250 [btrfs]
-[3868.761047]  btrfs_run_delayed_refs+0x86/0x210 [btrfs]
-[3868.762069]  ? lock_acquired+0x19f/0x420
-[3868.762829]  btrfs_commit_transaction+0x69/0xb20 [btrfs]
-[3868.763860]  ? _raw_spin_unlock+0x29/0x40
-[3868.764614]  ? btrfs_block_rsv_release+0x1c2/0x1e0 [btrfs]
-[3868.765870]  create_subvol+0x1d8/0x9a0 [btrfs]
-[3868.766766]  btrfs_mksubvol+0x447/0x4c0 [btrfs]
-[3868.767669]  ? preempt_count_add+0x49/0xa0
-[3868.768444]  __btrfs_ioctl_snap_create+0x123/0x190 [btrfs]
-[3868.769639]  ? _copy_from_user+0x66/0xa0
-[3868.770391]  btrfs_ioctl_snap_create_v2+0xbb/0x140 [btrfs]
-[3868.771495]  btrfs_ioctl+0xd1e/0x35c0 [btrfs]
-[3868.772364]  ? __slab_free+0x10a/0x360
-[3868.773198]  ? rcu_read_lock_sched_held+0x12/0x60
-[3868.774121]  ? lock_release+0x223/0x4a0
-[3868.774863]  ? lock_acquired+0x19f/0x420
-[3868.775634]  ? rcu_read_lock_sched_held+0x12/0x60
-[3868.776530]  ? trace_hardirqs_on+0x1b/0xe0
-[3868.777373]  ? _raw_spin_unlock_irqrestore+0x3e/0x60
-[3868.778280]  ? kmem_cache_free+0x321/0x3c0
-[3868.779011]  ? __x64_sys_ioctl+0x83/0xb0
-[3868.779718]  __x64_sys_ioctl+0x83/0xb0
-[3868.780387]  do_syscall_64+0x3b/0xc0
-[3868.781059]  entry_SYSCALL_64_after_hwframe+0x44/0xae
-[3868.781953] RIP: 0033:0x7f281c59e957
-[3868.782585] Code: 3c 1c 48 f7 d8 4c (...)
-[3868.785867] RSP: 002b:00007ffe1f83e2b8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010
-[3868.787198] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f281c59e957
-[3868.788450] RDX: 00007ffe1f83e2c0 RSI: 0000000050009418 RDI: 0000000000000003
-[3868.789748] RBP: 00007ffe1f83f300 R08: 0000000000000000 R09: 00007ffe1f83fe36
-[3868.791214] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000003
-[3868.792468] R13: 0000000000000003 R14: 00007ffe1f83e2c0 R15: 00000000000003cc
-[3868.793765]  </TASK>
-[3868.794037] irq event stamp: 0
-[3868.794548] hardirqs last  enabled at (0): [<0000000000000000>] 0x0
-[3868.795670] hardirqs last disabled at (0): [<ffffffff98294214>] copy_process+0x934/0x2040
-[3868.797086] softirqs last  enabled at (0): [<ffffffff98294214>] copy_process+0x934/0x2040
-[3868.798309] softirqs last disabled at (0): [<0000000000000000>] 0x0
-[3868.799284] ---[ end trace be24c7002fe27747 ]---
-[3868.799928] BTRFS info (device dm-0): leaf 241188864 gen 1268 total ptrs 214 free space 469 owner 2
-[3868.801133] BTRFS info (device dm-0): refs 2 lock_owner 225627 current 225627
-[3868.802056]  item 0 key (237436928 169 0) itemoff 16250 itemsize 33
-[3868.802863]          extent refs 1 gen 1265 flags 2
-[3868.803447]          ref#0: tree block backref root 1610
-(...)
-[3869.064354]  item 114 key (241008640 169 0) itemoff 12488 itemsize 33
-[3869.065421]          extent refs 1 gen 1268 flags 2
-[3869.066115]          ref#0: tree block backref root 1689
-(...)
-[3869.403834] BTRFS error (device dm-0): unable to find ref byte nr 241008640 parent 0 root 1622  owner 0 offset 0
-[3869.405641] BTRFS: error (device dm-0) in __btrfs_free_extent:3076: errno=-2 No such entry
-[3869.407138] BTRFS: error (device dm-0) in btrfs_run_delayed_refs:2159: errno=-2 No such entry
-
-Fix this by passing the new subvolume's root ID to btrfs_free_tree_block().
-This requires changing the root argument of btrfs_free_tree_block() from
-struct btrfs_root * to a u64, since at this point during the subvolume
-creation we have not yet created the struct btrfs_root for the new
-subvolume, and btrfs_free_tree_block() only needs a root ID and nothing
-else from a struct btrfs_root.
-
-This was triggered by test case generic/475 from fstests.
-
-Fixes: 67addf29004c5b ("btrfs: fix metadata extent leak after failure to create subvolume")
-CC: stable@vger.kernel.org # 4.4+
-Reviewed-by: Nikolay Borisov <nborisov@suse.com>
-Signed-off-by: Filipe Manana <fdmanana@suse.com>
-Signed-off-by: David Sterba <dsterba@suse.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- fs/btrfs/ctree.c           | 17 +++++++++--------
- fs/btrfs/ctree.h           |  7 ++++++-
- fs/btrfs/extent-tree.c     | 13 +++++++------
- fs/btrfs/free-space-tree.c |  4 ++--
- fs/btrfs/ioctl.c           |  9 +++++----
- fs/btrfs/qgroup.c          |  3 ++-
- 6 files changed, 31 insertions(+), 22 deletions(-)
-
-diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
-index 74c8e18f3720..64599625c7d7 100644
---- a/fs/btrfs/ctree.c
-+++ b/fs/btrfs/ctree.c
-@@ -462,8 +462,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
-               BUG_ON(ret < 0);
-               rcu_assign_pointer(root->node, cow);
--              btrfs_free_tree_block(trans, root, buf, parent_start,
--                                    last_ref);
-+              btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
-+                                    parent_start, last_ref);
-               free_extent_buffer(buf);
-               add_root_to_dirty_list(root);
-       } else {
-@@ -484,8 +484,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
-                               return ret;
-                       }
-               }
--              btrfs_free_tree_block(trans, root, buf, parent_start,
--                                    last_ref);
-+              btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
-+                                    parent_start, last_ref);
-       }
-       if (unlock_orig)
-               btrfs_tree_unlock(buf);
-@@ -926,7 +926,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
-               free_extent_buffer(mid);
-               root_sub_used(root, mid->len);
--              btrfs_free_tree_block(trans, root, mid, 0, 1);
-+              btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
-               /* once for the root ptr */
-               free_extent_buffer_stale(mid);
-               return 0;
-@@ -985,7 +985,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
-                       btrfs_tree_unlock(right);
-                       del_ptr(root, path, level + 1, pslot + 1);
-                       root_sub_used(root, right->len);
--                      btrfs_free_tree_block(trans, root, right, 0, 1);
-+                      btrfs_free_tree_block(trans, btrfs_root_id(root), right,
-+                                            0, 1);
-                       free_extent_buffer_stale(right);
-                       right = NULL;
-               } else {
-@@ -1030,7 +1031,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
-               btrfs_tree_unlock(mid);
-               del_ptr(root, path, level + 1, pslot);
-               root_sub_used(root, mid->len);
--              btrfs_free_tree_block(trans, root, mid, 0, 1);
-+              btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
-               free_extent_buffer_stale(mid);
-               mid = NULL;
-       } else {
-@@ -4031,7 +4032,7 @@ static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans,
-       root_sub_used(root, leaf->len);
-       atomic_inc(&leaf->refs);
--      btrfs_free_tree_block(trans, root, leaf, 0, 1);
-+      btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
-       free_extent_buffer_stale(leaf);
- }
- /*
-diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
-index 7553e9dc5f93..5fe5eccb3c87 100644
---- a/fs/btrfs/ctree.h
-+++ b/fs/btrfs/ctree.h
-@@ -2257,6 +2257,11 @@ static inline bool btrfs_root_dead(const struct btrfs_root *root)
-       return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_DEAD)) != 0;
- }
-+static inline u64 btrfs_root_id(const struct btrfs_root *root)
-+{
-+      return root->root_key.objectid;
-+}
-+
- /* struct btrfs_root_backup */
- BTRFS_SETGET_STACK_FUNCS(backup_tree_root, struct btrfs_root_backup,
-                  tree_root, 64);
-@@ -2719,7 +2724,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
-                                            u64 empty_size,
-                                            enum btrfs_lock_nesting nest);
- void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
--                         struct btrfs_root *root,
-+                         u64 root_id,
-                          struct extent_buffer *buf,
-                          u64 parent, int last_ref);
- int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
-diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
-index fc4895e6a62c..25ef6e3fd306 100644
---- a/fs/btrfs/extent-tree.c
-+++ b/fs/btrfs/extent-tree.c
-@@ -3275,20 +3275,20 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
- }
- void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
--                         struct btrfs_root *root,
-+                         u64 root_id,
-                          struct extent_buffer *buf,
-                          u64 parent, int last_ref)
- {
--      struct btrfs_fs_info *fs_info = root->fs_info;
-+      struct btrfs_fs_info *fs_info = trans->fs_info;
-       struct btrfs_ref generic_ref = { 0 };
-       int ret;
-       btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF,
-                              buf->start, buf->len, parent);
-       btrfs_init_tree_ref(&generic_ref, btrfs_header_level(buf),
--                          root->root_key.objectid, 0, false);
-+                          root_id, 0, false);
--      if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
-+      if (root_id != BTRFS_TREE_LOG_OBJECTID) {
-               btrfs_ref_tree_mod(fs_info, &generic_ref);
-               ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL);
-               BUG_ON(ret); /* -ENOMEM */
-@@ -3298,7 +3298,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
-               struct btrfs_block_group *cache;
-               bool must_pin = false;
--              if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
-+              if (root_id != BTRFS_TREE_LOG_OBJECTID) {
-                       ret = check_ref_cleanup(trans, buf->start);
-                       if (!ret) {
-                               btrfs_redirty_list_add(trans->transaction, buf);
-@@ -5472,7 +5472,8 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
-                       goto owner_mismatch;
-       }
--      btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1);
-+      btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
-+                            wc->refs[level] == 1);
- out:
-       wc->refs[level] = 0;
-       wc->flags[level] = 0;
-diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
-index a33bca94d133..3abec44c6255 100644
---- a/fs/btrfs/free-space-tree.c
-+++ b/fs/btrfs/free-space-tree.c
-@@ -1256,8 +1256,8 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
-       btrfs_tree_lock(free_space_root->node);
-       btrfs_clean_tree_block(free_space_root->node);
-       btrfs_tree_unlock(free_space_root->node);
--      btrfs_free_tree_block(trans, free_space_root, free_space_root->node,
--                            0, 1);
-+      btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
-+                            free_space_root->node, 0, 1);
-       btrfs_put_root(free_space_root);
-diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
-index 1b85d98df66b..a7533416370a 100644
---- a/fs/btrfs/ioctl.c
-+++ b/fs/btrfs/ioctl.c
-@@ -617,11 +617,12 @@ static noinline int create_subvol(struct user_namespace *mnt_userns,
-                * Since we don't abort the transaction in this case, free the
-                * tree block so that we don't leak space and leave the
-                * filesystem in an inconsistent state (an extent item in the
--               * extent tree without backreferences). Also no need to have
--               * the tree block locked since it is not in any tree at this
--               * point, so no other task can find it and use it.
-+               * extent tree with a backreference for a root that does not
-+               * exists). Also no need to have the tree block locked since it
-+               * is not in any tree at this point, so no other task can find
-+               * it and use it.
-                */
--              btrfs_free_tree_block(trans, root, leaf, 0, 1);
-+              btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
-               free_extent_buffer(leaf);
-               goto fail;
-       }
-diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
-index db680f5be745..6c037f1252b7 100644
---- a/fs/btrfs/qgroup.c
-+++ b/fs/btrfs/qgroup.c
-@@ -1219,7 +1219,8 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
-       btrfs_tree_lock(quota_root->node);
-       btrfs_clean_tree_block(quota_root->node);
-       btrfs_tree_unlock(quota_root->node);
--      btrfs_free_tree_block(trans, quota_root, quota_root->node, 0, 1);
-+      btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
-+                            quota_root->node, 0, 1);
-       btrfs_put_root(quota_root);
--- 
-2.34.1
-
diff --git a/queue-5.15/media-mxl111sf-change-mutex_init-location.patch b/queue-5.15/media-mxl111sf-change-mutex_init-location.patch
new file mode 100644 (file)
index 0000000..b40ad88
--- /dev/null
@@ -0,0 +1,112 @@
+From 44870a9e7a3c24acbb3f888b2a7cc22c9bdf7e7f Mon Sep 17 00:00:00 2001
+From: Pavel Skripkin <paskripkin@gmail.com>
+Date: Thu, 19 Aug 2021 12:42:21 +0200
+Subject: media: mxl111sf: change mutex_init() location
+
+From: Pavel Skripkin <paskripkin@gmail.com>
+
+commit 44870a9e7a3c24acbb3f888b2a7cc22c9bdf7e7f upstream.
+
+Syzbot reported, that mxl111sf_ctrl_msg() uses uninitialized
+mutex. The problem was in wrong mutex_init() location.
+
+Previous mutex_init(&state->msg_lock) call was in ->init() function, but
+dvb_usbv2_init() has this order of calls:
+
+       dvb_usbv2_init()
+         dvb_usbv2_adapter_init()
+           dvb_usbv2_adapter_frontend_init()
+             props->frontend_attach()
+
+         props->init()
+
+Since mxl111sf_* devices call mxl111sf_ctrl_msg() in ->frontend_attach()
+internally we need to initialize state->msg_lock before
+frontend_attach(). To achieve it, ->probe() call added to all mxl111sf_*
+devices, which will simply initiaize mutex.
+
+Reported-and-tested-by: syzbot+5ca0bf339f13c4243001@syzkaller.appspotmail.com
+
+Fixes: 8572211842af ("[media] mxl111sf: convert to new DVB USB")
+Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/usb/dvb-usb-v2/mxl111sf.c |   16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+@@ -931,8 +931,6 @@ static int mxl111sf_init(struct dvb_usb_
+                 .len = sizeof(eeprom), .buf = eeprom },
+       };
+-      mutex_init(&state->msg_lock);
+-
+       ret = get_chip_info(state);
+       if (mxl_fail(ret))
+               pr_err("failed to get chip info during probe");
+@@ -1074,6 +1072,14 @@ static int mxl111sf_get_stream_config_dv
+       return 0;
+ }
++static int mxl111sf_probe(struct dvb_usb_device *dev)
++{
++      struct mxl111sf_state *state = d_to_priv(dev);
++
++      mutex_init(&state->msg_lock);
++      return 0;
++}
++
+ static struct dvb_usb_device_properties mxl111sf_props_dvbt = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+@@ -1083,6 +1089,7 @@ static struct dvb_usb_device_properties
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
++      .probe             = mxl111sf_probe,
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_dvbt,
+       .tuner_attach      = mxl111sf_attach_tuner,
+@@ -1124,6 +1131,7 @@ static struct dvb_usb_device_properties
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
++      .probe             = mxl111sf_probe,
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_atsc,
+       .tuner_attach      = mxl111sf_attach_tuner,
+@@ -1165,6 +1173,7 @@ static struct dvb_usb_device_properties
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
++      .probe             = mxl111sf_probe,
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_mh,
+       .tuner_attach      = mxl111sf_attach_tuner,
+@@ -1233,6 +1242,7 @@ static struct dvb_usb_device_properties
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
++      .probe             = mxl111sf_probe,
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_atsc_mh,
+       .tuner_attach      = mxl111sf_attach_tuner,
+@@ -1311,6 +1321,7 @@ static struct dvb_usb_device_properties
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
++      .probe             = mxl111sf_probe,
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_mercury,
+       .tuner_attach      = mxl111sf_attach_tuner,
+@@ -1381,6 +1392,7 @@ static struct dvb_usb_device_properties
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
++      .probe             = mxl111sf_probe,
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_mercury_mh,
+       .tuner_attach      = mxl111sf_attach_tuner,
diff --git a/queue-5.15/mptcp-add-missing-documented-nl-params.patch b/queue-5.15/mptcp-add-missing-documented-nl-params.patch
new file mode 100644 (file)
index 0000000..98e9540
--- /dev/null
@@ -0,0 +1,53 @@
+From 6813b1928758ce64fabbb8ef157f994b7c2235fa Mon Sep 17 00:00:00 2001
+From: Matthieu Baerts <matthieu.baerts@tessares.net>
+Date: Tue, 14 Dec 2021 15:16:04 -0800
+Subject: mptcp: add missing documented NL params
+
+From: Matthieu Baerts <matthieu.baerts@tessares.net>
+
+commit 6813b1928758ce64fabbb8ef157f994b7c2235fa upstream.
+
+'loc_id' and 'rem_id' are set in all events linked to subflows but those
+were missing in the events description in the comments.
+
+Fixes: b911c97c7dc7 ("mptcp: add netlink event support")
+Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/uapi/linux/mptcp.h |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/include/uapi/linux/mptcp.h
++++ b/include/uapi/linux/mptcp.h
+@@ -129,19 +129,21 @@ struct mptcp_info {
+  * MPTCP_EVENT_REMOVED: token, rem_id
+  * An address has been lost by the peer.
+  *
+- * MPTCP_EVENT_SUB_ESTABLISHED: token, family, saddr4 | saddr6,
+- *                              daddr4 | daddr6, sport, dport, backup,
+- *                              if_idx [, error]
++ * MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id,
++ *                              saddr4 | saddr6, daddr4 | daddr6, sport,
++ *                              dport, backup, if_idx [, error]
+  * A new subflow has been established. 'error' should not be set.
+  *
+- * MPTCP_EVENT_SUB_CLOSED: token, family, saddr4 | saddr6, daddr4 | daddr6,
+- *                         sport, dport, backup, if_idx [, error]
++ * MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6,
++ *                         daddr4 | daddr6, sport, dport, backup, if_idx
++ *                         [, error]
+  * A subflow has been closed. An error (copy of sk_err) could be set if an
+  * error has been detected for this subflow.
+  *
+- * MPTCP_EVENT_SUB_PRIORITY: token, family, saddr4 | saddr6, daddr4 | daddr6,
+- *                           sport, dport, backup, if_idx [, error]
+- *       The priority of a subflow has changed. 'error' should not be set.
++ * MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6,
++ *                           daddr4 | daddr6, sport, dport, backup, if_idx
++ *                           [, error]
++ * The priority of a subflow has changed. 'error' should not be set.
+  */
+ enum mptcp_event_type {
+       MPTCP_EVENT_UNSPEC = 0,
index 5ace94490079bc283b1efc6f004fd2dca2f921ee..e4150c7e982fca48d1af7425d8bfccab221152f4 100644 (file)
@@ -151,4 +151,10 @@ drm-amd-pm-fix-reading-smu-fw-version-from-amdgpu_firmware_info-on-yc.patch
 revert-can-m_can-remove-support-for-custom-bit-timing.patch
 can-m_can-make-custom-bittiming-fields-const.patch
 can-m_can-pci-use-custom-bit-timings-for-elkhart-lake.patch
-btrfs-fix-invalid-delayed-ref-after-subvolume-creation-failure.patch
+arm-dts-imx6ull-pinfunc-fix-csi_data07__esai_tx0-pad-name.patch
+xsk-do-not-sleep-in-poll-when-need_wakeup-set.patch
+mptcp-add-missing-documented-nl-params.patch
+bpf-x64-factor-out-emission-of-rex-byte-in-more-cases.patch
+bpf-fix-extable-address-check.patch
+usb-core-make-do_proc_control-and-do_proc_bulk-killable.patch
+media-mxl111sf-change-mutex_init-location.patch
diff --git a/queue-5.15/usb-core-make-do_proc_control-and-do_proc_bulk-killable.patch b/queue-5.15/usb-core-make-do_proc_control-and-do_proc_bulk-killable.patch
new file mode 100644 (file)
index 0000000..178709e
--- /dev/null
@@ -0,0 +1,304 @@
+From ae8709b296d80c7f45aa1f35c0e7659ad69edce1 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 3 Sep 2021 13:53:12 -0400
+Subject: USB: core: Make do_proc_control() and do_proc_bulk() killable
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit ae8709b296d80c7f45aa1f35c0e7659ad69edce1 upstream.
+
+The USBDEVFS_CONTROL and USBDEVFS_BULK ioctls invoke
+usb_start_wait_urb(), which contains an uninterruptible wait with a
+user-specified timeout value.  If timeout value is very large and the
+device being accessed does not respond in a reasonable amount of time,
+the kernel will complain about "Task X blocked for more than N
+seconds", as found in testing by syzbot:
+
+INFO: task syz-executor.0:8700 blocked for more than 143 seconds.
+      Not tainted 5.14.0-rc7-syzkaller #0
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:syz-executor.0  state:D stack:23192 pid: 8700 ppid:  8455 flags:0x00004004
+Call Trace:
+ context_switch kernel/sched/core.c:4681 [inline]
+ __schedule+0xc07/0x11f0 kernel/sched/core.c:5938
+ schedule+0x14b/0x210 kernel/sched/core.c:6017
+ schedule_timeout+0x98/0x2f0 kernel/time/timer.c:1857
+ do_wait_for_common+0x2da/0x480 kernel/sched/completion.c:85
+ __wait_for_common kernel/sched/completion.c:106 [inline]
+ wait_for_common kernel/sched/completion.c:117 [inline]
+ wait_for_completion_timeout+0x46/0x60 kernel/sched/completion.c:157
+ usb_start_wait_urb+0x167/0x550 drivers/usb/core/message.c:63
+ do_proc_bulk+0x978/0x1080 drivers/usb/core/devio.c:1236
+ proc_bulk drivers/usb/core/devio.c:1273 [inline]
+ usbdev_do_ioctl drivers/usb/core/devio.c:2547 [inline]
+ usbdev_ioctl+0x3441/0x6b10 drivers/usb/core/devio.c:2713
+...
+
+To fix this problem, this patch replaces usbfs's calls to
+usb_control_msg() and usb_bulk_msg() with special-purpose code that
+does essentially the same thing (as recommended in the comment for
+usb_start_wait_urb()), except that it always uses a killable wait and
+it uses GFP_KERNEL rather than GFP_NOIO.
+
+Reported-and-tested-by: syzbot+ada0f7d3d9fd2016d927@syzkaller.appspotmail.com
+Suggested-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20210903175312.GA468440@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/devio.c |  144 ++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 111 insertions(+), 33 deletions(-)
+
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -32,6 +32,7 @@
+ #include <linux/usb.h>
+ #include <linux/usbdevice_fs.h>
+ #include <linux/usb/hcd.h>    /* for usbcore internals */
++#include <linux/usb/quirks.h>
+ #include <linux/cdev.h>
+ #include <linux/notifier.h>
+ #include <linux/security.h>
+@@ -1102,14 +1103,55 @@ static int usbdev_release(struct inode *
+       return 0;
+ }
++static void usbfs_blocking_completion(struct urb *urb)
++{
++      complete((struct completion *) urb->context);
++}
++
++/*
++ * Much like usb_start_wait_urb, but returns status separately from
++ * actual_length and uses a killable wait.
++ */
++static int usbfs_start_wait_urb(struct urb *urb, int timeout,
++              unsigned int *actlen)
++{
++      DECLARE_COMPLETION_ONSTACK(ctx);
++      unsigned long expire;
++      int rc;
++
++      urb->context = &ctx;
++      urb->complete = usbfs_blocking_completion;
++      *actlen = 0;
++      rc = usb_submit_urb(urb, GFP_KERNEL);
++      if (unlikely(rc))
++              return rc;
++
++      expire = (timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT);
++      rc = wait_for_completion_killable_timeout(&ctx, expire);
++      if (rc <= 0) {
++              usb_kill_urb(urb);
++              *actlen = urb->actual_length;
++              if (urb->status != -ENOENT)
++                      ;       /* Completed before it was killed */
++              else if (rc < 0)
++                      return -EINTR;
++              else
++                      return -ETIMEDOUT;
++      }
++      *actlen = urb->actual_length;
++      return urb->status;
++}
++
+ static int do_proc_control(struct usb_dev_state *ps,
+               struct usbdevfs_ctrltransfer *ctrl)
+ {
+       struct usb_device *dev = ps->dev;
+       unsigned int tmo;
+       unsigned char *tbuf;
+-      unsigned wLength;
++      unsigned int wLength, actlen;
+       int i, pipe, ret;
++      struct urb *urb = NULL;
++      struct usb_ctrlrequest *dr = NULL;
+       ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest,
+                             ctrl->wIndex);
+@@ -1122,51 +1164,63 @@ static int do_proc_control(struct usb_de
+                       sizeof(struct usb_ctrlrequest));
+       if (ret)
+               return ret;
++
++      ret = -ENOMEM;
+       tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+-      if (!tbuf) {
+-              ret = -ENOMEM;
++      if (!tbuf)
+               goto done;
+-      }
++      urb = usb_alloc_urb(0, GFP_NOIO);
++      if (!urb)
++              goto done;
++      dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
++      if (!dr)
++              goto done;
++
++      dr->bRequestType = ctrl->bRequestType;
++      dr->bRequest = ctrl->bRequest;
++      dr->wValue = cpu_to_le16(ctrl->wValue);
++      dr->wIndex = cpu_to_le16(ctrl->wIndex);
++      dr->wLength = cpu_to_le16(ctrl->wLength);
++
+       tmo = ctrl->timeout;
+       snoop(&dev->dev, "control urb: bRequestType=%02x "
+               "bRequest=%02x wValue=%04x "
+               "wIndex=%04x wLength=%04x\n",
+               ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+               ctrl->wIndex, ctrl->wLength);
+-      if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) {
++
++      if ((ctrl->bRequestType & USB_DIR_IN) && wLength) {
+               pipe = usb_rcvctrlpipe(dev, 0);
+-              snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0);
++              usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf,
++                              wLength, NULL, NULL);
++              snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, NULL, 0);
+               usb_unlock_device(dev);
+-              i = usb_control_msg(dev, pipe, ctrl->bRequest,
+-                                  ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
+-                                  tbuf, ctrl->wLength, tmo);
++              i = usbfs_start_wait_urb(urb, tmo, &actlen);
+               usb_lock_device(dev);
+-              snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
+-                        tbuf, max(i, 0));
+-              if ((i > 0) && ctrl->wLength) {
+-                      if (copy_to_user(ctrl->data, tbuf, i)) {
++              snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen);
++              if (!i && actlen) {
++                      if (copy_to_user(ctrl->data, tbuf, actlen)) {
+                               ret = -EFAULT;
+-                              goto done;
++                              goto recv_fault;
+                       }
+               }
+       } else {
+-              if (ctrl->wLength) {
+-                      if (copy_from_user(tbuf, ctrl->data, ctrl->wLength)) {
++              if (wLength) {
++                      if (copy_from_user(tbuf, ctrl->data, wLength)) {
+                               ret = -EFAULT;
+                               goto done;
+                       }
+               }
+               pipe = usb_sndctrlpipe(dev, 0);
+-              snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT,
+-                      tbuf, ctrl->wLength);
++              usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf,
++                              wLength, NULL, NULL);
++              snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, tbuf, wLength);
+               usb_unlock_device(dev);
+-              i = usb_control_msg(dev, pipe, ctrl->bRequest,
+-                                  ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
+-                                  tbuf, ctrl->wLength, tmo);
++              i = usbfs_start_wait_urb(urb, tmo, &actlen);
+               usb_lock_device(dev);
+-              snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
++              snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0);
+       }
+       if (i < 0 && i != -EPIPE) {
+               dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
+@@ -1174,8 +1228,15 @@ static int do_proc_control(struct usb_de
+                          current->comm, ctrl->bRequestType, ctrl->bRequest,
+                          ctrl->wLength, i);
+       }
+-      ret = i;
++      ret = (i < 0 ? i : actlen);
++
++ recv_fault:
++      /* Linger a bit, prior to the next control message. */
++      if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
++              msleep(200);
+  done:
++      kfree(dr);
++      usb_free_urb(urb);
+       free_page((unsigned long) tbuf);
+       usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) +
+                       sizeof(struct usb_ctrlrequest));
+@@ -1195,10 +1256,11 @@ static int do_proc_bulk(struct usb_dev_s
+               struct usbdevfs_bulktransfer *bulk)
+ {
+       struct usb_device *dev = ps->dev;
+-      unsigned int tmo, len1, pipe;
+-      int len2;
++      unsigned int tmo, len1, len2, pipe;
+       unsigned char *tbuf;
+       int i, ret;
++      struct urb *urb = NULL;
++      struct usb_host_endpoint *ep;
+       ret = findintfep(ps->dev, bulk->ep);
+       if (ret < 0)
+@@ -1206,14 +1268,17 @@ static int do_proc_bulk(struct usb_dev_s
+       ret = checkintf(ps, ret);
+       if (ret)
+               return ret;
++
++      len1 = bulk->len;
++      if (len1 < 0 || len1 >= (INT_MAX - sizeof(struct urb)))
++              return -EINVAL;
++
+       if (bulk->ep & USB_DIR_IN)
+               pipe = usb_rcvbulkpipe(dev, bulk->ep & 0x7f);
+       else
+               pipe = usb_sndbulkpipe(dev, bulk->ep & 0x7f);
+-      if (!usb_maxpacket(dev, pipe, !(bulk->ep & USB_DIR_IN)))
+-              return -EINVAL;
+-      len1 = bulk->len;
+-      if (len1 >= (INT_MAX - sizeof(struct urb)))
++      ep = usb_pipe_endpoint(dev, pipe);
++      if (!ep || !usb_endpoint_maxp(&ep->desc))
+               return -EINVAL;
+       ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
+       if (ret)
+@@ -1223,17 +1288,29 @@ static int do_proc_bulk(struct usb_dev_s
+        * len1 can be almost arbitrarily large.  Don't WARN if it's
+        * too big, just fail the request.
+        */
++      ret = -ENOMEM;
+       tbuf = kmalloc(len1, GFP_KERNEL | __GFP_NOWARN);
+-      if (!tbuf) {
+-              ret = -ENOMEM;
++      if (!tbuf)
+               goto done;
++      urb = usb_alloc_urb(0, GFP_KERNEL);
++      if (!urb)
++              goto done;
++
++      if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
++                      USB_ENDPOINT_XFER_INT) {
++              pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
++              usb_fill_int_urb(urb, dev, pipe, tbuf, len1,
++                              NULL, NULL, ep->desc.bInterval);
++      } else {
++              usb_fill_bulk_urb(urb, dev, pipe, tbuf, len1, NULL, NULL);
+       }
++
+       tmo = bulk->timeout;
+       if (bulk->ep & 0x80) {
+               snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);
+               usb_unlock_device(dev);
+-              i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
++              i = usbfs_start_wait_urb(urb, tmo, &len2);
+               usb_lock_device(dev);
+               snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2);
+@@ -1253,12 +1330,13 @@ static int do_proc_bulk(struct usb_dev_s
+               snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1);
+               usb_unlock_device(dev);
+-              i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
++              i = usbfs_start_wait_urb(urb, tmo, &len2);
+               usb_lock_device(dev);
+               snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0);
+       }
+       ret = (i < 0 ? i : len2);
+  done:
++      usb_free_urb(urb);
+       kfree(tbuf);
+       usbfs_decrease_memory_usage(len1 + sizeof(struct urb));
+       return ret;
diff --git a/queue-5.15/xsk-do-not-sleep-in-poll-when-need_wakeup-set.patch b/queue-5.15/xsk-do-not-sleep-in-poll-when-need_wakeup-set.patch
new file mode 100644 (file)
index 0000000..01aa564
--- /dev/null
@@ -0,0 +1,52 @@
+From bd0687c18e635b63233dc87f38058cd728802ab4 Mon Sep 17 00:00:00 2001
+From: Magnus Karlsson <magnus.karlsson@intel.com>
+Date: Tue, 14 Dec 2021 11:26:07 +0100
+Subject: xsk: Do not sleep in poll() when need_wakeup set
+
+From: Magnus Karlsson <magnus.karlsson@intel.com>
+
+commit bd0687c18e635b63233dc87f38058cd728802ab4 upstream.
+
+Do not sleep in poll() when the need_wakeup flag is set. When this
+flag is set, the application needs to explicitly wake up the driver
+with a syscall (poll, recvmsg, sendmsg, etc.) to guarantee that Rx
+and/or Tx processing will be processed promptly. But the current code
+in poll(), sleeps first then wakes up the driver. This means that no
+driver processing will occur (baring any interrupts) until the timeout
+has expired.
+
+Fix this by checking the need_wakeup flag first and if set, wake the
+driver and return to the application. Only if need_wakeup is not set
+should the process sleep if there is a timeout set in the poll() call.
+
+Fixes: 77cd0d7b3f25 ("xsk: add support for need_wakeup flag in AF_XDP rings")
+Reported-by: Keith Wiles <keith.wiles@intel.com>
+Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Link: https://lore.kernel.org/bpf/20211214102607.7677-1-magnus.karlsson@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xdp/xsk.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -692,8 +692,6 @@ static __poll_t xsk_poll(struct file *fi
+       struct xdp_sock *xs = xdp_sk(sk);
+       struct xsk_buff_pool *pool;
+-      sock_poll_wait(file, sock, wait);
+-
+       if (unlikely(!xsk_is_bound(xs)))
+               return mask;
+@@ -705,6 +703,8 @@ static __poll_t xsk_poll(struct file *fi
+               else
+                       /* Poll needs to drive Tx also in copy mode */
+                       __xsk_sendmsg(sk);
++      } else {
++              sock_poll_wait(file, sock, wait);
+       }
+       if (xs->rx && !xskq_prod_is_empty(xs->rx))