5.12.3-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 282/384 tools/power/turbostat: Fix turbostat for AMD Zen CPUs
In reply to Greg Kroah-HartmanFrom: Bas Nieuwenhuizen <[email protected]>
commit 301b1d3a9104f4f3a8ab4171cf88d0f55d632b41 upstream.
It was reported that on Zen+ system turbostat started exiting, which was tracked down to the MSR_PKG_ENERGY_STAT read failing because offset_to_idx wasn't returning a non-negative index.
This patch combined the modification from Bingsong Si and
Bas Nieuwenhuizen and addd the MSR to the index system as alternative for MSR_PKG_ENERGY_STATUS.
--- tools/power/x86/turbostat/turbostat.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/power/x86/turbostat/turbostat.c +6 -2
@@ -297,7 +297,10 @@ int idx_to_offset(int idx)switch (idx) {case IDX_PKG_ENERGY : - offset =MSR_PKG_ENERGY_STATUS ; +if (do_rapl &RAPL_AMD_F17H ) + offset =MSR_PKG_ENERGY_STAT ; +else + offset =MSR_PKG_ENERGY_STATUS ;break ;case IDX_DRAM_ENERGY : offset =MSR_DRAM_ENERGY_STATUS ;
@@ -326,6 +329,7 @@ int offset_to_idx(int offset)switch (offset) {case MSR_PKG_ENERGY_STATUS : +case MSR_PKG_ENERGY_STAT : idx =IDX_PKG_ENERGY ;break ;case MSR_DRAM_ENERGY_STATUS :
@@ -353,7 +357,7 @@ int idx_valid(int idx) {switch (idx) {case IDX_PKG_ENERGY : -return do_rapl &RAPL_PKG ; +return do_rapl & (RAPL_PKG |RAPL_AMD_F17H );case IDX_DRAM_ENERGY :return do_rapl &RAPL_DRAM ;case IDX_PP0_ENERGY :
Greg Kroah-Hartman
maintainerPATCH 283/384 btrfs: fix race when picking most recent mod log operation for an old root
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
[ Upstream commit f9690f426b2134cc3e74bfc5d9dfd6a4b2ca5281 ]
Commit dbcc7d57bffc0c ("btrfs: fix race when cloning extent buffer during rewind of an old root"), fixed a race when we need to rewind the extent buffer of an old root. It was caused by picking a new mod log operation for the extent buffer while getting a cloned extent buffer with an outdated number of items (off by -1), because we cloned the extent buffer without locking it first.
However there is still another similar race, but in the opposite direction. The cloned extent buffer has a number of items that does not match the number of tree mod log operations that are going to be replayed. This is because right after we got the last (most recent) tree mod log operation to replay and before locking and cloning the extent buffer, another task adds a new pointer to the extent buffer, which results in adding a new tree mod log operation and incrementing the number of items in the extent buffer. So after cloning we have mismatch between the number of items in the extent buffer and the number of mod log operations we are going to apply to it. This results in hitting a BUG_ON() that produces the following stack trace:
------------[ cut here ]------------
kernel BUG at fs/btrfs/tree-mod-log.c:675!
invalid opcode: 0000 [#1] SMP KASAN PTI
CPU: 3 PID: 4811 Comm: crawl_1215 Tainted: G W 5.12.0-7d1efdf501f8-misc-next+ #99
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
RIP: 0010:tree_mod_log_rewind+0x3b1/0x3c0
Code: 05 48 8d 74 10 (...)
RSP: 0018:ffffc90001027090 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff8880a8514600 RCX: ffffffffaa9e59b6
RDX: 0000000000000007 RSI: dffffc0000000000 RDI: ffff8880a851462c
RBP: ffffc900010270e0 R08: 00000000000000c0 R09: ffffed1004333417
R10: ffff88802199a0b7 R11: ffffed1004333416 R12: 000000000000000e
R13: ffff888135af8748 R14: ffff88818766ff00 R15: ffff8880a851462c
FS: 00007f29acf62700(0000) GS:ffff8881f2200000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f0e6013f718 CR3: 000000010d42e003 CR4: 0000000000170ee0
Call Trace:
btrfs_get_old_root+0x16a/0x5c0
? lock_downgrade+0x400/0x400
btrfs_search_old_slot+0x192/0x520
? btrfs_search_slot+0x1090/0x1090
? free_extent_buffer.part.61+0xd7/0x140
? free_extent_buffer+0x13/0x20
resolve_indirect_refs+0x3e9/0xfc0
? lock_downgrade+0x400/0x400
? __kasan_check_read+0x11/0x20
? add_prelim_ref.part.11+0x150/0x150
? lock_downgrade+0x400/0x400
? __kasan_check_read+0x11/0x20
? lock_acquired+0xbb/0x620
? __kasan_check_write+0x14/0x20
? do_raw_spin_unlock+0xa8/0x140
? rb_insert_color+0x340/0x360
? prelim_ref_insert+0x12d/0x430
find_parent_nodes+0x5c3/0x1830
? stack_trace_save+0x87/0xb0
? resolve_indirect_refs+0xfc0/0xfc0
? fs_reclaim_acquire+0x67/0xf0
? __kasan_check_read+0x11/0x20
? lockdep_hardirqs_on_prepare+0x210/0x210
? fs_reclaim_acquire+0x67/0xf0
? __kasan_check_read+0x11/0x20
? ___might_sleep+0x10f/0x1e0
? __kasan_kmalloc+0x9d/0xd0
? trace_hardirqs_on+0x55/0x120
btrfs_find_all_roots_safe+0x142/0x1e0
? find_parent_nodes+0x1830/0x1830
? trace_hardirqs_on+0x55/0x120
? ulist_free+0x1f/0x30
? btrfs_inode_flags_to_xflags+0x50/0x50
iterate_extent_inodes+0x20e/0x580
? tree_backref_for_extent+0x230/0x230
? release_extent_buffer+0x225/0x280
? read_extent_buffer+0xdd/0x110
? lock_downgrade+0x400/0x400
? __kasan_check_read+0x11/0x20
? lock_acquired+0xbb/0x620
? __kasan_check_write+0x14/0x20
? do_raw_spin_unlock+0xa8/0x140
? _raw_spin_unlock+0x22/0x30
? release_extent_buffer+0x225/0x280
iterate_inodes_from_logical+0x129/0x170
? iterate_inodes_from_logical+0x129/0x170
? btrfs_inode_flags_to_xflags+0x50/0x50
? iterate_extent_inodes+0x580/0x580
? __vmalloc_node+0x92/0xb0
? init_data_container+0x34/0xb0
? init_data_container+0x34/0xb0
? kvmalloc_node+0x60/0x80
btrfs_ioctl_logical_to_ino+0x158/0x230
btrfs_ioctl+0x2038/0x4360
? __kasan_check_write+0x14/0x20
? mmput+0x3b/0x220
? btrfs_ioctl_get_supported_features+0x30/0x30
? __kasan_check_read+0x11/0x20
? __kasan_check_read+0x11/0x20
? lock_release+0xc8/0x650
? __might_fault+0x64/0xd0
? __kasan_check_read+0x11/0x20
? lock_downgrade+0x400/0x400
? lockdep_hardirqs_on_prepare+0x210/0x210
? lockdep_hardirqs_on_prepare+0x13/0x210
? _raw_spin_unlock_irqrestore+0x51/0x63
? __kasan_check_read+0x11/0x20
? do_vfs_ioctl+0xfc/0x9d0
? ioctl_file_clone+0xe0/0xe0
? lock_downgrade+0x400/0x400
? lockdep_hardirqs_on_prepare+0x210/0x210
? __kasan_check_read+0x11/0x20
? lock_release+0xc8/0x650
? __task_pid_nr_ns+0xd3/0x250
? __kasan_check_read+0x11/0x20
? __fget_files+0x160/0x230
? __fget_light+0xf2/0x110
__x64_sys_ioctl+0xc3/0x100
do_syscall_64+0x37/0x80
entry_SYSCALL_64_after_hwframe+0x44/0xae
RIP: 0033:0x7f29ae85b427
Code: 00 00 90 48 8b (...)
RSP: 002b:00007f29acf5fcf8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007f29acf5ff40 RCX: 00007f29ae85b427
RDX: 00007f29acf5ff48 RSI: 00000000c038943b RDI: 0000000000000003
RBP: 0000000001000000 R08: 0000000000000000 R09: 00007f29acf60120
R10: 00005640d5fc7b00 R11: 0000000000000246 R12: 0000000000000003
R13: 00007f29acf5ff48 R14: 00007f29acf5ff40 R15: 00007f29acf5fef8
Modules linked in:
---[ end trace 85e5fce078dfbe04 ]--- (gdb) l *(tree_mod_log_rewind+0x3b1)
0xffffffff819e5b21 is in tree_mod_log_rewind (fs/btrfs/tree-mod-log.c:675).
670 * the modification. As we're going backwards, we do the 671 * opposite of each operation here. 672 */
673 switch (tm->op) {
674 case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING:
675 BUG_ON(tm->slot < n);
676 fallthrough;
677 case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_MOVING:
678 case BTRFS_MOD_LOG_KEY_REMOVE:
679 btrfs_set_node_key(eb, &tm->key, tm->slot);
(gdb) quit
The following steps explain in more detail how it happens:
1) We have one tree mod log user (through fiemap or the logical ino ioctl), with a sequence number of 1, so we have fs_info->tree_mod_seq == 1. This is task A;
2) Another task is at ctree.c:balance_level() and we have eb X currently as the root of the tree, and we promote its single child, eb Y, as the new root.
Then, at ctree.c:balance_level(), we call:
ret = btrfs_tree_mod_log_insert_root(root->node, child, true);
3) At btrfs_tree_mod_log_insert_root() we create a tree mod log operation of type BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING, with a ->logical field pointing to ebX->start. We only have one item in eb X, so we create only one tree mod log operation, and store in the "tm_list" array;
4) Then, still at btrfs_tree_mod_log_insert_root(), we create a tree mod log element of operation type BTRFS_MOD_LOG_ROOT_REPLACE, ->logical set to ebY->start, ->old_root.logical set to ebX->start, ->old_root.level set to the level of eb X and ->generation set to the generation of eb X;
5) Then btrfs_tree_mod_log_insert_root() calls tree_mod_log_free_eb() with "tm_list" as argument. After that, tree_mod_log_free_eb() calls tree_mod_log_insert(). This inserts the mod log operation of type BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING from step 3 into the rbtree with a sequence number of 2 (and fs_info->tree_mod_seq set to 2);
6) Then, after inserting the "tm_list" single element into the tree mod log rbtree, the BTRFS_MOD_LOG_ROOT_REPLACE element is inserted, which gets the sequence number 3 (and fs_info->tree_mod_seq set to 3);
7) Back to ctree.c:balance_level(), we free eb X by calling btrfs_free_tree_block() on it. Because eb X was created in the current transaction, has no other references and writeback did not happen for it, we add it back to the free space cache/tree;
8) Later some other task B allocates the metadata extent from eb X, since it is marked as free space in the space cache/tree, and uses it as a node for some other btree;
9) The tree mod log user task calls btrfs_search_old_slot(), which calls btrfs_get_old_root(), and finally that calls tree_mod_log_oldest_root() with time_seq == 1 and eb_root == eb Y;
10) The first iteration of the while loop finds the tree mod log element with sequence number 3, for the logical address of eb Y and of type BTRFS_MOD_LOG_ROOT_REPLACE;
11) Because the operation type is BTRFS_MOD_LOG_ROOT_REPLACE, we don't
break out of the loop, and set root_logical to point to
tm->old_root.logical, which corresponds to the logical address of
eb X;12) On the next iteration of the while loop, the call to tree_mod_log_search_oldest() returns the smallest tree mod log element for the logical address of eb X, which has a sequence number of 2, an operation type of BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING and corresponds to the old slot 0 of eb X (eb X had only 1 item in it before being freed at step 7);
13) We then break out of the while loop and return the tree mod log operation of type BTRFS_MOD_LOG_ROOT_REPLACE (eb Y), and not the one for slot 0 of eb X, to btrfs_get_old_root();
14) At btrfs_get_old_root(), we process the BTRFS_MOD_LOG_ROOT_REPLACE operation and set "logical" to the logical address of eb X, which was the old root. We then call tree_mod_log_search() passing it the logical address of eb X and time_seq == 1;
15) But before calling tree_mod_log_search(), task B locks eb X, adds a key to eb X, which results in adding a tree mod log operation of type BTRFS_MOD_LOG_KEY_ADD, with a sequence number of 4, to the tree mod log, and increments the number of items in eb X from 0 to 1. Now fs_info->tree_mod_seq has a value of 4;
16) Task A then calls tree_mod_log_search(), which returns the most recent tree mod log operation for eb X, which is the one just added by task B at the previous step, with a sequence number of 4, a type of BTRFS_MOD_LOG_KEY_ADD and for slot 0;
17) Before task A locks and clones eb X, task A adds another key to eb X, which results in adding a new BTRFS_MOD_LOG_KEY_ADD mod log operation, with a sequence number of 5, for slot 1 of eb X, increments the number of items in eb X from 1 to 2, and unlocks eb X.
Now fs_info->tree_mod_seq has a value of 5;
18) Task A then locks eb X and clones it. The clone has a value of 2 for the number of items and the pointer "tm" points to the tree mod log operation with sequence number 4, not the most recent one with a sequence number of 5, so there is mismatch between the number of mod log operations that are going to be applied to the cloned version of eb X and the number of items in the clone;
19) Task A then calls tree_mod_log_rewind() with the clone of eb X, the tree mod log operation with sequence number 4 and a type of BTRFS_MOD_LOG_KEY_ADD, and time_seq == 1;
20) At tree_mod_log_rewind(), we set the local variable "n" with a value of 2, which is the number of items in the clone of eb X.
Then in the first iteration of the while loop, we process the mod log operation with sequence number 4, which is targeted at slot 0 and has a type of BTRFS_MOD_LOG_KEY_ADD. This results in decrementing "n" from 2 to 1.
Then we pick the next tree mod log operation for eb X, which is the tree mod log operation with a sequence number of 2, a type of BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING and for slot 0, it is the one added in step 5 to the tree mod log tree.
We go back to the top of the loop to process this mod log operation, and because its slot is 0 and "n" has a value of 1, we hit the BUG_ON:
(...)
switch (tm->op) {
case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING:
BUG_ON(tm->slot < n); fallthrough;
(...)
Fix this by checking for a more recent tree mod log operation after locking and cloning the extent buffer of the old root node, and use it as the first operation to apply to the cloned extent buffer when rewinding it.
Stable backport notes: due to moved code and renames, in =< 5.11 the change should be applied to ctree.c:get_old_root.
--- fs/btrfs/ctree.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
fs/btrfs/ctree.c +20 -0
@@ -1365,10 +1365,30 @@ get_old_root(struct btrfs_root *root, u64 time_seq)"failed to read tree block %llu from get_old_root" , logical); }else { +struct tree_mod_elem *tm2; +btrfs_tree_read_lock (old); eb =btrfs_clone_extent_buffer (old); +/* +* After the lookup for the most recent tree mod operation +* above and before we locked and cloned the extent buffer +* 'old', a new tree mod log operation may have been added. +* So lookup for a more recent one to make sure the number +* of mod log operations we replay is consistent with the +* number of items we have in the cloned extent buffer, +* otherwise we can hit a BUG_ON when rewinding the extent +* buffer. +*/ + tm2 =tree_mod_log_search (fs_info, logical, time_seq);btrfs_tree_read_unlock (old);free_extent_buffer (old); +ASSERT (tm2); +ASSERT (tm2 == tm || tm2->seq > tm->seq); +if (!tm2 || tm2->seq < tm->seq) { +free_extent_buffer (eb); +return NULL ; + } + tm = tm2; } }else if (old_root) { eb_root_owner =btrfs_header_owner (eb_root);
Signature · 1 line
2.30.2
Greg Kroah-Hartman
maintainerPATCH 284/384 btrfs: fix a potential hole punching failure
In reply to Greg Kroah-HartmanFrom: BingJing Chang <[email protected]>
[ Upstream commit 3227788cd369d734d2d3cd94f8af7536b60fa552 ]
In commit d77815461f04 ("btrfs: Avoid trucating page or punching hole in a already existed hole."), existing holes can be skipped by calling find_first_non_hole() to adjust start and len. However, if the given len is invalid and large, when an EXTENT_MAP_HOLE extent is found, len will not be set to zero because (em->start + em->len) is less than (start + len). Then the ret will be 1 but len will not be set to 0. The propagated non-zero ret will result in fallocate failure.
In the while-loop of btrfs_replace_file_extents(), len is not updated every time before it calls find_first_non_hole(). That is, after btrfs_drop_extents() successfully drops the last non-hole file extent, it may fail with ENOSPC when attempting to drop a file extent item representing a hole. The problem can happen. After it calls find_first_non_hole(), the cur_offset will be adjusted to be larger than or equal to end. However, since the len is not set to zero, the break-loop condition (ret && !len) will not be met. After it leaves the while-loop, fallocate will return 1, which is an unexpected return value.
We're not able to construct a reproducible way to let btrfs_drop_extents() fail with ENOSPC after it drops the last non-hole file extent but with remaining holes left. However, it's quite easy to fix. We just need to update and check the len every time before we call find_first_non_hole(). To make the while loop more readable, we also pull the variable updates to the bottom of loop like this:
while (cur_offset < end) {
...
// update cur_offset & len
// advance cur_offset & len in hole-punching case if needed}
--- fs/btrfs/file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/btrfs/file.c +3 -3
@@ -2729,8 +2729,6 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path, extent_info->file_offset += replace_len; } - cur_offset = drop_args.drop_end; - ret =btrfs_update_inode (trans, root,BTRFS_I (inode));if (ret)break ;
@@ -2750,7 +2748,9 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,BUG_ON (ret);/* shouldn't happen */ trans->block_rsv = rsv; -if (!extent_info) { + cur_offset = drop_args.drop_end; + len = end - cur_offset; +if (!extent_info && len) { ret =find_first_non_hole (BTRFS_I (inode), &cur_offset, &len);if (unlikely (ret <0 ))
Signature · 1 line
2.30.2
Greg Kroah-Hartman
maintainerPATCH 285/384 arm64/vdso: Discard .note.gnu.property sections in vDSO
In reply to Greg Kroah-HartmanFrom: Bill Wendling <[email protected]>
[ Upstream commit 388708028e6937f3fc5fc19aeeb847f8970f489c ]
The arm64 assembler in binutils 2.32 and above generates a program property note in a note section, .note.gnu.property, to encode used x86 ISAs and features. But the kernel linker script only contains a single NOTE segment:
PHDRS
{
text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
note PT_NOTE FLAGS(4); /* PF_R */
}The NOTE segment generated by the vDSO linker script is aligned to 4 bytes. But the .note.gnu.property section must be aligned to 8 bytes on arm64.
$ readelf -n vdso64.so
Displaying notes found in: .note
Owner Data size Description
Linux 0x00000004 Unknown note type: (0x00000000)
description data: 06 00 00 00 readelf: Warning: note with invalid namesz and/or descsz found at offset 0x20
readelf: Warning: type: 0x78, namesize: 0x00000100, descsize: 0x756e694c, alignment: 8
Since the note.gnu.property section in the vDSO is not checked by the dynamic linker, discard the .note.gnu.property sections in the vDSO.
Similar to commit 4caffe6a28d31 ("x86/vdso: Discard .note.gnu.property sections in vDSO"), but for arm64.
--- arch/arm64/kernel/vdso/vdso.lds.S | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
arch/arm64/kernel/vdso/vdso.lds.S +7 -1
@@ -31,6 +31,13 @@ SECTIONS .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } + /* + * Discard .note.gnu.property sections which are unused and have + * different alignment requirement from vDSO note sections. + */ + /DISCARD/ : { + *(.note.GNU-stack .note.gnu.property) + } .note : { *(.note.*) } :text :note . = ALIGN(16);
@@ -48,7 +55,6 @@ SECTIONS PROVIDE(end = .); /DISCARD/ : { - *(.note.GNU-stack) *(.data .data.* .gnu.linkonce.d.* .sdata*) *(.bss .sbss .dynbss .dynsbss) *(.eh_frame .eh_frame_hdr)
Signature · 1 line
2.30.2
Greg Kroah-Hartman
maintainerPATCH 286/384 Makefile: Move -Wno-unused-but-set-variable out of GCC only block
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit 885480b084696331bea61a4f7eba10652999a9c1 upstream.
Currently, -Wunused-but-set-variable is only supported by GCC so it is disabled unconditionally in a GCC only block (it is enabled with W=1). clang currently has its implementation for this warning in review so preemptively move this statement out of the GCC only block and wrap it with cc-disable-warning so that both compilers function the same.
--- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
Makefile +4 -4
@@ -775,16 +775,16 @@ KBUILD_CFLAGS += -Wno-gnu KBUILD_CFLAGS += -mno-global-merge else -# These warnings generated too much noise in a regular build. -# Use make W=1 to enable them (see scripts/Makefile.extrawarn) -KBUILD_CFLAGS += -Wno-unused-but-set-variable - # Warn about unmarked fall-throughs in switch statement. # Disabled for clang while comment to attribute conversion happens and # https://github.com/ClangBuiltLinux/linux/issues/636 is discussed. KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,) endif +# These warnings generated too much noise in a regular build. +# Use make W=1 to enable them (see scripts/Makefile.extrawarn) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) + KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) ifdef CONFIG_FRAME_POINTER KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
Greg Kroah-Hartman
maintainerPATCH 287/384 riscv/kprobe: fix kernel panic when invoking sys_read traced by kprobe
In reply to Greg Kroah-HartmanFrom: Liao Chang <[email protected]>
commit b1ebaa0e1318494a7637099a26add50509e37964 upstream.
The execution of sys_read end up hitting a BUG_ON() in __find_get_block after installing kprobe at sys_read, the BUG message like the following:
[ 65.708663] ------------[ cut here ]------------ [ 65.709987] kernel BUG at fs/buffer.c:1251! [ 65.711283] Kernel BUG [#1] [ 65.712032] Modules linked in: [ 65.712925] CPU: 0 PID: 51 Comm: sh Not tainted 5.12.0-rc4 #1 [ 65.714407] Hardware name: riscv-virtio,qemu (DT) [ 65.715696] epc : __find_get_block+0x218/0x2c8 [ 65.716835] ra : __getblk_gfp+0x1c/0x4a [ 65.717831] epc : ffffffe00019f11e ra : ffffffe00019f56a sp : ffffffe002437930 [ 65.719553] gp : ffffffe000f06030 tp : ffffffe0015abc00 t0 : ffffffe00191e038 [ 65.721290] t1 : ffffffe00191e038 t2 : 000000000000000a s0 : ffffffe002437960 [ 65.723051] s1 : ffffffe00160ad00 a0 : ffffffe00160ad00 a1 : 000000000000012a [ 65.724772] a2 : 0000000000000400 a3 : 0000000000000008 a4 : 0000000000000040 [ 65.726545] a5 : 0000000000000000 a6 : ffffffe00191e000 a7 : 0000000000000000 [ 65.728308] s2 : 000000000000012a s3 : 0000000000000400 s4 : 0000000000000008 [ 65.730049] s5 : 000000000000006c s6 : ffffffe00240f800 s7 : ffffffe000f080a8 [ 65.731802] s8 : 0000000000000001 s9 : 000000000000012a s10: 0000000000000008 [ 65.733516] s11: 0000000000000008 t3 : 00000000000003ff t4 : 000000000000000f [ 65.734434] t5 : 00000000000003ff t6 : 0000000000040000 [ 65.734613] status: 0000000000000100 badaddr: 0000000000000000 cause: 0000000000000003 [ 65.734901] Call Trace: [ 65.735076] [<ffffffe00019f11e>] __find_get_block+0x218/0x2c8 [ 65.735417] [<ffffffe00020017a>] __ext4_get_inode_loc+0xb2/0x2f6 [ 65.735618] [<ffffffe000201b6c>] ext4_get_inode_loc+0x3a/0x8a [ 65.735802] [<ffffffe000203380>] ext4_reserve_inode_write+0x2e/0x8c [ 65.735999] [<ffffffe00020357a>] __ext4_mark_inode_dirty+0x4c/0x18e [ 65.736208] [<ffffffe000206bb0>] ext4_dirty_inode+0x46/0x66 [ 65.736387] [<ffffffe000192914>] __mark_inode_dirty+0x12c/0x3da [ 65.736576] [<ffffffe000180dd2>] touch_atime+0x146/0x150 [ 65.736748] [<ffffffe00010d762>] filemap_read+0x234/0x246 [ 65.736920] [<ffffffe00010d834>] generic_file_read_iter+0xc0/0x114 [ 65.737114] [<ffffffe0001f5d7a>] ext4_file_read_iter+0x42/0xea [ 65.737310] [<ffffffe000163f2c>] new_sync_read+0xe2/0x15a [ 65.737483] [<ffffffe000165814>] vfs_read+0xca/0xf2 [ 65.737641] [<ffffffe000165bae>] ksys_read+0x5e/0xc8 [ 65.737816] [<ffffffe000165c26>] sys_read+0xe/0x16 [ 65.737973] [<ffffffe000003972>] ret_from_syscall+0x0/0x2 [ 65.738858] ---[ end trace fe93f985456c935d ]---
A simple reproducer looks like:
echo 'p:myprobe sys_read fd=%a0 buf=%a1 count=%a2' > /sys/kernel/debug/tracing/kprobe_events echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
cat /sys/kernel/debug/tracing/trace
Here's what happens to hit that BUG_ON():
1) After installing kprobe at entry of sys_read, the first instruction is replaced by 'ebreak' instruction on riscv64 platform.
2) Once kernel reach the 'ebreak' instruction at the entry of sys_read, it trap into the riscv breakpoint handler, where it do something to setup for coming single-step of origin instruction, including backup the 'sstatus' in pt_regs, followed by disable interrupt during single stepping via clear 'SIE' bit of 'sstatus' in pt_regs.
3) Then kernel restore to the instruction slot contains two instructions, one is original instruction at entry of sys_read, the other is 'ebreak'. Here it trigger a 'Instruction page fault' exception (value at 'scause' is '0xc'), if PF is not filled into PageTabe for that slot yet.
4) Again kernel trap into page fault exception handler, where it choose different policy according to the state of running kprobe. Because afte 2) the state is KPROBE_HIT_SS, so kernel reset the current kprobe and 'pc' points back to the probe address.
5) Because 'epc' point back to 'ebreak' instrution at sys_read probe, kernel trap into breakpoint handler again, and repeat the operations at 2), however 'sstatus' without 'SIE' is keep at 4), it cause the real 'sstatus' saved at 2) is overwritten by the one withou 'SIE'.
6) When kernel cross the probe the 'sstatus' CSR restore with value without 'SIE', and reach __find_get_block where it requires the interrupt must be enabled.
Fix this is very trivial, just restore the value of 'sstatus' in pt_regs with backup one at 2) when the instruction being single stepped cause a page fault.
--- arch/riscv/kernel/probes/kprobes.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/riscv/kernel/probes/kprobes.c +3 -1
@@ -260,8 +260,10 @@ int __kprobes kprobe_fault_handler(strucif (kcb->kprobe_status ==KPROBE_REENTER )restore_previous_kprobe (kcb); -else +else { +kprobes_restore_local_irqflag (kcb, regs);reset_current_kprobe (); + }break ;case KPROBE_HIT_ACTIVE :
Greg Kroah-Hartman
maintainerPATCH 288/384 fs: fix reporting supported extra file attributes for statx()
In reply to Greg Kroah-HartmanFrom: Theodore Ts'o <[email protected]>
commit 5afa7e8b70d65819245fece61a65fd753b4aae33 upstream.
statx(2) notes that any attribute that is not indicated as supported by stx_attributes_mask has no usable value. Commits 801e523796004 ("fs: move generic stat response attr handling to vfs_getattr_nosec") and 712b2698e4c02 ("fs/stat: Define DAX statx attribute") sets STATX_ATTR_AUTOMOUNT and STATX_ATTR_DAX, respectively, without setting stx_attributes_mask, which can cause xfstests generic/532 to fail.
Fix this in the same way as commit 1b9598c8fb99 ("xfs: fix reporting supported extra file attributes for statx()")
--- fs/stat.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/stat.c +8 -0
@@ -86,12 +86,20 @@ int vfs_getattr_nosec(const struct path/* SB_NOATIME means filesystem supplies dummy atime value */ if (inode->i_sb->s_flags &SB_NOATIME ) stat->result_mask &= ~STATX_ATIME ; + +/* +* Note: If you add another clause to set an attribute flag, please +* update attributes_mask below. +*/ if (IS_AUTOMOUNT (inode)) stat->attributes |=STATX_ATTR_AUTOMOUNT ;if (IS_DAX (inode)) stat->attributes |=STATX_ATTR_DAX ; + stat->attributes_mask |= (STATX_ATTR_AUTOMOUNT | +STATX_ATTR_DAX ); + mnt_userns =mnt_user_ns (path->mnt);if (inode->i_op->getattr) return inode->i_op->getattr(mnt_userns, path, stat,
Greg Kroah-Hartman
maintainerPATCH 289/384 virtiofs: fix memory leak in virtio_fs_probe()
In reply to Greg Kroah-HartmanFrom: Luis Henriques <[email protected]>
commit c79c5e0178922a9e092ec8fed026750f39dcaef4 upstream.
When accidentally passing twice the same tag to qemu, kmemleak ended up reporting a memory leak in virtiofs. Also, looking at the log I saw the following error (that's when I realised the duplicated tag):
virtiofs: probe of virtio5 failed with error -17
Here's the kmemleak log for reference:
unreferenced object 0xffff888103d47800 (size 1024):
comm "systemd-udevd", pid 118, jiffies 4294893780 (age 18.340s) hex dump (first 32 bytes):
00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N..........
ff ff ff ff ff ff ff ff 80 90 02 a0 ff ff ff ff ................
backtrace:
[<000000000ebb87c1>] virtio_fs_probe+0x171/0x7ae [virtiofs]
[<00000000f8aca419>] virtio_dev_probe+0x15f/0x210
[<000000004d6baf3c>] really_probe+0xea/0x430
[<00000000a6ceeac8>] device_driver_attach+0xa8/0xb0
[<00000000196f47a7>] __driver_attach+0x98/0x140
[<000000000b20601d>] bus_for_each_dev+0x7b/0xc0
[<00000000399c7b7f>] bus_add_driver+0x11b/0x1f0
[<0000000032b09ba7>] driver_register+0x8f/0xe0
[<00000000cdd55998>] 0xffffffffa002c013
[<000000000ea196a2>] do_one_initcall+0x64/0x2e0
[<0000000008f727ce>] do_init_module+0x5c/0x260
[<000000003cdedab6>] __do_sys_finit_module+0xb5/0x120
[<00000000ad2f48c6>] do_syscall_64+0x33/0x40
[<00000000809526b5>] entry_SYSCALL_64_after_hwframe+0x44/0xae--- fs/fuse/virtio_fs.c | 1 + 1 file changed, 1 insertion(+)
fs/fuse/virtio_fs.c +1 -0
@@ -896,6 +896,7 @@ static int virtio_fs_probe(struct virtio out_vqs: vdev->config->reset (vdev);virtio_fs_cleanup_vqs (vdev, fs); +kfree (fs->vqs); out: vdev->priv =NULL ;
Greg Kroah-Hartman
maintainerPATCH 290/384 kcsan, debugfs: Move debugfs file creation out of early init
In reply to Greg Kroah-HartmanFrom: Marco Elver <[email protected]>
commit e36299efe7d749976fbdaaf756dee6ef32543c2c upstream.
Commit 56348560d495 ("debugfs: do not attempt to create a new file before the filesystem is initalized") forbids creating new debugfs files until debugfs is fully initialized. This means that KCSAN's debugfs file creation, which happened at the end of __init(), no longer works. And was apparently never supposed to work!
However, there is no reason to create KCSAN's debugfs file so early. This commit therefore moves its creation to a late_initcall() callback.
--- kernel/kcsan/core.c | 2 -- kernel/kcsan/debugfs.c | 4 +++- kernel/kcsan/kcsan.h | 5 ----- 3 files changed, 3 insertions(+), 8 deletions(-)
kernel/kcsan/core.c +0 -2
@@ -639,8 +639,6 @@ void __init kcsan_init(void)BUG_ON (!in_task ()); -kcsan_debugfs_init (); -for_each_possible_cpu (cpu)per_cpu (kcsan_rand_state, cpu) = (u32 )get_cycles ();
kernel/kcsan/debugfs.c +3 -1
@@ -261,7 +261,9 @@ static const struct file_operations debu .release = single_release }; -void __init kcsan_debugfs_init (void ) +static void __init kcsan_debugfs_init (void ) {debugfs_create_file ("kcsan" ,0644 ,NULL ,NULL , &debugfs_ops); } + +late_initcall (kcsan_debugfs_init);
kernel/kcsan/kcsan.h +0 -5
@@ -31,11 +31,6 @@ void kcsan_save_irqtrace(struct task_strvoid kcsan_restore_irqtrace (struct task_struct *task);/* -* Initialize debugfs file. -*/ -void kcsan_debugfs_init (void ); - -/* * Statistics counters displayed via debugfs; should only be modified in * slow-paths. */
Greg Kroah-Hartman
maintainerPATCH 291/384 ubifs: Only check replay with inode type to judge if inode linked
In reply to Greg Kroah-HartmanFrom: Guochun Mao <[email protected]>
commit 3e903315790baf4a966436e7f32e9c97864570ac upstream.
Conside the following case, it just write a big file into flash, when complete writing, delete the file, and then power off promptly. Next time power on, we'll get a replay list like:
...
LEB 1105:211344 len 4144 deletion 0 sqnum 428783 key type 1 inode 80 LEB 15:233544 len 160 deletion 1 sqnum 428785 key type 0 inode 80 LEB 1105:215488 len 4144 deletion 0 sqnum 428787 key type 1 inode 80
...
In the replay list, data nodes' deletion are 0, and the inode node's deletion is 1. In current logic, the file's dentry will be removed, but inode and the flash space it occupied will be reserved. User will see that much free space been disappeared.
We only need to check the deletion value of the following inode type node of the replay entry.
--- fs/ubifs/replay.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ubifs/replay.c +2 -1
@@ -223,7 +223,8 @@ static bool inode_still_linked(struct ub*/ list_for_each_entry_reverse (r, &c->replay_list, list) {ubifs_assert (c, r->sqnum >= rino->sqnum); -if (key_inum (c, &r->key) ==key_inum (c, &rino->key)) +if (key_inum (c, &r->key) ==key_inum (c, &rino->key) && +key_type (c, &r->key) ==UBIFS_INO_KEY )return r->deletion ==0 ; }
Greg Kroah-Hartman
maintainerPATCH 292/384 f2fs: fix error handling in f2fs_end_enable_verity()
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 3c0315424f5e3d2a4113c7272367bee1e8e6a174 upstream.
f2fs didn't properly clean up if verity failed to be enabled on a file:
- It left verity metadata (pages past EOF) in the page cache, which would be exposed to userspace if the file was later extended.
- It didn't truncate the verity metadata at all (either from cache or from disk) if an error occurred while setting the verity bit.
Fix these bugs by adding a call to truncate_inode_pages() and ensuring that we truncate the verity metadata (both from cache and from disk) in all error paths. Also rework the code to cleanly separate the success path from the error paths, which makes it much easier to understand.
Finally, log a message if f2fs_truncate() fails, since it might otherwise fail silently.
--- fs/f2fs/verity.c | 79 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 23 deletions(-)
fs/f2fs/verity.c +56 -23
@@ -152,40 +152,73 @@ static int f2fs_end_enable_verity(struct size_t desc_size, u64 merkle_tree_size) {struct inode *inode =file_inode (filp); +struct f2fs_sb_info *sbi =F2FS_I_SB (inode);u64 desc_pos =f2fs_verity_metadata_pos (inode) + merkle_tree_size;struct fsverity_descriptor_location dloc = { .version =cpu_to_le32 (F2FS_VERIFY_VER ), .size =cpu_to_le32 (desc_size), .pos =cpu_to_le64 (desc_pos), }; -int err =0 ; +int err =0 , err2 =0 ; -if (desc !=NULL ) { -/* Succeeded; write the verity descriptor. */ - err =pagecache_write (inode, desc, desc_size, desc_pos); - -/* Write all pages before clearing FI_VERITY_IN_PROGRESS. */ -if (!err) - err =filemap_write_and_wait (inode->i_mapping); - } - -/* If we failed, truncate anything we wrote past i_size. */ -if (desc ==NULL || err) -f2fs_truncate (inode); +/* +* If an error already occurred (which fs/verity/ signals by passing +* desc == NULL), then only clean-up is needed. +*/ +if (desc ==NULL ) + goto cleanup; + +/* Append the verity descriptor. */ + err =pagecache_write (inode, desc, desc_size, desc_pos); +if (err) + goto cleanup; + +/* +* Write all pages (both data and verity metadata). Note that this must +* happen before clearing FI_VERITY_IN_PROGRESS; otherwise pages beyond +* i_size won't be written properly. For crash consistency, this also +* must happen before the verity inode flag gets persisted. +*/ + err =filemap_write_and_wait (inode->i_mapping); +if (err) + goto cleanup; + +/* Set the verity xattr. */ + err =f2fs_setxattr (inode,F2FS_XATTR_INDEX_VERITY , +F2FS_XATTR_NAME_VERITY , &dloc,sizeof (dloc), +NULL ,XATTR_CREATE ); +if (err) + goto cleanup; + +/* Finally, set the verity inode flag. */ +file_set_verity (inode); +f2fs_set_inode_flags (inode); +f2fs_mark_inode_dirty_sync (inode, true);clear_inode_flag (inode,FI_VERITY_IN_PROGRESS ); +return 0 ; -if (desc !=NULL && !err) { - err =f2fs_setxattr (inode,F2FS_XATTR_INDEX_VERITY , -F2FS_XATTR_NAME_VERITY , &dloc,sizeof (dloc), -NULL ,XATTR_CREATE ); -if (!err) { -file_set_verity (inode); -f2fs_set_inode_flags (inode); -f2fs_mark_inode_dirty_sync (inode, true); - } +cleanup: +/* +* Verity failed to be enabled, so clean up by truncating any verity +* metadata that was written beyond i_size (both from cache and from +* disk) and clearing FI_VERITY_IN_PROGRESS. +* +* Taking i_gc_rwsem[WRITE] is needed to stop f2fs garbage collection +* from re-instantiating cached pages we are truncating (since unlike +* normal file accesses, garbage collection isn't limited by i_size). +*/ +down_write (&F2FS_I (inode)->i_gc_rwsem[WRITE ]); +truncate_inode_pages (inode->i_mapping, inode->i_size); + err2 =f2fs_truncate (inode); +if (err2) { +f2fs_err (sbi,"Truncating verity metadata failed (errno=%d)" , + err2); +set_sbi_flag (sbi,SBI_NEED_FSCK ); } -return err; +up_write (&F2FS_I (inode)->i_gc_rwsem[WRITE ]); +clear_inode_flag (inode,FI_VERITY_IN_PROGRESS ); +return err ?: err2; } static int f2fs_get_verity_descriptor(struct inode *inode, void *buf,
Greg Kroah-Hartman
maintainerPATCH 293/384 f2fs: fix to avoid out-of-bounds memory access
In reply to Greg Kroah-HartmanFrom: Chao Yu <[email protected]>
commit b862676e371715456c9dade7990c8004996d0d9e upstream.
butt3rflyh4ck <[email protected]> reported a bug found by syzkaller fuzzer with custom modifications in 5.12.0-rc3+ [1]:
dump_stack+0xfa/0x151 lib/dump_stack.c:120 print_address_description.constprop.0.cold+0x82/0x32c mm/kasan/report.c:232 __kasan_report mm/kasan/report.c:399 [inline] kasan_report.cold+0x7c/0xd8 mm/kasan/report.c:416 f2fs_test_bit fs/f2fs/f2fs.h:2572 [inline] current_nat_addr fs/f2fs/node.h:213 [inline] get_next_nat_page fs/f2fs/node.c:123 [inline] __flush_nat_entry_set fs/f2fs/node.c:2888 [inline] f2fs_flush_nat_entries+0x258e/0x2960 fs/f2fs/node.c:2991 f2fs_write_checkpoint+0x1372/0x6a70 fs/f2fs/checkpoint.c:1640 f2fs_issue_checkpoint+0x149/0x410 fs/f2fs/checkpoint.c:1807 f2fs_sync_fs+0x20f/0x420 fs/f2fs/super.c:1454 __sync_filesystem fs/sync.c:39 [inline] sync_filesystem fs/sync.c:67 [inline] sync_filesystem+0x1b5/0x260 fs/sync.c:48 generic_shutdown_super+0x70/0x370 fs/super.c:448 kill_block_super+0x97/0xf0 fs/super.c:1394
The root cause is, if nat entry in checkpoint journal area is corrupted, e.g. nid of journalled nat entry exceeds max nid value, during checkpoint, once it tries to flush nat journal to NAT area, get_next_nat_page() may access out-of-bounds memory on nat_bitmap due to it uses wrong nid value as bitmap offset.
[1] https://lore.kernel.org/lkml/CAFcO6XOMWdr8pObek6eN6-fs58KG9doRFadgJj-FnF-1x43s2g@mail.gmail.com/T/#u
--- fs/f2fs/node.c | 3 +++ 1 file changed, 3 insertions(+)
fs/f2fs/node.c +3 -0
@@ -2785,6 +2785,9 @@ static void remove_nats_in_journal(strucstruct f2fs_nat_entry raw_ne;nid_t nid =le32_to_cpu (nid_in_journal (journal, i)); +if (f2fs_check_nid_range (sbi, nid)) +continue ; + raw_ne =nat_in_journal (journal, i); ne =__lookup_nat_cache (nm_i, nid);
Greg Kroah-Hartman
maintainerPATCH 294/384 mlxsw: spectrum_mr: Update egress RIF list before routes action
In reply to Greg Kroah-HartmanFrom: Ido Schimmel <[email protected]>
commit cbaf3f6af9c268caf558c8e7ec52bcb35c5455dd upstream.
Each multicast route that is forwarding packets (as opposed to trapping them) points to a list of egress router interfaces (RIFs) through which packets are replicated.
A route's action can transition from trap to forward when a RIF is created for one of the route's egress virtual interfaces (eVIF). When this happens, the route's action is first updated and only later the list of egress RIFs is committed to the device.
This results in the route pointing to an invalid list. In case the list pointer is out of range (due to uninitialized memory), the device will complain:
mlxsw_spectrum2 0000:06:00.0: EMAD reg access failed (tid=5733bf490000905c,reg_id=300f(pefa),type=write,status=7(bad parameter))
Fix this by first committing the list of egress RIFs to the device and only later update the route's action.
Note that a fix is not needed in the reverse function (i.e., mlxsw_sp_mr_route_evif_unresolve()), as there the route's action is first updated and only later the RIF is removed from the list.
--- drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +15 -15
@@ -535,6 +535,16 @@ mlxsw_sp_mr_route_evif_resolve(struct mlu16 erif_index =0 ;int err; +/* Add the eRIF */ +if (mlxsw_sp_mr_vif_valid (rve->mr_vif)) { + erif_index =mlxsw_sp_rif_index (rve->mr_vif->rif); + err = mr->mr_ops->route_erif_add (mlxsw_sp, + rve->mr_route->route_priv, + erif_index); +if (err) +return err; + } +/* Update the route action, as the new eVIF can be a tunnel or a pimreg * device which will require updating the action. */
@@ -544,17 +554,7 @@ mlxsw_sp_mr_route_evif_resolve(struct ml rve->mr_route->route_priv, route_action);if (err) -return err; - } - -/* Add the eRIF */ -if (mlxsw_sp_mr_vif_valid (rve->mr_vif)) { - erif_index =mlxsw_sp_rif_index (rve->mr_vif->rif); - err = mr->mr_ops->route_erif_add (mlxsw_sp, - rve->mr_route->route_priv, - erif_index); -if (err) - goto err_route_erif_add; + goto err_route_action_update; }/* Update the minimum MTU */
@@ -572,14 +572,14 @@ mlxsw_sp_mr_route_evif_resolve(struct mlreturn 0 ; err_route_min_mtu_update: -if (mlxsw_sp_mr_vif_valid (rve->mr_vif)) - mr->mr_ops->route_erif_del (mlxsw_sp, rve->mr_route->route_priv, - erif_index); -err_route_erif_add:if (route_action != rve->mr_route->route_action) mr->mr_ops->route_action_update (mlxsw_sp, rve->mr_route->route_priv, rve->mr_route->route_action); +err_route_action_update: +if (mlxsw_sp_mr_vif_valid (rve->mr_vif)) + mr->mr_ops->route_erif_del (mlxsw_sp, rve->mr_route->route_priv, + erif_index);return err; }
Greg Kroah-Hartman
maintainerPATCH 295/384 openvswitch: fix stack OOB read while fragmenting IPv4 packets
In reply to Greg Kroah-HartmanFrom: Davide Caratti <[email protected]>
commit 7c0ea5930c1c211931819d83cfb157bff1539a4c upstream.
running openvswitch on kernels built with KASAN, it's possible to see the following splat while testing fragmentation of IPv4 packets:
BUG: KASAN: stack-out-of-bounds in ip_do_fragment+0x1b03/0x1f60 Read of size 1 at addr ffff888112fc713c by task handler2/1367 CPU: 0 PID: 1367 Comm: handler2 Not tainted 5.12.0-rc6+ #418 Hardware name: Red Hat KVM, BIOS 1.11.1-4.module+el8.1.0+4066+0f1aadab 04/01/2014 Call Trace: dump_stack+0x92/0xc1 print_address_description.constprop.7+0x1a/0x150 kasan_report.cold.13+0x7f/0x111 ip_do_fragment+0x1b03/0x1f60 ovs_fragment+0x5bf/0x840 [openvswitch] do_execute_actions+0x1bd5/0x2400 [openvswitch] ovs_execute_actions+0xc8/0x3d0 [openvswitch] ovs_packet_cmd_execute+0xa39/0x1150 [openvswitch] genl_family_rcv_msg_doit.isra.15+0x227/0x2d0 genl_rcv_msg+0x287/0x490 netlink_rcv_skb+0x120/0x380 genl_rcv+0x24/0x40 netlink_unicast+0x439/0x630 netlink_sendmsg+0x719/0xbf0 sock_sendmsg+0xe2/0x110 ____sys_sendmsg+0x5ba/0x890 ___sys_sendmsg+0xe9/0x160 __sys_sendmsg+0xd3/0x170 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f957079db07 Code: c3 66 90 41 54 41 89 d4 55 48 89 f5 53 89 fb 48 83 ec 10 e8 eb ec ff ff 44 89 e2 48 89 ee 89 df 41 89 c0 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 35 44 89 c7 48 89 44 24 08 e8 24 ed ff ff 48 RSP: 002b:00007f956ce35a50 EFLAGS: 00000293 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 0000000000000019 RCX: 00007f957079db07 RDX: 0000000000000000 RSI: 00007f956ce35ae0 RDI: 0000000000000019 RBP: 00007f956ce35ae0 R08: 0000000000000000 R09: 00007f9558006730 R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000000000 R13: 00007f956ce37308 R14: 00007f956ce35f80 R15: 00007f956ce35ae0 The buggy address belongs to the page: page:00000000af2a1d93 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x112fc7 flags: 0x17ffffc0000000() raw: 0017ffffc0000000 0000000000000000 dead000000000122 0000000000000000 raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kasan: bad access detected
addr ffff888112fc713c is located in stack of task handler2/1367 at offset 180 in frame:
ovs_fragment+0x0/0x840 [openvswitch]
this frame has 2 objects:
[32, 144) 'ovs_dst'
[192, 424) 'ovs_rt'
Memory state around the buggy address:
ffff888112fc7000: f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888112fc7080: 00 f1 f1 f1 f1 00 00 00 00 00 00 00 00 00 00 00
>ffff888112fc7100: 00 00 00 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00
^
ffff888112fc7180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888112fc7200: 00 00 00 00 00 00 f2 f2 f2 00 00 00 00 00 00 00for IPv4 packets, ovs_fragment() uses a temporary struct dst_entry. Then, in the following call graph:
ip_do_fragment()
ip_skb_dst_mtu()
ip_dst_mtu_maybe_forward()
ip_mtu_locked()the pointer to struct dst_entry is used as pointer to struct rtable: this turns the access to struct members like rt_mtu_locked into an OOB read in the stack. Fix this changing the temporary variable used for IPv4 packets in ovs_fragment(), similarly to what is done for IPv6 few lines below.
--- net/openvswitch/actions.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/openvswitch/actions.c +4 -4
@@ -827,17 +827,17 @@ static void ovs_fragment(struct net *net }if (key->eth.type ==htons (ETH_P_IP )) { -struct dst_entry ovs_dst; +struct rtable ovs_rt = {0 };unsigned long orig_dst;prepare_frag (vport, skb, orig_network_offset,ovs_key_mac_proto (key)); -dst_init (&ovs_dst, &ovs_dst_ops,NULL ,1 , +dst_init (&ovs_rt.dst, &ovs_dst_ops,NULL ,1 ,DST_OBSOLETE_NONE ,DST_NOCOUNT ); - ovs_dst.dev = vport->dev; + ovs_rt.dst.dev = vport->dev; orig_dst = skb->_skb_refdst; -skb_dst_set_noref (skb, &ovs_dst); +skb_dst_set_noref (skb, &ovs_rt.dst);IPCB (skb)->frag_max_size = mru;ip_do_fragment (net, skb->sk, skb, ovs_vport_output);
Greg Kroah-Hartman
maintainerPATCH 296/384 net/sched: sch_frag: fix stack OOB read while fragmenting IPv4 packets
In reply to Greg Kroah-HartmanFrom: Davide Caratti <[email protected]>
commit 31fe34a0118e0acc958c802e830ad5d37ef6b1d3 upstream.
when 'act_mirred' tries to fragment IPv4 packets that had been previously re-assembled using 'act_ct', splats like the following can be observed on kernels built with KASAN:
BUG: KASAN: stack-out-of-bounds in ip_do_fragment+0x1b03/0x1f60
Read of size 1 at addr ffff888147009574 by task ping/947
CPU: 0 PID: 947 Comm: ping Not tainted 5.12.0-rc6+ #418
Hardware name: Red Hat KVM, BIOS 1.11.1-4.module+el8.1.0+4066+0f1aadab 04/01/2014
Call Trace:
<IRQ>
dump_stack+0x92/0xc1
print_address_description.constprop.7+0x1a/0x150
kasan_report.cold.13+0x7f/0x111
ip_do_fragment+0x1b03/0x1f60
sch_fragment+0x4bf/0xe40
tcf_mirred_act+0xc3d/0x11a0 [act_mirred]
tcf_action_exec+0x104/0x3e0
fl_classify+0x49a/0x5e0 [cls_flower]
tcf_classify_ingress+0x18a/0x820
__netif_receive_skb_core+0xae7/0x3340
__netif_receive_skb_one_core+0xb6/0x1b0
process_backlog+0x1ef/0x6c0
__napi_poll+0xaa/0x500
net_rx_action+0x702/0xac0
__do_softirq+0x1e4/0x97f
do_softirq+0x71/0x90
</IRQ>
__local_bh_enable_ip+0xdb/0xf0
ip_finish_output2+0x760/0x2120
ip_do_fragment+0x15a5/0x1f60
__ip_finish_output+0x4c2/0xea0
ip_output+0x1ca/0x4d0
ip_send_skb+0x37/0xa0
raw_sendmsg+0x1c4b/0x2d00
sock_sendmsg+0xdb/0x110
__sys_sendto+0x1d7/0x2b0
__x64_sys_sendto+0xdd/0x1b0
do_syscall_64+0x33/0x40
entry_SYSCALL_64_after_hwframe+0x44/0xae
RIP: 0033:0x7f82e13853eb
Code: 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 f3 0f 1e fa 48 8d 05 75 42 2c 00 41 89 ca 8b 00 85 c0 75 14 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 75 c3 0f 1f 40 00 41 57 4d 89 c7 41 56 41 89
RSP: 002b:00007ffe01fad888 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00005571aac13700 RCX: 00007f82e13853eb
RDX: 0000000000002330 RSI: 00005571aac13700 RDI: 0000000000000003
RBP: 0000000000002330 R08: 00005571aac10500 R09: 0000000000000010
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffe01faefb0
R13: 00007ffe01fad890 R14: 00007ffe01fad980 R15: 00005571aac0f0a0
The buggy address belongs to the page:
page:000000001dff2e03 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x147009
flags: 0x17ffffc0001000(reserved)
raw: 0017ffffc0001000 ffffea00051c0248 ffffea00051c0248 0000000000000000
raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888147009400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888147009480: f1 f1 f1 f1 04 f2 f2 f2 f2 f2 f2 f2 00 00 00 00
>ffff888147009500: 00 00 00 00 00 00 00 00 00 00 f2 f2 f2 f2 f2 f2
^
ffff888147009580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888147009600: 00 00 00 00 00 00 00 00 00 00 00 00 00 f2 f2 f2for IPv4 packets, sch_fragment() uses a temporary struct dst_entry. Then, in the following call graph:
ip_do_fragment()
ip_skb_dst_mtu()
ip_dst_mtu_maybe_forward()
ip_mtu_locked()the pointer to struct dst_entry is used as pointer to struct rtable: this turns the access to struct members like rt_mtu_locked into an OOB read in the stack. Fix this changing the temporary variable used for IPv4 packets in sch_fragment(), similarly to what is done for IPv6 few lines below.
--- net/sched/sch_frag.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/sched/sch_frag.c +4 -4
@@ -90,16 +90,16 @@ static int sch_fragment(struct net *net, }if (skb_protocol (skb, true) ==htons (ETH_P_IP )) { -struct dst_entry sch_frag_dst; +struct rtable sch_frag_rt = {0 };unsigned long orig_dst;sch_frag_prepare_frag (skb, xmit); -dst_init (&sch_frag_dst, &sch_frag_dst_ops,NULL ,1 , +dst_init (&sch_frag_rt.dst, &sch_frag_dst_ops,NULL ,1 ,DST_OBSOLETE_NONE ,DST_NOCOUNT ); - sch_frag_dst.dev = skb->dev; + sch_frag_rt.dst.dev = skb->dev; orig_dst = skb->_skb_refdst; -skb_dst_set_noref (skb, &sch_frag_dst); +skb_dst_set_noref (skb, &sch_frag_rt.dst);IPCB (skb)->frag_max_size = mru; ret =ip_do_fragment (net, skb->sk, skb, sch_frag_xmit);
Greg Kroah-Hartman
maintainerPATCH 297/384 ACPI: GTDT: Dont corrupt interrupt mappings on watchdow probe failure
In reply to Greg Kroah-HartmanFrom: Marc Zyngier <[email protected]>
commit 1ecd5b129252249b9bc03d7645a7bda512747277 upstream.
When failing the driver probe because of invalid firmware properties, the GTDT driver unmaps the interrupt that it mapped earlier.
However, it never checks whether the mapping of the interrupt actially succeeded. Even more, should the firmware report an illegal interrupt number that overlaps with the GIC SGI range, this can result in an IPI being unmapped, and subsequent fireworks (as reported by Dann Frazier).
Rework the driver to have a slightly saner behaviour and actually check whether the interrupt has been mapped before unmapping things.
--- drivers/acpi/arm64/gtdt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/acpi/arm64/gtdt.c +6 -4
@@ -329,7 +329,7 @@ static int __init gtdt_import_sbsa_gwdt( int index) {struct platform_device *pdev; -int irq =map_gt_gsi (wd->timer_interrupt, wd->timer_flags); +int irq;/* * According to SBSA specification the size of refresh and control
@@ -338,7 +338,7 @@ static int __init gtdt_import_sbsa_gwdt(struct resource res[] = {DEFINE_RES_MEM (wd->control_frame_address,SZ_4K ),DEFINE_RES_MEM (wd->refresh_frame_address,SZ_4K ), -DEFINE_RES_IRQ (irq), + {}, };int nr_res =ARRAY_SIZE (res);
@@ -348,10 +348,11 @@ static int __init gtdt_import_sbsa_gwdt(if (!(wd->refresh_frame_address && wd->control_frame_address)) {pr_err (FW_BUG "failed to get the Watchdog base address.\n" ); -acpi_unregister_gsi (wd->timer_interrupt);return -EINVAL ; } + irq =map_gt_gsi (wd->timer_interrupt, wd->timer_flags); + res[2 ] = (struct resource )DEFINE_RES_IRQ (irq);if (irq <=0 ) {pr_warn ("failed to map the Watchdog interrupt.\n" ); nr_res--;
@@ -364,7 +365,8 @@ static int __init gtdt_import_sbsa_gwdt(*/ pdev =platform_device_register_simple ("sbsa-gwdt" , index, res, nr_res);if (IS_ERR (pdev)) { -acpi_unregister_gsi (wd->timer_interrupt); +if (irq >0 ) +acpi_unregister_gsi (wd->timer_interrupt);return PTR_ERR (pdev); }
Greg Kroah-Hartman
maintainerPATCH 298/384 NFS: fs_context: validate UDP retrans to prevent shift out-of-bounds
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
commit c09f11ef35955785f92369e25819bf0629df2e59 upstream.
Fix shift out-of-bounds in xprt_calc_majortimeo(). This is caused by a garbage timeout (retrans) mount option being passed to nfs mount, in this case from syzkaller.
If the protocol is XPRT_TRANSPORT_UDP, then 'retrans' is a shift value for a 64-bit long integer, so 'retrans' cannot be >= 64. If it is >= 64, fail the mount and return an error.
--- fs/nfs/fs_context.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
fs/nfs/fs_context.c +12 -0
@@ -974,6 +974,15 @@ static int nfs23_parse_monolithic(struct sizeof(mntfh->data) - mntfh->size);/* +* for proto == XPRT_TRANSPORT_UDP, which is what uses +* to_exponential, implying shift: limit the shift value +* to BITS_PER_LONG (majortimeo is unsigned long) +*/ +if (!(data->flags &NFS_MOUNT_TCP ))/* this will be UDP */ +if (data->retrans >=64 )/* shift value is too large */ + goto out_invalid_data; + +/* * Translate to nfs_fs_context, which nfs_fill_super * can deal with. */
@@ -1073,6 +1082,9 @@ out_no_address: out_invalid_fh:return nfs_invalf (fc,"NFS: invalid root filehandle" ); + +out_invalid_data: +return nfs_invalf (fc,"NFS: invalid binary mount data" ); }#if IS_ENABLED (CONFIG_NFS_V4 )
Greg Kroah-Hartman
maintainerPATCH 299/384 NFS: Dont discard pNFS layout segments that are marked for return
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit 39fd01863616964f009599e50ca5c6ea9ebf88d6 upstream.
If the pNFS layout segment is marked with the NFS_LSEG_LAYOUTRETURN flag, then the assumption is that it has some reporting requirement to perform through a layoutreturn (e.g. flexfiles layout stats or error information).
--- fs/nfs/pnfs.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/nfs/pnfs.c +5 -0
@@ -2468,6 +2468,9 @@ pnfs_mark_matching_lsegs_return(struct passert_spin_locked (&lo->plh_inode->i_lock); +if (test_bit (NFS_LAYOUT_RETURN_REQUESTED , &lo->plh_flags)) + tmp_list = &lo->plh_return_segs; +list_for_each_entry_safe (lseg, next, &lo->plh_segs, pls_list)if (pnfs_match_lseg_recall (lseg, return_range, seq)) { dprintk("%s: marking lseg %p iomode %d "
@@ -2475,6 +2478,8 @@ pnfs_mark_matching_lsegs_return(struct p lseg, lseg->pls_range.iomode, lseg->pls_range.offset, lseg->pls_range.length); +if (test_bit (NFS_LSEG_LAYOUTRETURN , &lseg->pls_flags)) + tmp_list = &lo->plh_return_segs;if (mark_lseg_invalid (lseg, tmp_list))continue ; remaining++;
Greg Kroah-Hartman
maintainerPATCH 300/384 NFSv4: Dont discard segments marked for return in _pnfs_return_layout()
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit de144ff4234f935bd2150108019b5d87a90a8a96 upstream.
If the pNFS layout segment is marked with the NFS_LSEG_LAYOUTRETURN flag, then the assumption is that it has some reporting requirement to perform through a layoutreturn (e.g. flexfiles layout stats or error information).
--- fs/nfs/pnfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/pnfs.c +1 -1
@@ -1344,7 +1344,7 @@ _pnfs_return_layout(struct inode *ino) } valid_layout =pnfs_layout_is_valid (lo);pnfs_clear_layoutcommit (ino, &tmp_list); -pnfs_mark_matching_lsegs_invalid (lo, &tmp_list,NULL ,0 ); +pnfs_mark_matching_lsegs_return (lo, &tmp_list,NULL ,0 );if (NFS_SERVER (ino)->pnfs_curr_ld->return_range) {struct pnfs_layout_range range = {
Greg Kroah-Hartman
maintainerPATCH 301/384 Input: ili210x - add missing negation for touch indication on ili210x
In reply to Greg Kroah-HartmanFrom: Hansem Ro <[email protected]>
commit ac05a8a927e5a1027592d8f98510a511dadeed14 upstream.
This adds the negation needed for proper finger detection on Ilitek ili2107/ili210x. This fixes polling issues (on Amazon Kindle Fire) caused by returning false for the cooresponding finger on the touchscreen.
--- drivers/input/touchscreen/ili210x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/touchscreen/ili210x.c +1 -1
@@ -87,7 +87,7 @@ static bool ili210x_touchdata_to_coords( unsigned int *x, unsigned int *y, unsigned int *z) { - if (touchdata[0] & BIT(finger)) + if (!(touchdata[0] & BIT(finger))) return false; *x =get_unaligned_be16 (touchdata +1 + (finger *4 ) +0 );
Greg Kroah-Hartman
maintainerPATCH 302/384 jffs2: Fix kasan slab-out-of-bounds problem
In reply to Greg Kroah-HartmanFrom: lizhe <[email protected]>
commit 960b9a8a7676b9054d8b46a2c7db52a0c8766b56 upstream.
KASAN report a slab-out-of-bounds problem. The logs are listed below. It is because in function jffs2_scan_dirent_node, we alloc "checkedlen+1" bytes for fd->name and we check crc with length rd->nsize. If checkedlen is less than rd->nsize, it will cause the slab-out-of-bounds problem.
jffs2: Dirent at *** has zeroes in name. Truncating to %d char
==================================================================
BUG: KASAN: slab-out-of-bounds in crc32_le+0x1ce/0x260 at addr ffff8800842cf2d1
Read of size 1 by task test_JFFS2/915
=============================================================================
BUG kmalloc-64 (Tainted: G B O ): kasan: bad access detected
-----------------------------------------------------------------------------
INFO: Allocated in jffs2_alloc_full_dirent+0x2a/0x40 age=0 cpu=1 pid=915
___slab_alloc+0x580/0x5f0
__slab_alloc.isra.24+0x4e/0x64
__kmalloc+0x170/0x300
jffs2_alloc_full_dirent+0x2a/0x40
jffs2_scan_eraseblock+0x1ca4/0x3b64
jffs2_scan_medium+0x285/0xfe0
jffs2_do_mount_fs+0x5fb/0x1bbc
jffs2_do_fill_super+0x245/0x6f0
jffs2_fill_super+0x287/0x2e0
mount_mtd_aux.isra.0+0x9a/0x144
mount_mtd+0x222/0x2f0
jffs2_mount+0x41/0x60
mount_fs+0x63/0x230
vfs_kern_mount.part.6+0x6c/0x1f4
do_mount+0xae8/0x1940
SyS_mount+0x105/0x1d0
INFO: Freed in jffs2_free_full_dirent+0x22/0x40 age=27 cpu=1 pid=915
__slab_free+0x372/0x4e4
kfree+0x1d4/0x20c
jffs2_free_full_dirent+0x22/0x40
jffs2_build_remove_unlinked_inode+0x17a/0x1e4
jffs2_do_mount_fs+0x1646/0x1bbc
jffs2_do_fill_super+0x245/0x6f0
jffs2_fill_super+0x287/0x2e0
mount_mtd_aux.isra.0+0x9a/0x144
mount_mtd+0x222/0x2f0
jffs2_mount+0x41/0x60
mount_fs+0x63/0x230
vfs_kern_mount.part.6+0x6c/0x1f4
do_mount+0xae8/0x1940
SyS_mount+0x105/0x1d0
entry_SYSCALL_64_fastpath+0x1e/0x97
Call Trace:
[<ffffffff815befef>] dump_stack+0x59/0x7e
[<ffffffff812d1d65>] print_trailer+0x125/0x1b0
[<ffffffff812d82c8>] object_err+0x34/0x40
[<ffffffff812dadef>] kasan_report.part.1+0x21f/0x534
[<ffffffff81132401>] ? vprintk+0x2d/0x40
[<ffffffff815f1ee2>] ? crc32_le+0x1ce/0x260
[<ffffffff812db41a>] kasan_report+0x26/0x30
[<ffffffff812d9fc1>] __asan_load1+0x3d/0x50
[<ffffffff815f1ee2>] crc32_le+0x1ce/0x260
[<ffffffff814764ae>] ? jffs2_alloc_full_dirent+0x2a/0x40
[<ffffffff81485cec>] jffs2_scan_eraseblock+0x1d0c/0x3b64
[<ffffffff81488813>] ? jffs2_scan_medium+0xccf/0xfe0
[<ffffffff81483fe0>] ? jffs2_scan_make_ino_cache+0x14c/0x14c
[<ffffffff812da3e9>] ? kasan_unpoison_shadow+0x35/0x50
[<ffffffff812da3e9>] ? kasan_unpoison_shadow+0x35/0x50
[<ffffffff812da462>] ? kasan_kmalloc+0x5e/0x70
[<ffffffff812d5d90>] ? kmem_cache_alloc_trace+0x10c/0x2cc
[<ffffffff818169fb>] ? mtd_point+0xf7/0x130
[<ffffffff81487dc9>] jffs2_scan_medium+0x285/0xfe0
[<ffffffff81487b44>] ? jffs2_scan_eraseblock+0x3b64/0x3b64
[<ffffffff812da3e9>] ? kasan_unpoison_shadow+0x35/0x50
[<ffffffff812da3e9>] ? kasan_unpoison_shadow+0x35/0x50
[<ffffffff812da462>] ? kasan_kmalloc+0x5e/0x70
[<ffffffff812d57df>] ? __kmalloc+0x12b/0x300
[<ffffffff812da462>] ? kasan_kmalloc+0x5e/0x70
[<ffffffff814a2753>] ? jffs2_sum_init+0x9f/0x240
[<ffffffff8148b2ff>] jffs2_do_mount_fs+0x5fb/0x1bbc
[<ffffffff8148ad04>] ? jffs2_del_noinode_dirent+0x640/0x640
[<ffffffff812da462>] ? kasan_kmalloc+0x5e/0x70
[<ffffffff81127c5b>] ? __init_rwsem+0x97/0xac
[<ffffffff81492349>] jffs2_do_fill_super+0x245/0x6f0
[<ffffffff81493c5b>] jffs2_fill_super+0x287/0x2e0
[<ffffffff814939d4>] ? jffs2_parse_options+0x594/0x594
[<ffffffff81819bea>] mount_mtd_aux.isra.0+0x9a/0x144
[<ffffffff81819eb6>] mount_mtd+0x222/0x2f0
[<ffffffff814939d4>] ? jffs2_parse_options+0x594/0x594
[<ffffffff81819c94>] ? mount_mtd_aux.isra.0+0x144/0x144
[<ffffffff81258757>] ? free_pages+0x13/0x1c
[<ffffffff814fa0ac>] ? selinux_sb_copy_data+0x278/0x2e0
[<ffffffff81492b35>] jffs2_mount+0x41/0x60
[<ffffffff81302fb7>] mount_fs+0x63/0x230
[<ffffffff8133755f>] ? alloc_vfsmnt+0x32f/0x3b0
[<ffffffff81337f2c>] vfs_kern_mount.part.6+0x6c/0x1f4
[<ffffffff8133ceec>] do_mount+0xae8/0x1940
[<ffffffff811b94e0>] ? audit_filter_rules.constprop.6+0x1d10/0x1d10
[<ffffffff8133c404>] ? copy_mount_string+0x40/0x40
[<ffffffff812cbf78>] ? alloc_pages_current+0xa4/0x1bc
[<ffffffff81253a89>] ? __get_free_pages+0x25/0x50
[<ffffffff81338993>] ? copy_mount_options.part.17+0x183/0x264
[<ffffffff8133e3a9>] SyS_mount+0x105/0x1d0
[<ffffffff8133e2a4>] ? copy_mnt_ns+0x560/0x560
[<ffffffff810e8391>] ? msa_space_switch_handler+0x13d/0x190
[<ffffffff81be184a>] entry_SYSCALL_64_fastpath+0x1e/0x97
[<ffffffff810e9274>] ? msa_space_switch+0xb0/0xe0
Memory state around the buggy address:
ffff8800842cf180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff8800842cf200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff8800842cf280: fc fc fc fc fc fc 00 00 00 00 01 fc fc fc fc fc
^
ffff8800842cf300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff8800842cf380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================--- fs/jffs2/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/jffs2/scan.c +1 -1
@@ -1079,7 +1079,7 @@ static int jffs2_scan_dirent_node(structmemcpy (&fd->name, rd->name, checkedlen); fd->name[checkedlen] =0 ; - crc =crc32 (0 , fd->name, rd->nsize); + crc =crc32 (0 , fd->name, checkedlen);if (crc !=je32_to_cpu (rd->name_crc)) {pr_notice ("%s(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n" , __func__, ofs,je32_to_cpu (rd->name_crc), crc);
Greg Kroah-Hartman
maintainerPATCH 303/384 jffs2: Hook up splice_write callback
In reply to Greg Kroah-HartmanFrom: Joel Stanley <[email protected]>
commit 42984af09afc414d540fcc8247f42894b0378a91 upstream.
overlayfs using jffs2 as the upper filesystem would fail in some cases since moving to v5.10. The test case used was to run 'touch' on a file that exists in the lower fs, causing the modification time to be updated. It returns EINVAL when the bug is triggered.
A bisection showed this was introduced in v5.9-rc1, with commit 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops"). Reverting that commit restores the expected behaviour.
Some digging showed that this was due to jffs2 lacking an implementation of splice_write. (For unknown reasons the warn_unsupported that should trigger was not displaying any output).
Adding this patch resolved the issue and the test now passes.
--- fs/jffs2/file.c | 1 + 1 file changed, 1 insertion(+)
fs/jffs2/file.c +1 -0
@@ -57,6 +57,7 @@ const struct file_operations jffs2_file_ .mmap = generic_file_readonly_mmap, .fsync = jffs2_fsync, .splice_read = generic_file_splice_read, + .splice_write = iter_file_splice_write, };/* jffs2_file_inode_operations */
Greg Kroah-Hartman
maintainerPATCH 304/384 iommu/vt-d: Force to flush iotlb before creating superpage
In reply to Greg Kroah-HartmanFrom: Longpeng(Mike) <[email protected]>
commit 38c527aeb41926c71902dd42f788a8b093b21416 upstream.
The translation caches may preserve obsolete data when the mapping size is changed, suppose the following sequence which can reveal the problem with high probability.
1.mmap(4GB,MAP_HUGETLB)
2.
while (1) {
(a) DMA MAP 0,0xa0000 (b) DMA UNMAP 0,0xa0000 (c) DMA MAP 0,0xc0000000
* DMA read IOVA 0 may failure here (Not present)
* if the problem occurs.
(d) DMA UNMAP 0,0xc0000000
}
The page table(only focus on IOVA 0) after (a) is:
PML4: 0x19db5c1003 entry:0xffff899bdcd2f000
PDPE: 0x1a1cacb003 entry:0xffff89b35b5c1000
PDE: 0x1a30a72003 entry:0xffff89b39cacb000
PTE: 0x21d200803 entry:0xffff89b3b0a72000The page table after (b) is:
PML4: 0x19db5c1003 entry:0xffff899bdcd2f000
PDPE: 0x1a1cacb003 entry:0xffff89b35b5c1000
PDE: 0x1a30a72003 entry:0xffff89b39cacb000
PTE: 0x0 entry:0xffff89b3b0a72000The page table after (c) is:
PML4: 0x19db5c1003 entry:0xffff899bdcd2f000 PDPE: 0x1a1cacb003 entry:0xffff89b35b5c1000 PDE: 0x21d200883 entry:0xffff89b39cacb000 (*)
Because the PDE entry after (b) is present, it won't be flushed even if the iommu driver flush cache when unmap, so the obsolete data may be preserved in cache, which would cause the wrong translation at end.
However, we can see the PDE entry is finally switch to 2M-superpage mapping, but it does not transform to 0x21d200883 directly:
1. PDE: 0x1a30a72003
2. __domain_mapping
dma_pte_free_pagetable
Set the PDE entry to ZERO
Set the PDE entry to 0x21d200883
So we must flush the cache after the entry switch to ZERO to avoid the obsolete info be preserved.
--- drivers/iommu/intel/iommu.c | 52 ++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 14 deletions(-)
drivers/iommu/intel/iommu.c +38 -14
@@ -2289,6 +2289,41 @@ static inline int hardware_largepage_capreturn level; } +/* +* Ensure that old small page tables are removed to make room for superpage(s). +* We're going to add new large pages, so make sure we don't remove their parent +* tables. The IOTLB/devTLBs should be flushed if any PDE/PTEs are cleared. +*/ +static void switch_to_super_page (struct dmar_domain *domain, +unsigned long start_pfn, +unsigned long end_pfn,int level) +{ +unsigned long lvl_pages =lvl_to_nr_pages (level); +struct dma_pte *pte =NULL ; +int i; + +while (start_pfn <= end_pfn) { +if (!pte) + pte =pfn_to_dma_pte (domain, start_pfn, &level); + +if (dma_pte_present (pte)) { +dma_pte_free_pagetable (domain, start_pfn, + start_pfn + lvl_pages -1 , + level +1 ); + +for_each_domain_iommu (i, domain) +iommu_flush_iotlb_psi (g_iommus[i], domain, + start_pfn, lvl_pages, +0 ,0 ); + } + + pte++; + start_pfn += lvl_pages; +if (first_pte_in_page (pte)) + pte =NULL ; + } +} +static int __domain_mapping (struct dmar_domain *domain,unsigned long iov_pfn,unsigned long phys_pfn,unsigned long nr_pages,int prot)
@@ -2329,22 +2364,11 @@ __domain_mapping(struct dmar_domain *domreturn -ENOMEM ;/* It is large page*/ if (largepage_lvl >1 ) { -unsigned long nr_superpages, end_pfn; +unsigned long end_pfn; pteval |=DMA_PTE_LARGE_PAGE ; - lvl_pages =lvl_to_nr_pages (largepage_lvl); - - nr_superpages = nr_pages / lvl_pages; - end_pfn = iov_pfn + nr_superpages * lvl_pages -1 ; - -/* -* Ensure that old small page tables are -* removed to make room for superpage(s). -* We're adding new large pages, so make sure -* we don't remove their parent tables. -*/ -dma_pte_free_pagetable (domain, iov_pfn, end_pfn, - largepage_lvl +1 ); + end_pfn = ((iov_pfn + nr_pages) &level_mask (largepage_lvl)) -1 ; +switch_to_super_page (domain, iov_pfn, end_pfn, largepage_lvl); }else { pteval &= ~(uint64_t )DMA_PTE_LARGE_PAGE ; }
Greg Kroah-Hartman
maintainerPATCH 305/384 powerpc/vdso: Separate vvar vma from vdso
In reply to Greg Kroah-HartmanFrom: Dmitry Safonov <[email protected]>
commit 1c4bce6753857dc409a0197342d18764e7f4b741 upstream.
Since commit 511157ab641e ("powerpc/vdso: Move vdso datapage up front") VVAR page is in front of the VDSO area. In result it breaks CRIU (Checkpoint Restore In Userspace) [1], where CRIU expects that "[vdso]" from /proc/../maps points at ELF/vdso image, rather than at VVAR data page. Laurent made a patch to keep CRIU working (by reading aux vector). But I think it still makes sence to separate two mappings into different VMAs. It will also make ppc64 less "special" for userspace and as a side-bonus will make VVAR page un-writable by debugger (which previously would COW page and can be unexpected).
I opportunistically Cc stable on it: I understand that usually such stuff isn't a stable material, but that will allow us in CRIU have one workaround less that is needed just for one release (v5.11) on one platform (ppc64), which we otherwise have to maintain. I wouldn't go as far as to say that the commit 511157ab641e is ABI regression as no other userspace got broken, but I'd really appreciate if it gets backported to v5.11 after v5.12 is released, so as not to complicate already non-simple CRIU-vdso code. Thanks!
[1]: https://github.com/checkpoint-restore/criu/issues/1417
--- arch/powerpc/include/asm/mmu_context.h | 2 - arch/powerpc/kernel/vdso.c | 54 +++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 16 deletions(-)
arch/powerpc/include/asm/mmu_context.h +1 -1
@@ -263,7 +263,7 @@ extern void arch_exit_mmap(struct mm_strstatic inline void arch_unmap (struct mm_struct *mm,unsigned long start,unsigned long end) { -unsigned long vdso_base = (unsigned long )mm->context.vdso -PAGE_SIZE ; +unsigned long vdso_base = (unsigned long )mm->context.vdso;if (start <= vdso_base && vdso_base < end) mm->context.vdso =NULL ;
arch/powerpc/kernel/vdso.c +39 -15
116 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 306/384 powerpc/powernv: Enable HAIL (HV AIL) for ISA v3.1 processors
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
commit 49c1d07fd04f54eb588c4a1dfcedc8d22c5ffd50 upstream.
Starting with ISA v3.1, LPCR[AIL] no longer controls the interrupt mode for HV=1 interrupts. Instead, a new LPCR[HAIL] bit is defined which behaves like AIL=3 for HV interrupts when set.
Set HAIL on bare metal to give us mmu-on interrupts and improve performance.
This also fixes an scv bug: we don't implement scv real mode (AIL=0) vectors because they are at an inconvenient location, so we just disable scv support when AIL can not be set. However powernv assumes that LPCR[AIL] will enable AIL mode so it enables scv support despite HV interrupts being AIL=0, which causes scv interrupts to go off into the weeds.
--- arch/powerpc/include/asm/reg.h | 1 + arch/powerpc/kernel/setup_64.c | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-)
arch/powerpc/include/asm/reg.h +1 -0
@@ -441,6 +441,7 @@#define LPCR_VRMA_LP1 ASM_CONST(0x0000800000000000)#define LPCR_RMLS 0x1C000000/* Implementation dependent RMO limit sel */ #define LPCR_RMLS_SH 26 +#define LPCR_HAIL ASM_CONST(0x0000000004000000)/* HV AIL (ISAv3.1) */ #define LPCR_ILE ASM_CONST(0x0000000002000000)/* !HV irqs set MSR:LE */ #define LPCR_AIL ASM_CONST(0x0000000001800000)/* Alternate interrupt location */ #define LPCR_AIL_0 ASM_CONST(0x0000000000000000)/* MMU off exception offset 0x0 */
arch/powerpc/kernel/setup_64.c +16 -3
@@ -232,10 +232,23 @@ static void cpu_ready_for_interrupts(voi* If we are not in hypervisor mode the job is done once for * the whole partition in configure_exceptions(). */ -if (cpu_has_feature (CPU_FTR_HVMODE ) && -cpu_has_feature (CPU_FTR_ARCH_207S )) { +if (cpu_has_feature (CPU_FTR_HVMODE )) {unsigned long lpcr =mfspr (SPRN_LPCR ); -mtspr (SPRN_LPCR , lpcr |LPCR_AIL_3 ); +unsigned long new_lpcr = lpcr; + +if (cpu_has_feature (CPU_FTR_ARCH_31 )) { +/* P10 DD1 does not have HAIL */ +if (pvr_version_is (PVR_POWER10 ) && + (mfspr (SPRN_PVR ) &0xf00 ) ==0x100 ) + new_lpcr |=LPCR_AIL_3 ; +else + new_lpcr |=LPCR_HAIL ; + }else if (cpu_has_feature (CPU_FTR_ARCH_207S )) { + new_lpcr |=LPCR_AIL_3 ; + } + +if (new_lpcr != lpcr) +mtspr (SPRN_LPCR , new_lpcr); }/*
Greg Kroah-Hartman
maintainerPATCH 307/384 powerpc/eeh: Fix EEH handling for hugepages in ioremap space.
In reply to Greg Kroah-HartmanFrom: Mahesh Salgaonkar <[email protected]>
commit 5ae5bc12d0728db60a0aa9b62160ffc038875f1a upstream.
During the EEH MMIO error checking, the current implementation fails to map the (virtual) MMIO address back to the pci device on radix with hugepage mappings for I/O. This results into failure to dispatch EEH event with no recovery even when EEH capability has been enabled on the device.
eeh_check_failure(token) # token = virtual MMIO address
addr = eeh_token_to_phys(token);
edev = eeh_addr_cache_get_dev(addr);
if (!edev)
return 0;
eeh_dev_check_failure(edev); <= Dispatch the EEH event
In case of hugepage mappings, eeh_token_to_phys() has a bug in virt -> phys translation that results in wrong physical address, which is then passed to eeh_addr_cache_get_dev() to match it against cached pci I/O address ranges to get to a PCI device. Hence, it fails to find a match and the EEH event never gets dispatched leaving the device in failed state.
The commit 33439620680be ("powerpc/eeh: Handle hugepages in ioremap space") introduced following logic to translate virt to phys for hugepage mappings:
eeh_token_to_phys():
+ pa = pte_pfn(*ptep);
+
+ /* On radix we can do hugepage mappings for io, so handle that */
+ if (hugepage_shift) {
+ pa <<= hugepage_shift; <= This is wrong
+ pa |= token & ((1ul << hugepage_shift) - 1);
+ }
This patch fixes the virt -> phys translation in eeh_token_to_phys() function.
$ cat /sys/kernel/debug/powerpc/eeh_address_cache mem addr range [0x0000040080000000-0x00000400807fffff]: 0030:01:00.1 mem addr range [0x0000040080800000-0x0000040080ffffff]: 0030:01:00.1 mem addr range [0x0000040081000000-0x00000400817fffff]: 0030:01:00.0 mem addr range [0x0000040081800000-0x0000040081ffffff]: 0030:01:00.0 mem addr range [0x0000040082000000-0x000004008207ffff]: 0030:01:00.1 mem addr range [0x0000040082080000-0x00000400820fffff]: 0030:01:00.0 mem addr range [0x0000040082100000-0x000004008210ffff]: 0030:01:00.1 mem addr range [0x0000040082110000-0x000004008211ffff]: 0030:01:00.0
Above is the list of cached io address ranges of pci 0030:01:00.<fn>.
Before this patch:
Tracing 'arg1' of function eeh_addr_cache_get_dev() during error injection clearly shows that 'addr=' contains wrong physical address:
kworker/u16:0-7 [001] .... 108.883775: eeh_addr_cache_get_dev:
(eeh_addr_cache_get_dev+0xc/0xf0) addr=0x80103000a510
dmesg shows no EEH recovery messages:
[ 108.563768] bnx2x: [bnx2x_timer:5801(eth2)]MFW seems hanged: drv_pulse (0x9ae) != mcp_pulse (0x7fff) [ 108.563788] bnx2x: [bnx2x_hw_stats_update:870(eth2)]NIG timer max (4294967295) [ 108.883788] bnx2x: [bnx2x_acquire_hw_lock:2013(eth1)]lock_status 0xffffffff resource_bit 0x1 [ 108.884407] bnx2x 0030:01:00.0 eth1: MDC/MDIO access timeout [ 108.884976] bnx2x 0030:01:00.0 eth1: MDC/MDIO access timeout <..>
After this patch:
eeh_addr_cache_get_dev() trace shows correct physical address:
<idle>-0 [001] ..s. 1043.123828: eeh_addr_cache_get_dev:
(eeh_addr_cache_get_dev+0xc/0xf0) addr=0x40080bc7cd8
dmesg logs shows EEH recovery getting triggerred:
[ 964.323980] bnx2x: [bnx2x_timer:5801(eth2)]MFW seems hanged: drv_pulse (0x746f) != mcp_pulse (0x7fff) [ 964.323991] EEH: Recovering PHB#30-PE#10000 [ 964.324002] EEH: PE location: N/A, PHB location: N/A [ 964.324006] EEH: Frozen PHB#30-PE#10000 detected <..>
--- arch/powerpc/kernel/eeh.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
arch/powerpc/kernel/eeh.c +4 -7
@@ -362,14 +362,11 @@ static inline unsigned long eeh_token_to pa =pte_pfn (*ptep);/* On radix we can do hugepage mappings for io, so handle that */ -if (hugepage_shift) { - pa <<= hugepage_shift; - pa |= token & ((1ul << hugepage_shift) -1 ); - }else { - pa <<=PAGE_SHIFT ; - pa |= token & (PAGE_SIZE -1 ); - } +if (!hugepage_shift) + hugepage_shift =PAGE_SHIFT ; + pa <<=PAGE_SHIFT ; + pa |= token & ((1ul << hugepage_shift) -1 );return pa; }
Greg Kroah-Hartman
maintainerPATCH 308/384 powerpc/kexec_file: Use current CPU info while setting up FDT
In reply to Greg Kroah-HartmanFrom: Sourabh Jain <[email protected]>
commit 40c753993e3aad51a12c21233486e2037417a4d6 upstream.
kexec_file_load() uses initial_boot_params in setting up the device tree for the kernel to be loaded. Though initial_boot_params holds info about CPUs at the time of boot, it doesn't account for hot added CPUs.
So, kexec'ing with kexec_file_load() syscall leaves the kexec'ed kernel with inaccurate CPU info.
If kdump kernel is loaded with kexec_file_load() syscall and the system crashes on a hot added CPU, the capture kernel hangs failing to identify the boot CPU, with no output.
To avoid this from happening, extract current CPU info from of_root device node and use it for setting up the fdt in kexec_file_load case.
--- arch/powerpc/kexec/file_load_64.c | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+)
arch/powerpc/kexec/file_load_64.c +92 -0
@@ -961,6 +961,93 @@ unsigned int kexec_fdt_totalsize_ppc64(s }/** +* add_node_props - Reads node properties from device node structure and add +* them to fdt. +* @fdt: Flattened device tree of the kernel +* @node_offset: offset of the node to add a property at +* @dn: device node pointer +* +* Returns 0 on success, negative errno on error. +*/ +static int add_node_props (void *fdt,int node_offset,const struct device_node *dn) +{ +int ret =0 ; +struct property *pp; + +if (!dn) +return -EINVAL ; + +for_each_property_of_node (dn, pp) { + ret =fdt_setprop (fdt, node_offset, pp->name, pp->value, pp->length); +if (ret <0 ) { +pr_err ("Unable to add %s property: %s\n" , pp->name,fdt_strerror (ret)); +return ret; + } + } +return ret; +} + +/** +* update_cpus_node - Update cpus node of flattened device tree using of_root +* device node. +* @fdt: Flattened device tree of the kernel. +* +* Returns 0 on success, negative errno on error. +*/ +static int update_cpus_node (void *fdt) +{ +struct device_node *cpus_node, *dn; +int cpus_offset, cpus_subnode_offset, ret =0 ; + + cpus_offset =fdt_path_offset (fdt,"/cpus" ); +if (cpus_offset <0 && cpus_offset != -FDT_ERR_NOTFOUND ) { +pr_err ("Malformed device tree: error reading /cpus node: %s\n" , +fdt_strerror (cpus_offset)); +return cpus_offset; + } + +if (cpus_offset >0 ) { + ret =fdt_del_node (fdt, cpus_offset); +if (ret <0 ) { +pr_err ("Error deleting /cpus node: %s\n" ,fdt_strerror (ret)); +return -EINVAL ; + } + } + +/* Add cpus node to fdt */ + cpus_offset =fdt_add_subnode (fdt,fdt_path_offset (fdt,"/" ),"cpus" ); +if (cpus_offset <0 ) { +pr_err ("Error creating /cpus node: %s\n" ,fdt_strerror (cpus_offset)); +return -EINVAL ; + } + +/* Add cpus node properties */ + cpus_node =of_find_node_by_path ("/cpus" ); + ret =add_node_props (fdt, cpus_offset, cpus_node); +of_node_put (cpus_node); +if (ret <0 ) +return ret; + +/* Loop through all subnodes of cpus and add them to fdt */ +for_each_node_by_type (dn,"cpu" ) { + cpus_subnode_offset =fdt_add_subnode (fdt, cpus_offset, dn->full_name); +if (cpus_subnode_offset <0 ) { +pr_err ("Unable to add %s subnode: %s\n" , dn->full_name, +fdt_strerror (cpus_subnode_offset)); + ret = cpus_subnode_offset; + goto out; + } + + ret =add_node_props (fdt, cpus_subnode_offset, dn); +if (ret <0 ) + goto out; + } +out: +of_node_put (dn); +return ret; +} + +/** * setup_new_fdt_ppc64 - Update the flattend device-tree of the kernel * being loaded. * @image: kexec image being loaded.
@@ -1020,6 +1107,11 @@ int setup_new_fdt_ppc64(const struct kim } } +/* Update cpus nodes information to account hotplug CPUs. */ + ret =update_cpus_node (fdt); +if (ret <0 ) + goto out; +/* Update memory reserve map */ ret =get_reserved_memory_ranges (&rmem);if (ret)
Greg Kroah-Hartman
maintainerPATCH 309/384 powerpc/32: Fix boot failure with CONFIG_STACKPROTECTOR
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit f5668260b872e89b8d3942a8b7d4278aa9c2c981 upstream.
Commit 7c95d8893fb5 ("powerpc: Change calling convention for create_branch() et. al.") complexified the frame of function do_feature_fixups(), leading to GCC setting up a stack guard when CONFIG_STACKPROTECTOR is selected.
The problem is that do_feature_fixups() is called very early while 'current' in r2 is not set up yet and the code is still not at the final address used at link time.
So, like other instrumentation, stack protection needs to be deactivated for feature-fixups.c and code-patching.c
--- arch/powerpc/lib/Makefile | 3 +++ 1 file changed, 3 insertions(+)
arch/powerpc/lib/Makefile +3 -0
@@ -5,6 +5,9 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) +CFLAGS_code-patching.o += -fno-stack-protector +CFLAGS_feature-fixups.o += -fno-stack-protector + CFLAGS_REMOVE_code-patching.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_feature-fixups.o = $(CC_FLAGS_FTRACE)
Greg Kroah-Hartman
maintainerPATCH 310/384 powerpc: fix EDEADLOCK redefinition error in uapi/asm/errno.h
In reply to Greg Kroah-HartmanFrom: Tony Ambardar <[email protected]>
commit 7de21e679e6a789f3729e8402bc440b623a28eae upstream.
A few archs like powerpc have different errno.h values for macros EDEADLOCK and EDEADLK. In code including both libc and linux versions of errno.h, this can result in multiple definitions of EDEADLOCK in the include chain. Definitions to the same value (e.g. seen with mips) do not raise warnings, but on powerpc there are redefinitions changing the value, which raise warnings and errors (if using "-Werror").
Guard against these redefinitions to avoid build errors like the following, first seen cross-compiling libbpf v5.8.9 for powerpc using GCC 8.4.0 with musl 1.1.24:
In file included from ../../arch/powerpc/include/uapi/asm/errno.h:5,
from ../../include/linux/err.h:8,
from libbpf.c:29: ../../include/uapi/asm-generic/errno.h:40: error: "EDEADLOCK" redefined [-Werror]
#define EDEADLOCK EDEADLK
In file included from toolchain-powerpc_8540_gcc-8.4.0_musl/include/errno.h:10,
from libbpf.c:26:
toolchain-powerpc_8540_gcc-8.4.0_musl/include/bits/errno.h:58: note: this is the location of the previous definition
#define EDEADLOCK 58
cc1: all warnings being treated as errors
--- arch/powerpc/include/uapi/asm/errno.h | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/include/uapi/asm/errno.h +1 -0
@@ -2,6 +2,7 @@#ifndef _ASM_POWERPC_ERRNO_H#define _ASM_POWERPC_ERRNO_H +#undef EDEADLOCK#include <asm-generic/errno.h> #undef EDEADLOCK
Greg Kroah-Hartman
maintainerPATCH 311/384 powerpc/kvm: Fix PR KVM with KUAP/MEM_KEYS enabled
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit e4e8bc1df691ba5ba749d1e2b67acf9827e51a35 upstream.
The changes to add KUAP support with the hash MMU broke booting of KVM PR guests. The symptom is no visible progress of the guest, or possibly just "SLOF" being printed to the qemu console.
Host code is still executing, but breaking into xmon might show a stack trace such as:
__might_fault+0x84/0xe0 (unreliable) kvm_read_guest+0x1c8/0x2f0 [kvm] kvmppc_ld+0x1b8/0x2d0 [kvm] kvmppc_load_last_inst+0x50/0xa0 [kvm] kvmppc_exit_pr_progint+0x178/0x220 [kvm_pr] kvmppc_handle_exit_pr+0x31c/0xe30 [kvm_pr] after_sprg3_load+0x80/0x90 [kvm_pr] kvmppc_vcpu_run_pr+0x104/0x260 [kvm_pr] kvmppc_vcpu_run+0x34/0x48 [kvm] kvm_arch_vcpu_ioctl_run+0x340/0x450 [kvm] kvm_vcpu_ioctl+0x2ac/0x8c0 [kvm] sys_ioctl+0x320/0x1060 system_call_exception+0x160/0x270 system_call_common+0xf0/0x27c
Bisect points to commit b2ff33a10c8b ("powerpc/book3s64/hash/kuap:
Enable kuap on hash"), but that's just the commit that enabled KUAP with hash and made the bug visible.
The root cause seems to be that KVM PR is creating kernel mappings that don't use the correct key, since we switched to using key 3.
We have a helper for adding the right key value, however it's designed to take a pteflags variable, which the KVM code doesn't have. But we can make it work by passing 0 for the pteflags, and tell it explicitly that it should use the kernel key.
With that changed guests boot successfully.
--- arch/powerpc/kvm/book3s_64_mmu_host.c | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/kvm/book3s_64_mmu_host.c +2 -0
@@ -12,6 +12,7 @@#include <asm/kvm_ppc.h> #include <asm/kvm_book3s.h> #include <asm/book3s/64/mmu-hash.h> +#include <asm/book3s/64/pkeys.h> #include <asm/machdep.h> #include <asm/mmu_context.h> #include <asm/hw_irq.h>
@@ -133,6 +134,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpuelse kvmppc_mmu_flush_icache (pfn); + rflags |=pte_to_hpte_pkey_bits (0 ,HPTE_USE_KERNEL_KEY ); rflags = (rflags & ~HPTE_R_WIMG ) | orig_pte->wimg;/*
Greg Kroah-Hartman
maintainerPATCH 312/384 powerpc/kvm: Fix build error when PPC_MEM_KEYS/PPC_PSERIES=n
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit ee1bc694fbaec1a662770703fc34a74abf418938 upstream.
lkp reported a randconfig failure:
In file included from arch/powerpc/include/asm/book3s/64/pkeys.h:6,
from arch/powerpc/kvm/book3s_64_mmu_host.c:15:
arch/powerpc/include/asm/book3s/64/hash-pkey.h: In function 'hash__vmflag_to_pte_pkey_bits':
Quoted 1 line
Quoted 1 line
arch/powerpc/include/asm/book3s/64/hash-pkey.h:10:23: error: 'VM_PKEY_BIT0' undeclared
10 | return (((vm_flags & VM_PKEY_BIT0) ? H_PTE_PKEY_BIT0 : 0x0UL) |
| ^~~~~~~~~~~~We added the include of book3s/64/pkeys.h for pte_to_hpte_pkey_bits(), but that header on its own should only be included when PPC_MEM_KEYS=y. Instead include linux/pkeys.h, which brings in the right definitions when PPC_MEM_KEYS=y and also provides empty stubs when PPC_MEM_KEYS=n.
--- arch/powerpc/kvm/book3s_64_mmu_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kvm/book3s_64_mmu_host.c +1 -1
@@ -8,11 +8,11 @@*/ #include <linux/kvm_host.h> +#include <linux/pkeys.h> #include <asm/kvm_ppc.h> #include <asm/kvm_book3s.h> #include <asm/book3s/64/mmu-hash.h> -#include <asm/book3s/64/pkeys.h> #include <asm/machdep.h> #include <asm/mmu_context.h> #include <asm/hw_irq.h>
Greg Kroah-Hartman
maintainerPATCH 313/384 intel_th: pci: Add Alder Lake-M support
In reply to Greg Kroah-HartmanFrom: Alexander Shishkin <[email protected]>
commit 48cb17531b15967d9d3f34c770a25cc6c4ca6ad1 upstream.
This adds support for the Trace Hub in Alder Lake-M PCH.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -274,6 +274,11 @@ static const struct pci_device_id intel_ .driver_data = (kernel_ulong_t)&intel_th_2x, }, { +/* Alder Lake-M */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x54a6), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + {/* Alder Lake CPU */ PCI_DEVICE (PCI_VENDOR_ID_INTEL ,0x466f ), .driver_data = (kernel_ulong_t)&intel_th_2x,
Greg Kroah-Hartman
maintainerPATCH 314/384 tpm: efi: Use local variable for calculating final log size
In reply to Greg Kroah-HartmanFrom: Stefan Berger <[email protected]>
commit 48cff270b037022e37835d93361646205ca25101 upstream.
When tpm_read_log_efi is called multiple times, which happens when one loads and unloads a TPM2 driver multiple times, then the global variable efi_tpm_final_log_size will at some point become a negative number due to the subtraction of final_events_preboot_size occurring each time. Use a local variable to avoid this integer underflow.
The following issue is now resolved:
Mar 8 15:35:12 hibinst kernel: Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 Mar 8 15:35:12 hibinst kernel: Workqueue: tpm-vtpm vtpm_proxy_work [tpm_vtpm_proxy] Mar 8 15:35:12 hibinst kernel: RIP: 0010:__memcpy+0x12/0x20 Mar 8 15:35:12 hibinst kernel: Code: 00 b8 01 00 00 00 85 d2 74 0a c7 05 44 7b ef 00 0f 00 00 00 c3 cc cc cc 66 66 90 66 90 48 89 f8 48 89 d1 48 c1 e9 03 83 e2 07 <f3> 48 a5 89 d1 f3 a4 c3 66 0f 1f 44 00 00 48 89 f8 48 89 d1 f3 a4 Mar 8 15:35:12 hibinst kernel: RSP: 0018:ffff9ac4c0fcfde0 EFLAGS: 00010206 Mar 8 15:35:12 hibinst kernel: RAX: ffff88f878cefed5 RBX: ffff88f878ce9000 RCX: 1ffffffffffffe0f Mar 8 15:35:12 hibinst kernel: RDX: 0000000000000003 RSI: ffff9ac4c003bff9 RDI: ffff88f878cf0e4d Mar 8 15:35:12 hibinst kernel: RBP: ffff9ac4c003b000 R08: 0000000000001000 R09: 000000007e9d6073 Mar 8 15:35:12 hibinst kernel: R10: ffff9ac4c003b000 R11: ffff88f879ad3500 R12: 0000000000000ed5 Mar 8 15:35:12 hibinst kernel: R13: ffff88f878ce9760 R14: 0000000000000002 R15: ffff88f77de7f018 Mar 8 15:35:12 hibinst kernel: FS: 0000000000000000(0000) GS:ffff88f87bd00000(0000) knlGS:0000000000000000 Mar 8 15:35:12 hibinst kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Mar 8 15:35:12 hibinst kernel: CR2: ffff9ac4c003c000 CR3: 00000001785a6004 CR4: 0000000000060ee0 Mar 8 15:35:12 hibinst kernel: Call Trace: Mar 8 15:35:12 hibinst kernel: tpm_read_log_efi+0x152/0x1a7 Mar 8 15:35:12 hibinst kernel: tpm_bios_log_setup+0xc8/0x1c0 Mar 8 15:35:12 hibinst kernel: tpm_chip_register+0x8f/0x260 Mar 8 15:35:12 hibinst kernel: vtpm_proxy_work+0x16/0x60 [tpm_vtpm_proxy] Mar 8 15:35:12 hibinst kernel: process_one_work+0x1b4/0x370 Mar 8 15:35:12 hibinst kernel: worker_thread+0x53/0x3e0 Mar 8 15:35:12 hibinst kernel: ? process_one_work+0x370/0x370
--- drivers/char/tpm/eventlog/efi.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)
drivers/char/tpm/eventlog/efi.c +21 -8
@@ -17,6 +17,7 @@ int tpm_read_log_efi(struct tpm_chip *ch {struct efi_tcg2_final_events_table *final_tbl =NULL ; +int final_events_log_size = efi_tpm_final_log_size;struct linux_efi_tpm_eventlog *log_tbl;struct tpm_bios_log *log;u32 log_size;
@@ -66,12 +67,12 @@ int tpm_read_log_efi(struct tpm_chip *ch ret = tpm_log_version;if (efi.tpm_final_log ==EFI_INVALID_TABLE_ADDR || - efi_tpm_final_log_size ==0 || + final_events_log_size ==0 || tpm_log_version !=EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 ) goto out; final_tbl =memremap (efi.tpm_final_log, -sizeof (*final_tbl) + efi_tpm_final_log_size, +sizeof (*final_tbl) + final_events_log_size,MEMREMAP_WB );if (!final_tbl) {pr_err ("Could not map UEFI TPM final log\n" );
@@ -80,10 +81,18 @@ int tpm_read_log_efi(struct tpm_chip *ch goto out; } - efi_tpm_final_log_size -= log_tbl->final_events_preboot_size; +/* +* The 'final events log' size excludes the 'final events preboot log' +* at its beginning. +*/ + final_events_log_size -= log_tbl->final_events_preboot_size; +/* +* Allocate memory for the 'combined log' where we will append the +* 'final events log' to. +*/ tmp =krealloc (log->bios_event_log, - log_size + efi_tpm_final_log_size, + log_size + final_events_log_size,GFP_KERNEL );if (!tmp) {kfree (log->bios_event_log);
@@ -94,15 +103,19 @@ int tpm_read_log_efi(struct tpm_chip *ch log->bios_event_log = tmp;/* -* Copy any of the final events log that didn't also end up in the -* main log. Events can be logged in both if events are generated +* Append any of the 'final events log' that didn't also end up in the +* 'main log'. Events can be logged in both if events are generated * between GetEventLog() and ExitBootServices(). */ memcpy ((void *)log->bios_event_log + log_size, final_tbl->events + log_tbl->final_events_preboot_size, - efi_tpm_final_log_size); + final_events_log_size); +/* +* The size of the 'combined log' is the size of the 'main log' plus +* the size of the 'final events log'. +*/ log->bios_event_log_end = log->bios_event_log + - log_size + efi_tpm_final_log_size; + log_size + final_events_log_size; out:memunmap (final_tbl);
Greg Kroah-Hartman
maintainerPATCH 315/384 tpm: vtpm_proxy: Avoid reading host log when using a virtual device
In reply to Greg Kroah-HartmanFrom: Stefan Berger <[email protected]>
commit 9716ac65efc8f780549b03bddf41e60c445d4709 upstream.
Avoid allocating memory and reading the host log when a virtual device is used since this log is of no use to that driver. A virtual device can be identified through the flag TPM_CHIP_FLAG_VIRTUAL, which is only set for the tpm_vtpm_proxy driver.
--- drivers/char/tpm/eventlog/common.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/char/tpm/eventlog/common.c +3 -0
@@ -107,6 +107,9 @@ void tpm_bios_log_setup(struct tpm_chipint log_version;int rc =0 ; +if (chip->flags &TPM_CHIP_FLAG_VIRTUAL ) +return ; + rc =tpm_read_log (chip);if (rc <0 )return ;
Greg Kroah-Hartman
maintainerPATCH 316/384 crypto: arm/curve25519 - Move .fpu after .arch
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit 44200f2d9b8b52389c70e6c7bbe51e0dc6eaf938 upstream.
Debian's clang carries a patch that makes the default FPU mode 'vfp3-d16' instead of 'neon' for 'armv7-a' to avoid generating NEON instructions on hardware that does not support them:
https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/raw/5a61ca6f21b4ad8c6ac4970e5ea5a7b5b4486d22/debian/patches/clang-arm-default-vfp3-on-armv7a.patch
https://bugs.debian.org/841474
https://bugs.debian.org/842142
https://bugs.debian.org/914268
This results in the following build error when clang's integrated assembler is used because the '.arch' directive overrides the '.fpu' directive:
arch/arm/crypto/curve25519-core.S:25:2: error: instruction requires: NEON
vmov.i32 q0, #1
^arch/arm/crypto/curve25519-core.S:26:2: error: instruction requires: NEON
vshr.u64 q1, q0, #7
^arch/arm/crypto/curve25519-core.S:27:2: error: instruction requires: NEON
vshr.u64 q0, q0, #8
^arch/arm/crypto/curve25519-core.S:28:2: error: instruction requires: NEON
vmov.i32 d4, #19
^
Shuffle the order of the '.arch' and '.fpu' directives so that the code builds regardless of the default FPU mode. This has been tested against both clang with and without Debian's patch and GCC.
--- arch/arm/crypto/curve25519-core.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/crypto/curve25519-core.S +1 -1
@@ -10,8 +10,8 @@ #include <linux/linkage.h> .text -.fpu neon .arch armv7-a +.fpu neon .align 4 ENTRY(curve25519_neon)
Greg Kroah-Hartman
maintainerPATCH 317/384 crypto: rng - fix crypto_rng_reset() refcounting when !CRYPTO_STATS
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 30d0f6a956fc74bb2e948398daf3278c6b08c7e9 upstream.
crypto_stats_get() is a no-op when the kernel is compiled without CONFIG_CRYPTO_STATS, so pairing it with crypto_alg_put() unconditionally (as crypto_rng_reset() does) is wrong.
Fix this by moving the call to crypto_stats_get() to just before the actual algorithm operation which might need it. This makes it always paired with crypto_stats_rng_seed().
--- crypto/rng.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
crypto/rng.c +3 -7
@@ -34,22 +34,18 @@ int crypto_rng_reset(struct crypto_rng *u8 *buf =NULL ;int err; -crypto_stats_get (alg);if (!seed && slen) { buf =kmalloc (slen,GFP_KERNEL ); -if (!buf) { -crypto_alg_put (alg); +if (!buf)return -ENOMEM ; - } err =get_random_bytes_wait (buf, slen); -if (err) { -crypto_alg_put (alg); +if (err) goto out; - } seed = buf; } +crypto_stats_get (alg); err =crypto_rng_alg (tfm)->seed (tfm, seed, slen);crypto_stats_rng_seed (alg, err); out:
Greg Kroah-Hartman
maintainerPATCH 318/384 md/raid1: properly indicate failure when ending a failed write request
In reply to Greg Kroah-HartmanFrom: Paul Clements <[email protected]>
commit 2417b9869b81882ab90fd5ed1081a1cb2d4db1dd upstream.
This patch addresses a data corruption bug in raid1 arrays using bitmaps. Without this fix, the bitmap bits for the failed I/O end up being cleared.
Since we are in the failure leg of raid1_end_write_request, the request either needs to be retried (R1BIO_WriteError) or failed (R1BIO_Degraded).
--- drivers/md/raid1.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/md/raid1.c +2 -0
@@ -478,6 +478,8 @@ static void raid1_end_write_request(struif (!test_bit (Faulty, &rdev->flags))set_bit (R1BIO_WriteError, &r1_bio->state);else { +/* Fail the request */ +set_bit (R1BIO_Degraded, &r1_bio->state);/* Finished with this branch */ r1_bio->bios[mirror] =NULL ; to_put = bio;
Greg Kroah-Hartman
maintainerPATCH 319/384 dm raid: fix inconclusive reshape layout on fast raid4/5/6 table reload sequences
In reply to Greg Kroah-HartmanFrom: Heinz Mauelshagen <[email protected]>
commit f99a8e4373eeacb279bc9696937a55adbff7a28a upstream.
If fast table reloads occur during an ongoing reshape of raid4/5/6 devices the target may race reading a superblock vs the the MD resync thread; causing an inconclusive reshape state to be read in its constructor.
lvm2 test lvconvert-raid-reshape-stripes-load-reload.sh can cause BUG_ON() to trigger in md_run(), e.g.:
"kernel BUG at drivers/md/raid5.c:7567!".
Scenario triggering the bug:
1. the MD sync thread calls end_reshape() from raid5_sync_request() when done reshaping. However end_reshape() _only_ updates the reshape position to MaxSector keeping the changed layout configuration though (i.e. any delta disks, chunk sector or RAID algorithm changes). That inconclusive configuration is stored in the superblock.
2. dm-raid constructs a mapping, loading named inconsistent superblock as of step 1 before step 3 is able to finish resetting the reshape state completely, and calls md_run() which leads to mentioned bug in raid5.c.
3. the MD RAID personality's finish_reshape() is called; which resets the reshape information on chunk sectors, delta disks, etc. This explains why the bug is rarely seen on multi-core machines, as MD's finish_reshape() superblock update races with the dm-raid constructor's superblock load in step 2.
Fix identifies inconclusive superblock content in the dm-raid constructor and resets it before calling md_run(), factoring out identifying checks into rs_is_layout_change() to share in existing rs_reshape_requested() and new rs_reset_inclonclusive_reshape(). Also enhance a comment and remove an empty line.
--- drivers/md/dm-raid.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-)
drivers/md/dm-raid.c +28 -6
@@ -1868,6 +1868,14 @@ static bool rs_takeover_requested(structreturn rs->md.new_level != rs->md.level; } +/* True if layout is set to reshape. */ +static bool rs_is_layout_change (struct raid_set *rs,bool use_mddev) +{ +return (use_mddev ? rs->md.delta_disks : rs->delta_disks) || + rs->md.new_layout != rs->md.layout || + rs->md.new_chunk_sectors != rs->md.chunk_sectors; +} +/* True if @rs is requested to reshape by ctr */ static bool rs_reshape_requested (struct raid_set *rs) {
@@ -1880,9 +1888,7 @@ static bool rs_reshape_requested(structif (rs_is_raid0 (rs))return false; - change = mddev->new_layout != mddev->layout || - mddev->new_chunk_sectors != mddev->chunk_sectors || - rs->delta_disks; + change =rs_is_layout_change (rs, false);/* Historical case to support raid1 reshape without delta disks */ if (rs_is_raid1 (rs)) {
@@ -2817,7 +2823,7 @@ static sector_t _get_reshape_sectors(str }/* -* +* Reshape: * - change raid layout * - change chunk size * - add disks
@@ -2927,6 +2933,20 @@ static int rs_setup_reshape(struct raid_ }/* +* If the md resync thread has updated superblock with max reshape position +* at the end of a reshape but not (yet) reset the layout configuration +* changes -> reset the latter. +*/ +static void rs_reset_inconclusive_reshape (struct raid_set *rs) +{ +if (!rs_is_reshaping (rs) &&rs_is_layout_change (rs, true)) { +rs_set_cur (rs); + rs->md.delta_disks =0 ; + rs->md.reshape_backwards =0 ; + } +} + +/* * Enable/disable discard support on RAID set depending on * RAID level and discard properties of underlying RAID members. */
@@ -3212,11 +3232,14 @@ size_check:if (r) goto bad; +/* Catch any inconclusive reshape superblock content. */ +rs_reset_inconclusive_reshape (rs); +/* Start raid set read-only and assumed clean to change in raid_resume() */ rs->md.ro =1 ; rs->md.in_sync =1 ; -/* Keep array frozen */ +/* Keep array frozen until resume. */ set_bit (MD_RECOVERY_FROZEN , &rs->md.recovery);/* Has to be held on running the array */
@@ -3230,7 +3253,6 @@ size_check: } r =md_start (&rs->md); -if (r) { ti->error ="Failed to start raid array" ;mddev_unlock (&rs->md);
Greg Kroah-Hartman
maintainerPATCH 320/384 fuse: fix write deadlock
In reply to Greg Kroah-HartmanFrom: Vivek Goyal <[email protected]>
commit 4f06dd92b5d0a6f8eec6a34b8d6ef3e1f4ac1e10 upstream.
There are two modes for write(2) and friends in fuse:
a) write through (update page cache, send sync WRITE request to userspace)
b) buffered write (update page cache, async writeout later)
The write through method kept all the page cache pages locked that were used for the request. Keeping more than one page locked is deadlock prone and Qian Cai demonstrated this with trinity fuzzing.
The reason for keeping the pages locked is that concurrent mapped reads shouldn't try to pull possibly stale data into the page cache.
For full page writes, the easy way to fix this is to make the cached page be the authoritative source by marking the page PG_uptodate immediately. After this the page can be safely unlocked, since mapped/cached reads will take the written data from the cache.
Concurrent mapped writes will now cause data in the original WRITE request to be updated; this however doesn't cause any data inconsistency and this scenario should be exceedingly rare anyway.
If the WRITE request returns with an error in the above case, currently the page is not marked uptodate; this means that a concurrent read will always read consistent data. After this patch the page is uptodate between writing to the cache and receiving the error: there's window where a cached read will read the wrong data. While theoretically this could be a regression, it is unlikely to be one in practice, since this is normal for buffered writes.
In case of a partial page write to an already uptodate page the locking is also unnecessary, with the above caveats.
Partial write of a not uptodate page still needs to be handled. One way would be to read the complete page before doing the write. This is not possible, since it might break filesystems that don't expect any READ requests when the file was opened O_WRONLY.
The other solution is to serialize the synchronous write with reads from the partial pages. The easiest way to do this is to keep the partial pages locked. The problem is that a write() may involve two such pages (one head and one tail). This patch fixes it by only locking the partial tail page. If there's a partial head page as well, then split that off as a separate WRITE request.
--- fs/fuse/file.c | 41 +++++++++++++++++++++++++++++------------ fs/fuse/fuse_i.h | 1 + 2 files changed, 30 insertions(+), 12 deletions(-)
fs/fuse/file.c +29 -12
@@ -1099,6 +1099,7 @@ static ssize_t fuse_send_write_pages(strstruct fuse_file *ff = file->private_data;struct fuse_mount *fm = ff->fm;unsigned int offset, i; +bool short_write;int err;for (i =0 ; i < ap->num_pages; i++)
@@ -1113,32 +1114,38 @@ static ssize_t fuse_send_write_pages(strif (!err && ia->write.out.size > count) err = -EIO ; + short_write = ia->write.out.size < count; offset = ap->descs[0 ].offset; count = ia->write.out.size;for (i =0 ; i < ap->num_pages; i++) {struct page *page = ap->pages[i]; -if (!err && !offset && count >=PAGE_SIZE ) -SetPageUptodate (page); - -if (count >PAGE_SIZE - offset) - count -=PAGE_SIZE - offset; -else - count =0 ; - offset =0 ; - -unlock_page (page); +if (err) { +ClearPageUptodate (page); + }else { +if (count >=PAGE_SIZE - offset) + count -=PAGE_SIZE - offset; +else { +if (short_write) +ClearPageUptodate (page); + count =0 ; + } + offset =0 ; + } +if (ia->write.page_locked && (i == ap->num_pages -1 )) +unlock_page (page);put_page (page); }return err; } -static ssize_t fuse_fill_write_pages (struct fuse_args_pages *ap, +static ssize_t fuse_fill_write_pages (struct fuse_io_args *ia,struct address_space *mapping,struct iov_iter *ii,loff_t pos,unsigned int max_pages) { +struct fuse_args_pages *ap = &ia->ap;struct fuse_conn *fc =get_fuse_conn (mapping->host);unsigned offset = pos & (PAGE_SIZE -1 );size_t count =0 ;
@@ -1191,6 +1198,16 @@ static ssize_t fuse_fill_write_pages(strif (offset ==PAGE_SIZE ) offset =0 ; +/* If we copied full page, mark it uptodate */ +if (tmp ==PAGE_SIZE ) +SetPageUptodate (page); + +if (PageUptodate (page)) { +unlock_page (page); + }else { + ia->write.page_locked = true; +break ; + }if (!fc->big_writes)break ; } while (iov_iter_count(ii) && count < fc->max_write &&
@@ -1234,7 +1251,7 @@ static ssize_t fuse_perform_write(structbreak ; } - count =fuse_fill_write_pages (ap, mapping, ii, pos, nr_pages); + count =fuse_fill_write_pages (&ia, mapping, ii, pos, nr_pages);if (count <=0 ) { err = count; }else {
fs/fuse/fuse_i.h +1 -0
@@ -912,6 +912,7 @@ struct fuse_io_args {struct {struct fuse_write_in in;struct fuse_write_out out; +bool page_locked; } write; };struct fuse_args_pages ap;
Greg Kroah-Hartman
maintainerPATCH 321/384 mm: page_alloc: ignore init_on_free=1 for debug_pagealloc=1
In reply to Greg Kroah-HartmanFrom: Sergei Trofimovich <[email protected]>
commit 9df65f522536719682bccd24245ff94db956256c upstream.
On !ARCH_SUPPORTS_DEBUG_PAGEALLOC (like ia64) debug_pagealloc=1 implies page_poison=on:
if (page_poisoning_enabled() ||
(!IS_ENABLED(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC) &&
debug_pagealloc_enabled()))
static_branch_enable(&_page_poisoning_enabled);page_poison=on needs to override init_on_free=1.
Before the change it did not work as expected for the following case:
- have PAGE_POISONING=y
- have page_poison unset
- have !ARCH_SUPPORTS_DEBUG_PAGEALLOC arch (like ia64)
- have init_on_free=1
- have debug_pagealloc=1
That way we get both keys enabled:
- static_branch_enable(&init_on_free);
- static_branch_enable(&_page_poisoning_enabled);
which leads to poisoned pages returned for __GFP_ZERO pages.
After the change we execute only:
- static_branch_enable(&_page_poisoning_enabled);
and ignore init_on_free=1.
--- mm/page_alloc.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-)
mm/page_alloc.c +17 -13
@@ -764,32 +764,36 @@ static inline void clear_page_guard(stru*/ void init_mem_debugging_and_hardening (void ) { +bool page_poisoning_requested = false; + +#ifdef CONFIG_PAGE_POISONING +/* +* Page poisoning is debug page alloc for some arches. If +* either of those options are enabled, enable poisoning. +*/ +if (page_poisoning_enabled () || + (!IS_ENABLED (CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC ) && +debug_pagealloc_enabled ())) { +static_branch_enable (&_page_poisoning_enabled); + page_poisoning_requested = true; + } +#endif +if (_init_on_alloc_enabled_early) { -if (page_poisoning_enabled ()) +if (page_poisoning_requested)pr_info ("mem auto-init: CONFIG_PAGE_POISONING is on, " "will take precedence over init_on_alloc\n" );else static_branch_enable (&init_on_alloc); }if (_init_on_free_enabled_early) { -if (page_poisoning_enabled ()) +if (page_poisoning_requested)pr_info ("mem auto-init: CONFIG_PAGE_POISONING is on, " "will take precedence over init_on_free\n" );else static_branch_enable (&init_on_free); } -#ifdef CONFIG_PAGE_POISONING -/* -* Page poisoning is debug page alloc for some arches. If -* either of those options are enabled, enable poisoning. -*/ -if (page_poisoning_enabled () || - (!IS_ENABLED (CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC ) && -debug_pagealloc_enabled ())) -static_branch_enable (&_page_poisoning_enabled); -#endif -#ifdef CONFIG_DEBUG_PAGEALLOC if (!debug_pagealloc_enabled ())return ;
Greg Kroah-Hartman
maintainerPATCH 322/384 exfat: fix erroneous discard when clear cluster bit
In reply to Greg Kroah-HartmanFrom: Hyeongseok Kim <[email protected]>
commit 77edfc6e51055b61cae2f54c8e6c3bb7c762e4fe upstream.
If mounted with discard option, exFAT issues discard command when clear cluster bit to remove file. But the input parameter of cluster-to-sector calculation is abnormally added by reserved cluster size which is 2, leading to discard unrelated sectors included in target+2 cluster. With fixing this, remove the wrong comments in set/clear/find bitmap functions.
--- fs/exfat/balloc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
fs/exfat/balloc.c +1 -10
@@ -141,10 +141,6 @@ void exfat_free_bitmap(struct exfat_sb_ikfree (sbi->vol_amap); } -/* -* If the value of "clu" is 0, it means cluster 2 which is the first cluster of -* the cluster heap. -*/ int exfat_set_bitmap (struct inode *inode,unsigned int clu) {int i, b;
@@ -162,10 +158,6 @@ int exfat_set_bitmap(struct inode *inodereturn 0 ; } -/* -* If the value of "clu" is 0, it means cluster 2 which is the first cluster of -* the cluster heap. -*/ void exfat_clear_bitmap (struct inode *inode,unsigned int clu,bool sync) {int i, b;
@@ -186,8 +178,7 @@ void exfat_clear_bitmap(struct inode *inint ret_discard; ret_discard =sb_issue_discard (sb, -exfat_cluster_to_sector (sbi, clu + -EXFAT_RESERVED_CLUSTERS ), +exfat_cluster_to_sector (sbi, clu), (1 << sbi->sect_per_clus_bits),GFP_NOFS ,0 );if (ret_discard == -EOPNOTSUPP ) {
Greg Kroah-Hartman
maintainerPATCH 323/384 sfc: farch: fix TX queue lookup in TX flush done handling
In reply to Greg Kroah-HartmanFrom: Edward Cree <[email protected]>
commit 5b1faa92289b53cad654123ed2bc8e10f6ddd4ac upstream.
We're starting from a TXQ instance number ('qid'), not a TXQ type, so
efx_get_tx_queue() is inappropriate (and could return NULL, leading to panics).
--- drivers/net/ethernet/sfc/farch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/sfc/farch.c +4 -4
@@ -1081,16 +1081,16 @@ static void efx_farch_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event) { struct efx_tx_queue *tx_queue; +struct efx_channel *channel;int qid; qid =EFX_QWORD_FIELD (*event,FSF_AZ_DRIVER_EV_SUBDATA );if (qid <EFX_MAX_TXQ_PER_CHANNEL * (efx->n_tx_channels + efx->n_extra_tx_channels)) { - tx_queue =efx_get_tx_queue (efx, qid /EFX_MAX_TXQ_PER_CHANNEL , - qid %EFX_MAX_TXQ_PER_CHANNEL ); -if (atomic_cmpxchg (&tx_queue->flush_outstanding,1 ,0 )) { + channel =efx_get_tx_channel (efx, qid /EFX_MAX_TXQ_PER_CHANNEL ); + tx_queue = channel->tx_queue + (qid %EFX_MAX_TXQ_PER_CHANNEL ); +if (atomic_cmpxchg (&tx_queue->flush_outstanding,1 ,0 ))efx_farch_magic_event (tx_queue->channel,EFX_CHANNEL_MAGIC_TX_DRAIN (tx_queue)); - } } }
Greg Kroah-Hartman
maintainerPATCH 324/384 sfc: farch: fix TX queue lookup in TX event handling
In reply to Greg Kroah-HartmanFrom: Edward Cree <[email protected]>
commit 83b09a1807415608b387c7bc748d329fefc5617e upstream.
We're starting from a TXQ label, not a TXQ type, so
efx_channel_get_tx_queue() is inappropriate (and could return NULL, leading to panics).
--- drivers/net/ethernet/sfc/farch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/sfc/farch.c +4 -4
@@ -835,14 +835,14 @@ efx_farch_handle_tx_event(struct efx_cha/* Transmit completion */ tx_ev_desc_ptr =EFX_QWORD_FIELD (*event,FSF_AZ_TX_EV_DESC_PTR ); tx_ev_q_label =EFX_QWORD_FIELD (*event,FSF_AZ_TX_EV_Q_LABEL ); - tx_queue =efx_channel_get_tx_queue ( - channel, tx_ev_q_label %EFX_MAX_TXQ_PER_CHANNEL ); + tx_queue = channel->tx_queue + + (tx_ev_q_label %EFX_MAX_TXQ_PER_CHANNEL );efx_xmit_done (tx_queue, tx_ev_desc_ptr); }else if (EFX_QWORD_FIELD (*event,FSF_AZ_TX_EV_WQ_FF_FULL )) {/* Rewrite the FIFO write pointer */ tx_ev_q_label =EFX_QWORD_FIELD (*event,FSF_AZ_TX_EV_Q_LABEL ); - tx_queue =efx_channel_get_tx_queue ( - channel, tx_ev_q_label %EFX_MAX_TXQ_PER_CHANNEL ); + tx_queue = channel->tx_queue + + (tx_ev_q_label %EFX_MAX_TXQ_PER_CHANNEL );netif_tx_lock (efx->net_dev);efx_farch_notify_tx_desc (tx_queue);
Greg Kroah-Hartman
maintainerPATCH 325/384 sfc: adjust efx->xdp_tx_queue_count with the real number of initialized queues
In reply to Greg Kroah-HartmanFrom: Ignat Korchagin <[email protected]>
commit 99ba0ea616aabdc8e26259fd722503e012199a76 upstream.
efx->xdp_tx_queue_count is initially initialized to num_possible_cpus() and is later used to allocate and traverse efx->xdp_tx_queues lookup array. However, we may end up not initializing all the array slots with real queues during probing. This results, for example, in a NULL pointer dereference, when running "# ethtool -S <iface>", similar to below
[2570283.664955][T4126959] BUG: kernel NULL pointer dereference, address: 00000000000000f8 [2570283.681283][T4126959] #PF: supervisor read access in kernel mode [2570283.695678][T4126959] #PF: error_code(0x0000) - not-present page [2570283.710013][T4126959] PGD 0 P4D 0 [2570283.721649][T4126959] Oops: 0000 [#1] SMP PTI [2570283.734108][T4126959] CPU: 23 PID: 4126959 Comm: ethtool Tainted: G O 5.10.20-cloudflare-2021.3.1 #1 [2570283.752641][T4126959] Hardware name: <redacted> [2570283.781408][T4126959] RIP: 0010:efx_ethtool_get_stats+0x2ca/0x330 [sfc] [2570283.796073][T4126959] Code: 00 85 c0 74 39 48 8b 95 a8 0f 00 00 48 85 d2 74 2d 31 c0 eb 07 48 8b 95 a8 0f 00 00 48 63 c8 49 83 c4 08 83 c0 01 48 8b 14 ca <48> 8b 92 f8 00 00 00 49 89 54 24 f8 39 85 a0 0f 00 00 77 d7 48 8b [2570283.831259][T4126959] RSP: 0018:ffffb79a77657ce8 EFLAGS: 00010202 [2570283.845121][T4126959] RAX: 0000000000000019 RBX: ffffb799cd0c9280 RCX: 0000000000000018 [2570283.860872][T4126959] RDX: 0000000000000000 RSI: ffff96dd970ce000 RDI: 0000000000000005 [2570283.876525][T4126959] RBP: ffff96dd86f0a000 R08: ffff96dd970ce480 R09: 000000000000005f [2570283.892014][T4126959] R10: ffffb799cd0c9fff R11: ffffb799cd0c9000 R12: ffffb799cd0c94f8 [2570283.907406][T4126959] R13: ffffffffc11b1090 R14: ffff96dd970ce000 R15: ffffffffc11cd66c [2570283.922705][T4126959] FS: 00007fa7723f8740(0000) GS:ffff96f51fac0000(0000) knlGS:0000000000000000 [2570283.938848][T4126959] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [2570283.952524][T4126959] CR2: 00000000000000f8 CR3: 0000001a73e6e006 CR4: 00000000007706e0 [2570283.967529][T4126959] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [2570283.982400][T4126959] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [2570283.997308][T4126959] PKRU: 55555554 [2570284.007649][T4126959] Call Trace: [2570284.017598][T4126959] dev_ethtool+0x1832/0x2830
Fix this by adjusting efx->xdp_tx_queue_count after probing to reflect the true value of initialized slots in efx->xdp_tx_queues.
--- drivers/net/ethernet/sfc/efx_channels.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/sfc/efx_channels.c +2 -0
@@ -914,6 +914,8 @@ int efx_set_channels(struct efx_nic *efx } } } +if (xdp_queue_number) + efx->xdp_tx_queue_count = xdp_queue_number; rc =netif_set_real_num_tx_queues (efx->net_dev, efx->n_tx_channels);if (rc)
Greg Kroah-Hartman
maintainerPATCH 326/384 rcu/nocb: Fix missed nocb_timer requeue
In reply to Greg Kroah-HartmanFrom: Frederic Weisbecker <[email protected]>
commit b2fcf2102049f6e56981e0ab3d9b633b8e2741da upstream.
This sequence of events can lead to a failure to requeue a CPU's ->nocb_timer:
1. There are no callbacks queued for any CPU covered by CPU 0-2's
->nocb_gp_kthread. Note that ->nocb_gp_kthread is associated with CPU 0.
2. CPU 1 enqueues its first callback with interrupts disabled, and
thus must defer awakening its ->nocb_gp_kthread. It therefore queues its rcu_data structure's ->nocb_timer. At this point, CPU 1's rdp->nocb_defer_wakeup is RCU_NOCB_WAKE.
3. CPU 2, which shares the same ->nocb_gp_kthread, also enqueues a
callback, but with interrupts enabled, allowing it to directly awaken the ->nocb_gp_kthread.
4. The newly awakened ->nocb_gp_kthread associates both CPU 1's
and CPU 2's callbacks with a future grace period and arranges for that grace period to be started.
5. This ->nocb_gp_kthread goes to sleep waiting for the end of this
future grace period.
6. This grace period elapses before the CPU 1's timer fires.
This is normally improbably given that the timer is set for only one jiffy, but timers can be delayed. Besides, it is possible that kernel was built with CONFIG_RCU_STRICT_GRACE_PERIOD=y.
7. The grace period ends, so rcu_gp_kthread awakens the
->nocb_gp_kthread, which in turn awakens both CPU 1's and CPU 2's ->nocb_cb_kthread. Then ->nocb_gb_kthread sleeps waiting for more newly queued callbacks.
8. CPU 1's ->nocb_cb_kthread invokes its callback, then sleeps
waiting for more invocable callbacks.
9. Note that neither kthread updated any ->nocb_timer state,
so CPU 1's ->nocb_defer_wakeup is still set to RCU_NOCB_WAKE.
10. CPU 1 enqueues its second callback, this time with interrupts
enabled so it can wake directly ->nocb_gp_kthread.
It does so with calling wake_nocb_gp() which also cancels the pending timer that got queued in step 2. But that doesn't reset CPU 1's ->nocb_defer_wakeup which is still set to RCU_NOCB_WAKE. So CPU 1's ->nocb_defer_wakeup and its ->nocb_timer are now desynchronized.
11. ->nocb_gp_kthread associates the callback queued in 10 with a new
grace period, arranges for that grace period to start and sleeps waiting for it to complete.
12. The grace period ends, rcu_gp_kthread awakens ->nocb_gp_kthread,
which in turn wakes up CPU 1's ->nocb_cb_kthread which then invokes the callback queued in 10.
13. CPU 1 enqueues its third callback, this time with interrupts
disabled so it must queue a timer for a deferred wakeup. However the value of its ->nocb_defer_wakeup is RCU_NOCB_WAKE which incorrectly indicates that a timer is already queued. Instead, CPU 1's ->nocb_timer was cancelled in 10. CPU 1 therefore fails to queue the ->nocb_timer.
14. CPU 1 has its pending callback and it may go unnoticed until
some other CPU ever wakes up ->nocb_gp_kthread or CPU 1 ever calls an explicit deferred wakeup, for example, during idle entry.
This commit fixes this bug by resetting rdp->nocb_defer_wakeup everytime we delete the ->nocb_timer.
It is quite possible that there is a similar scenario involving ->nocb_bypass_timer and ->nocb_defer_wakeup. However, despite some effort from several people, a failure scenario has not yet been located. However, that by no means guarantees that no such scenario exists. Finding a failure scenario is left as an exercise for the reader, and the "Fixes:" tag below relates to ->nocb_bypass_timer instead of ->nocb_timer.
--- kernel/rcu/tree_plugin.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
kernel/rcu/tree_plugin.h +5 -2
@@ -1646,7 +1646,11 @@ static bool wake_nocb_gp(struct rcu_datarcu_nocb_unlock_irqrestore (rdp, flags);return false; } -del_timer (&rdp->nocb_timer); + +if (READ_ONCE (rdp->nocb_defer_wakeup) >RCU_NOCB_WAKE_NOT ) { +WRITE_ONCE (rdp->nocb_defer_wakeup,RCU_NOCB_WAKE_NOT ); +del_timer (&rdp->nocb_timer); + }rcu_nocb_unlock_irqrestore (rdp, flags);raw_spin_lock_irqsave (&rdp_gp->nocb_gp_lock, flags);if (force ||READ_ONCE (rdp_gp->nocb_gp_sleep)) {
@@ -2265,7 +2269,6 @@ static bool do_nocb_deferred_wakeup_commreturn false; } ndw =READ_ONCE (rdp->nocb_defer_wakeup); -WRITE_ONCE (rdp->nocb_defer_wakeup,RCU_NOCB_WAKE_NOT ); ret =wake_nocb_gp (rdp, ndw ==RCU_NOCB_WAKE_FORCE , flags);trace_rcu_nocb_wake (rcu_state.name, rdp->cpu,TPS ("DeferredWake" ));
Greg Kroah-Hartman
maintainerPATCH 327/384 security: commoncap: fix -Wstringop-overread warning
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit 82e5d8cc768b0c7b03c551a9ab1f8f3f68d5f83f upstream.
gcc-11 introdces a harmless warning for cap_inode_getsecurity:
security/commoncap.c: In function ‘cap_inode_getsecurity’:security/commoncap.c:440:33: error: ‘memcpy’ reading 16 bytes from a region of size 0 [-Werror=stringop-overread]
440 | memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~The problem here is that tmpbuf is initialized to NULL, so gcc assumes it is not accessible unless it gets set by vfs_getxattr_alloc(). This is a legitimate warning as far as I can tell, but the code is correct since it correctly handles the error when that function fails.
Add a separate NULL check to tell gcc about it as well.
--- security/commoncap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/commoncap.c +1 -1
@@ -400,7 +400,7 @@ int cap_inode_getsecurity(struct user_na &tmpbuf, size, GFP_NOFS);dput (dentry); -if (ret <0 ) +if (ret <0 || !tmpbuf)return ret; fs_ns = inode->i_sb->s_user_ns;
Greg Kroah-Hartman
maintainerPATCH 328/384 Fix misc new gcc warnings
In reply to Greg Kroah-HartmanFrom: Linus Torvalds <[email protected]>
commit e7c6e405e171fb33990a12ecfd14e6500d9e5cf2 upstream.
It seems like Fedora 34 ends up enabling a few new gcc warnings, notably "-Wstringop-overread" and "-Warray-parameter".
Both of them cause what seem to be valid warnings in the kernel, where we have array size mismatches in function arguments (that are no longer just silently converted to a pointer to element, but actually checked).
This fixes most of the trivial ones, by making the function declaration match the function definition, and in the case of intel_pm.c, removing the over-specified array size from the argument declaration.
At least one 'stringop-overread' warning remains in the i915 driver, but that one doesn't have the same obvious trivial fix, and may or may not actually be indicative of a bug.
[ It was a mistake to upgrade one of my machines to Fedora 34 while
being busy with the merge window, but if this is the extent of the
compiler upgrade problems, things are better than usual - Linus ]
--- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb.h | 2 +- include/scsi/libfcoe.h | 2 +- net/bluetooth/ecdh_helper.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +1 -1
@@ -2993,7 +2993,7 @@ int ilk_wm_max_level(const struct drm_i9static void intel_print_wm_latency (struct drm_i915_private *dev_priv,const char *name, -const u16 wm[8 ]) +const u16 wm[]) {int level, max_level =ilk_wm_max_level (dev_priv);
drivers/media/usb/dvb-usb/dvb-usb.h +1 -1
@@ -487,7 +487,7 @@ extern int __must_check dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);/* commonly used remote control parsing */ -extern int dvb_usb_nec_rc_key_to_event (struct dvb_usb_device *,u8 [],u32 *,int *); +extern int dvb_usb_nec_rc_key_to_event (struct dvb_usb_device *,u8 [5 ],u32 *,int *);/* commonly used firmware download types and function */ struct hexline {
include/scsi/libfcoe.h +1 -1
@@ -249,7 +249,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctl struct fc_frame *);/* libfcoe funcs */ -u64 fcoe_wwn_from_mac (unsigned char mac[],unsigned int ,unsigned int ); +u64 fcoe_wwn_from_mac (unsigned char mac[MAX_ADDR_LEN ],unsigned int ,unsigned int );int fcoe_libfc_config (struct fc_lport *,struct fcoe_ctlr *,const struct libfc_function_template *,int init_fcp);u32 fcoe_fc_crc (struct fc_frame *fp);
net/bluetooth/ecdh_helper.h +1 -1
@@ -25,6 +25,6 @@int compute_ecdh_secret (struct crypto_kpp *tfm,const u8 pair_public_key[64 ],u8 secret[32 ]); -int set_ecdh_privkey (struct crypto_kpp *tfm,const u8 *private_key); +int set_ecdh_privkey (struct crypto_kpp *tfm,const u8 private_key[32 ]);int generate_ecdh_public_key (struct crypto_kpp *tfm,u8 public_key[64 ]);int generate_ecdh_keys (struct crypto_kpp *tfm,u8 public_key[64 ]);
Greg Kroah-Hartman
maintainerPATCH 329/384 smb3: when mounting with multichannel include it in requested capabilities
In reply to Greg Kroah-HartmanFrom: Steve French <[email protected]>
commit 679971e7213174efb56abc8fab1299d0a88db0e8 upstream.
In the SMB3/SMB3.1.1 negotiate protocol request, we are supposed to advertise CAP_MULTICHANNEL capability when establishing multiple channels has been requested by the user doing the mount. See MS-SMB2 sections 2.2.3 and 3.2.5.2
Without setting it there is some risk that multichannel could fail if the server interpreted the field strictly.
--- fs/cifs/smb2pdu.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/cifs/smb2pdu.c +5 -0
@@ -841,6 +841,8 @@ SMB2_negotiate(const unsigned int xid, s req->SecurityMode =0 ; req->Capabilities =cpu_to_le32 (server->vals->req_capabilities); +if (ses->chan_max >1 ) + req->Capabilities |=cpu_to_le32 (SMB2_GLOBAL_CAP_MULTI_CHANNEL );/* ClientGUID must be zero for SMB2.02 dialect */ if (server->vals->protocol_id ==SMB20_PROT_ID )
@@ -1032,6 +1034,9 @@ int smb3_validate_negotiate(const unsign pneg_inbuf->Capabilities =cpu_to_le32 (server->vals->req_capabilities); +if (tcon->ses->chan_max >1 ) + pneg_inbuf->Capabilities |=cpu_to_le32 (SMB2_GLOBAL_CAP_MULTI_CHANNEL ); +memcpy (pneg_inbuf->Guid, server->client_guid,SMB2_CLIENT_GUID_SIZE );
Greg Kroah-Hartman
maintainerPATCH 330/384 smb3: if max_channels set to more than one channel request multichannel
In reply to Greg Kroah-HartmanFrom: Steve French <[email protected]>
commit c1f8a398b6d661b594556a91224b096d92293061 upstream.
Mounting with "multichannel" is obviously implied if user requested more than one channel on mount (ie mount parm max_channels>1). Currently both have to be specified. Fix that so that if max_channels is greater than 1 on mount, enable multichannel rather than silently falling back to non-multichannel.
--- fs/cifs/fs_context.c | 3 +++ 1 file changed, 3 insertions(+)
fs/cifs/fs_context.c +3 -0
@@ -999,6 +999,9 @@ static int smb3_fs_context_parse_param(s goto cifs_parse_mount_err; } ctx->max_channels = result.uint_32; +/* If more than one channel requested ... they want multichan */ +if (result.uint_32 >1 ) + ctx->multichannel = true;break ;case Opt_handletimeout: ctx->handle_timeout = result.uint_32;
Greg Kroah-Hartman
maintainerPATCH 331/384 smb3: do not attempt multichannel to server which does not support it
In reply to Greg Kroah-HartmanFrom: Steve French <[email protected]>
commit 9c2dc11df50d1c8537075ff6b98472198e24438e upstream.
We were ignoring CAP_MULTI_CHANNEL in the server response - if the server doesn't support multichannel we should not be attempting it.
See MS-SMB2 section 3.2.5.2
--- fs/cifs/sess.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/cifs/sess.c +6 -0
@@ -97,6 +97,12 @@ int cifs_try_adding_channels(struct cifsreturn 0 ; } +if (!(ses->server->capabilities &SMB2_GLOBAL_CAP_MULTI_CHANNEL )) { +cifs_dbg (VFS ,"server %s does not support multichannel\n" , ses->server->hostname); + ses->chan_max =1 ; +return 0 ; + } +/* * Make a copy of the iface list at the time and use that * instead so as to not hold the iface spinlock for opening
Greg Kroah-Hartman
maintainerPATCH 332/384 Revert 337f13046ff0 ("futex: Allow FUTEX_CLOCK_REALTIME with FUTEX_WAIT op")
In reply to Greg Kroah-HartmanFrom: Thomas Gleixner <[email protected]>
commit 4fbf5d6837bf81fd7a27d771358f4ee6c4f243f8 upstream.
The FUTEX_WAIT operand has historically a relative timeout which means that the clock id is irrelevant as relative timeouts on CLOCK_REALTIME are not subject to wall clock changes and therefore are mapped by the kernel to CLOCK_MONOTONIC for simplicity.
If a caller would set FUTEX_CLOCK_REALTIME for FUTEX_WAIT the timeout is still treated relative vs. CLOCK_MONOTONIC and then the wait arms that timeout based on CLOCK_REALTIME which is broken and obviously has never been used or even tested.
Reject any attempt to use FUTEX_CLOCK_REALTIME with FUTEX_WAIT again.
The desired functionality can be achieved with FUTEX_WAIT_BITSET and a FUTEX_BITSET_MATCH_ANY argument.
--- kernel/futex.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/futex.c +1 -2
@@ -3711,8 +3711,7 @@ long do_futex(u32 __user *uaddr, int op,if (op &FUTEX_CLOCK_REALTIME ) { flags |=FLAGS_CLOCKRT ; -if (cmd !=FUTEX_WAIT && cmd !=FUTEX_WAIT_BITSET && \ - cmd !=FUTEX_WAIT_REQUEUE_PI ) +if (cmd !=FUTEX_WAIT_BITSET && cmd !=FUTEX_WAIT_REQUEUE_PI )return -ENOSYS ; }
Greg Kroah-Hartman
maintainerPATCH 333/384 futex: Do not apply time namespace adjustment on FUTEX_LOCK_PI
In reply to Greg Kroah-HartmanFrom: Thomas Gleixner <[email protected]>
commit cdf78db4070967869e4d027c11f4dd825d8f815a upstream.
FUTEX_LOCK_PI does not require to have the FUTEX_CLOCK_REALTIME bit set because it has been using CLOCK_REALTIME based absolute timeouts forever. Due to that, the time namespace adjustment which is applied when FUTEX_CLOCK_REALTIME is not set, will wrongly take place for FUTEX_LOCK_PI and wreckage the timeout.
Exclude it from that procedure.
--- kernel/futex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/futex.c +2 -2
@@ -3781,7 +3781,7 @@ SYSCALL_DEFINE6(futex, u32 __user *, uad t =timespec64_to_ktime (ts);if (cmd ==FUTEX_WAIT ) t =ktime_add_safe (ktime_get (), t); -else if (!(op &FUTEX_CLOCK_REALTIME )) +else if (cmd !=FUTEX_LOCK_PI && !(op &FUTEX_CLOCK_REALTIME )) t =timens_ktime_to_host (CLOCK_MONOTONIC , t); tp = &t; }
@@ -3975,7 +3975,7 @@ SYSCALL_DEFINE6(futex_time32, u32 __user t =timespec64_to_ktime (ts);if (cmd ==FUTEX_WAIT ) t =ktime_add_safe (ktime_get (), t); -else if (!(op &FUTEX_CLOCK_REALTIME )) +else if (cmd !=FUTEX_LOCK_PI && !(op &FUTEX_CLOCK_REALTIME )) t =timens_ktime_to_host (CLOCK_MONOTONIC , t); tp = &t; }
Greg Kroah-Hartman
maintainerPATCH 334/384 x86/cpu: Initialize MSR_TSC_AUX if RDTSCP *or* RDPID is supported
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit b6b4fbd90b155a0025223df2c137af8a701d53b3 upstream.
Initialize MSR_TSC_AUX with CPU node information if RDTSCP or RDPID is supported. This fixes a bug where vdso_read_cpunode() will read garbage via RDPID if RDPID is supported but RDTSCP is not. While no known CPU supports RDPID but not RDTSCP, both Intel's SDM and AMD's APM allow for RDPID to exist without RDTSCP, e.g. it's technically a legal CPU model for a virtual machine.
Note, technically MSR_TSC_AUX could be initialized if and only if RDPID is supported since RDTSCP is currently not used to retrieve the CPU node. But, the cost of the superfluous WRMSR is negigible, whereas leaving MSR_TSC_AUX uninitialized is just asking for future breakage if someone decides to utilize RDTSCP.
--- arch/x86/kernel/cpu/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/common.c +1 -1
@@ -1850,7 +1850,7 @@ static inline void setup_getcpu(int cpu)unsigned long cpudata =vdso_encode_cpunode (cpu,early_cpu_to_node (cpu));struct desc_struct d = { }; -if (boot_cpu_has (X86_FEATURE_RDTSCP )) +if (boot_cpu_has (X86_FEATURE_RDTSCP ) ||boot_cpu_has (X86_FEATURE_RDPID ))write_rdtscp_aux (cpudata);/* Store CPU and node number in limit. */
Greg Kroah-Hartman
maintainerPATCH 335/384 kbuild: update config_data.gz only when the content of .config is changed
In reply to Greg Kroah-HartmanFrom: Masahiro Yamada <[email protected]>
commit 46b41d5dd8019b264717978c39c43313a524d033 upstream.
If the timestamp of the .config file is updated, config_data.gz is regenerated, then vmlinux is re-linked. This occurs even if the content of the .config has not changed at all.
This issue was mitigated by commit 67424f61f813 ("kconfig: do not write .config if the content is the same"); Kconfig does not update the .config when it ends up with the identical configuration.
The issue is remaining when the .config is created by *_defconfig with some config fragment(s) applied on top.
This is typical for powerpc and mips, where several *_defconfig targets are constructed by using merge_config.sh.
One workaround is to have the copy of the .config. The filechk rule updates the copy, kernel/config_data, by checking the content instead of the timestamp.
With this commit, the second run with the same configuration avoids the needless rebuilds.
$ make ARCH=mips defconfig all
[ snip ]
$ make ARCH=mips defconfig all
*** Default configuration is based on target '32r2el_defconfig'
Using ./arch/mips/configs/generic_defconfig as base
Merging arch/mips/configs/generic/32r2.config
Merging arch/mips/configs/generic/el.config
Merging ./arch/mips/configs/generic/board-boston.config
Merging ./arch/mips/configs/generic/board-ni169445.config
Merging ./arch/mips/configs/generic/board-ocelot.config
Merging ./arch/mips/configs/generic/board-ranchu.config
Merging ./arch/mips/configs/generic/board-sead-3.config
Merging ./arch/mips/configs/generic/board-xilfpga.config
#
# configuration written to .config
#
SYNC include/config/auto.conf
CALL scripts/checksyscalls.sh
CALL scripts/atomic/check-atomics.sh
CHK include/generated/compile.h
CHK include/generated/autoksyms.h--- kernel/.gitignore | 1 + kernel/Makefile | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-)
kernel/.gitignore +1 -0
@@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only +/config_data kheaders.md5 timeconst.h hz.bc
kernel/Makefile +7 -2
@@ -138,10 +138,15 @@ obj-$(CONFIG_SCF_TORTURE_TEST) += scftor $(obj)/configs.o: $(obj)/config_data.gz -targets += config_data.gz -$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE +targets += config_data config_data.gz +$(obj)/config_data.gz: $(obj)/config_data FORCE $(call if_changed,gzip) +filechk_cat = cat $< + +$(obj)/config_data: $(KCONFIG_CONFIG) FORCE + $(call filechk,cat) + $(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz quiet_cmd_genikh = CHK $(obj)/kheaders_data.tar.xz
Greg Kroah-Hartman
maintainerPATCH 336/384 ext4: annotate data race in start_this_handle()
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 3b1833e92baba135923af4a07e73fe6e54be5a2f upstream.
Access to journal->j_running_transaction is not protected by appropriate lock and thus is racy. We are well aware of that and the code handles the race properly. Just add a comment and data_race() annotation.
--- fs/jbd2/transaction.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/jbd2/transaction.c +6 -1
@@ -349,7 +349,12 @@ static int start_this_handle(journal_t * } alloc_transaction: -if (!journal->j_running_transaction) { +/* +* This check is racy but it is just an optimization of allocating new +* transaction early if there are high chances we'll need it. If we +* guess wrong, we'll retry or free unused transaction. +*/ +if (!data_race (journal->j_running_transaction)) {/* * If __GFP_FS is not present, then we may be being called from * inside the fs writeback layer, so we MUST NOT fail.
Greg Kroah-Hartman
maintainerPATCH 337/384 ext4: annotate data race in jbd2_journal_dirty_metadata()
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 83fe6b18b8d04c6c849379005e1679bac9752466 upstream.
Assertion checks in jbd2_journal_dirty_metadata() are known to be racy but we don't want to be grabbing locks just for them. We thus recheck them under b_state_lock only if it looks like they would fail. Annotate the checks with data_race().
--- fs/jbd2/transaction.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/jbd2/transaction.c +4 -4
@@ -1479,8 +1479,8 @@ int jbd2_journal_dirty_metadata(handle_t* crucial to catch bugs so let's do a reliable check until the * lockless handling is fully proven. */ -if (jh->b_transaction != transaction && - jh->b_next_transaction != transaction) { +if (data_race (jh->b_transaction != transaction && + jh->b_next_transaction != transaction)) {spin_lock (&jh->b_state_lock);J_ASSERT_JH (jh, jh->b_transaction == transaction || jh->b_next_transaction == transaction);
@@ -1488,8 +1488,8 @@ int jbd2_journal_dirty_metadata(handle_t }if (jh->b_modified ==1 ) {/* If it's in our transaction it must be in BJ_Metadata list. */ -if (jh->b_transaction == transaction && - jh->b_jlist != BJ_Metadata) { +if (data_race (jh->b_transaction == transaction && + jh->b_jlist != BJ_Metadata)) {spin_lock (&jh->b_state_lock);if (jh->b_transaction == transaction && jh->b_jlist != BJ_Metadata)
Greg Kroah-Hartman
maintainerPATCH 338/384 ext4: fix check to prevent false positive report of incorrect used inodes
In reply to Greg Kroah-HartmanFrom: Zhang Yi <[email protected]>
commit a149d2a5cabbf6507a7832a1c4fd2593c55fd450 upstream.
Commit <50122847007> ("ext4: fix check to prevent initializing reserved inodes") check the block group zero and prevent initializing reserved inodes. But in some special cases, the reserved inode may not all belong to the group zero, it may exist into the second group if we format filesystem below.
mkfs.ext4 -b 4096 -g 8192 -N 1024 -I 4096 /dev/sda
So, it will end up triggering a false positive report of a corrupted file system. This patch fix it by avoid check reserved inodes if no free inode blocks will be zeroed.
--- fs/ext4/ialloc.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-)
fs/ext4/ialloc.c +32 -16
@@ -1513,6 +1513,7 @@ int ext4_init_inode_table(struct super_bhandle_t *handle;ext4_fsblk_t blk;int num, ret =0 , used_blks =0 ; +unsigned long used_inos =0 ;/* This should not happen, but just to be sure check this */ if (sb_rdonly (sb)) {
@@ -1543,22 +1544,37 @@ int ext4_init_inode_table(struct super_b* used inodes so we need to skip blocks with used inodes in * inode table. */ -if (!(gdp->bg_flags &cpu_to_le16 (EXT4_BG_INODE_UNINIT ))) - used_blks =DIV_ROUND_UP ((EXT4_INODES_PER_GROUP (sb) - -ext4_itable_unused_count (sb, gdp)), - sbi->s_inodes_per_block); - -if ((used_blks <0 ) || (used_blks > sbi->s_itb_per_group) || - ((group ==0 ) && ((EXT4_INODES_PER_GROUP (sb) - -ext4_itable_unused_count (sb, gdp)) < -EXT4_FIRST_INO (sb)))) { -ext4_error (sb,"Something is wrong with group %u: " -"used itable blocks: %d; " -"itable unused count: %u" , - group, used_blks, -ext4_itable_unused_count (sb, gdp)); - ret =1 ; - goto err_out; +if (!(gdp->bg_flags &cpu_to_le16 (EXT4_BG_INODE_UNINIT ))) { + used_inos =EXT4_INODES_PER_GROUP (sb) - +ext4_itable_unused_count (sb, gdp); + used_blks =DIV_ROUND_UP (used_inos, sbi->s_inodes_per_block); + +/* Bogus inode unused count? */ +if (used_blks <0 || used_blks > sbi->s_itb_per_group) { +ext4_error (sb,"Something is wrong with group %u: " +"used itable blocks: %d; " +"itable unused count: %u" , + group, used_blks, +ext4_itable_unused_count (sb, gdp)); + ret =1 ; + goto err_out; + } + + used_inos += group *EXT4_INODES_PER_GROUP (sb); +/* +* Are there some uninitialized inodes in the inode table +* before the first normal inode? +*/ +if ((used_blks != sbi->s_itb_per_group) && + (used_inos <EXT4_FIRST_INO (sb))) { +ext4_error (sb,"Something is wrong with group %u: " +"itable unused count: %u; " +"itables initialized count: %ld" , + group,ext4_itable_unused_count (sb, gdp), + used_inos); + ret =1 ; + goto err_out; + } } blk =ext4_inode_table (sb, gdp) + used_blks;
Greg Kroah-Hartman
maintainerPATCH 339/384 ext4: do not set SB_ACTIVE in ext4_orphan_cleanup()
In reply to Greg Kroah-HartmanFrom: Zhang Yi <[email protected]>
commit 72ffb49a7b623c92a37657eda7cc46a06d3e8398 upstream.
When CONFIG_QUOTA is enabled, if we failed to mount the filesystem due to some error happens behind ext4_orphan_cleanup(), it will end up triggering a after free issue of super_block. The problem is that ext4_orphan_cleanup() will set SB_ACTIVE flag if CONFIG_QUOTA is enabled, after we cleanup the truncated inodes, the last iput() will put them into the lru list, and these inodes' pages may probably dirty and will be write back by the writeback thread, so it could be raced by freeing super_block in the error path of mount_bdev().
After check the setting of SB_ACTIVE flag in ext4_orphan_cleanup(), it was used to ensure updating the quota file properly, but evict inode and trash data immediately in the last iput does not affect the quotafile, so setting the SB_ACTIVE flag seems not required[1]. Fix this issue by just remove the SB_ACTIVE setting.
[1] https://lore.kernel.org/linux-ext4/[email protected]/T/#m04990cfbc4f44592421736b504afcc346b2a7c00
--- fs/ext4/super.c | 3 --- 1 file changed, 3 deletions(-)
fs/ext4/super.c +0 -3
@@ -3023,9 +3023,6 @@ static void ext4_orphan_cleanup(struct s sb->s_flags &= ~SB_RDONLY ; }#ifdef CONFIG_QUOTA -/* Needed for iput() to work correctly and not trash data */ - sb->s_flags |=SB_ACTIVE ; -/* * Turn on quotas which were not enabled for read-only mounts if * filesystem has quota feature, so that they are updated correctly.
Greg Kroah-Hartman
maintainerPATCH 340/384 ext4: always panic when errors=panic is specified
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit ac2f7ca51b0929461ea49918f27c11b680f28995 upstream.
Before commit 014c9caa29d3 ("ext4: make ext4_abort() use __ext4_error()"), the following series of commands would trigger a panic:
1. mount /dev/sda -o ro,errors=panic test
2. mount /dev/sda -o remount,abort test
After commit 014c9caa29d3, remounting a file system using the test mount option "abort" will no longer trigger a panic. This commit will restore the behaviour immediately before commit 014c9caa29d3. (However, note that the Linux kernel's behavior has not been consistent; some previous kernel versions, including 5.4 and 4.19 similarly did not panic after using the mount option "abort".)
This also makes a change to long-standing behaviour; namely, the following series commands will now cause a panic, when previously it did not:
1. mount /dev/sda -o ro,errors=panic test
2. echo test > /sys/fs/ext4/sda/trigger_fs_error
However, this makes ext4's behaviour much more consistent, so this is a good thing.
--- fs/ext4/super.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
fs/ext4/super.c +4 -3
@@ -667,9 +667,6 @@ static void ext4_handle_error(struct supext4_commit_super (sb); } -if (sb_rdonly (sb) || continue_fs) -return ; -/* * We force ERRORS_RO behavior when system is rebooting. Otherwise we * could panic during 'reboot -f' as the underlying device got already
@@ -679,6 +676,10 @@ static void ext4_handle_error(struct suppanic ("EXT4-fs (device %s): panic forced after error\n" , sb->s_id); } + +if (sb_rdonly (sb) || continue_fs) +return ; +ext4_msg (sb,KERN_CRIT ,"Remounting filesystem read-only" );/* * Make sure updated value of ->s_mount_flags will be visible before
Greg Kroah-Hartman
maintainerPATCH 341/384 ext4: fix error code in ext4_commit_super
In reply to Greg Kroah-HartmanFrom: Fengnan Chang <[email protected]>
commit f88f1466e2a2e5ca17dfada436d3efa1b03a3972 upstream.
We should set the error code when ext4_commit_super check argument failed. Found in code review.
--- fs/ext4/super.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/ext4/super.c +4 -2
@@ -5559,8 +5559,10 @@ static int ext4_commit_super(struct supestruct buffer_head *sbh =EXT4_SB (sb)->s_sbh;int error =0 ; -if (!sbh ||block_device_ejected (sb)) -return error; +if (!sbh) +return -EINVAL ; +if (block_device_ejected (sb)) +return -ENODEV ;ext4_update_super (sb);
Greg Kroah-Hartman
maintainerPATCH 342/384 ext4: fix ext4_error_err save negative errno into superblock
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit 6810fad956df9e5467e8e8a5ac66fda0836c71fa upstream.
Fix As write_mmp_block() so that it returns -EIO instead of 1, so that the correct error gets saved into the superblock.
--- fs/ext4/mmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/mmp.c +1 -1
@@ -56,7 +56,7 @@ static int write_mmp_block(struct super_wait_on_buffer (bh);sb_end_write (sb);if (unlikely (!buffer_uptodate (bh))) -return 1 ; +return -EIO ;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 343/384 ext4: fix error return code in ext4_fc_perform_commit()
In reply to Greg Kroah-HartmanFrom: Xu Yihang <[email protected]>
commit e1262cd2e68a0870fb9fc95eb202d22e8f0074b7 upstream.
In case of if not ext4_fc_add_tlv branch, an error return code is missing.
--- fs/ext4/fast_commit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ext4/fast_commit.c +3 -1
@@ -1088,8 +1088,10 @@ static int ext4_fc_perform_commit(journa head.fc_tid =cpu_to_le32 ( sbi->s_journal->j_running_transaction->t_tid);if (!ext4_fc_add_tlv (sb,EXT4_FC_TAG_HEAD ,sizeof (head), - (u8 *)&head, &crc)) + (u8 *)&head, &crc)) { + ret = -ENOSPC ; goto out; + } }spin_lock (&sbi->s_fc_lock);
Greg Kroah-Hartman
maintainerPATCH 344/384 ext4: allow the dax flag to be set and cleared on inline directories
In reply to Greg Kroah-HartmanFrom: Theodore Ts'o <[email protected]>
commit 4811d9929cdae4238baf5b2522247bd2f9fa7b50 upstream.
This is needed to allow generic/607 to pass for file systems with the inline data_feature enabled, and it allows the use of file systems where the directories use inline_data, while the files are accessed via DAX.
--- fs/ext4/ialloc.c | 3 ++- fs/ext4/ioctl.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
fs/ext4/ialloc.c +2 -1
@@ -1292,7 +1292,8 @@ got: ei->i_extra_isize = sbi->s_want_extra_isize; ei->i_inline_off =0 ; -if (ext4_has_feature_inline_data (sb)) +if (ext4_has_feature_inline_data (sb) && + (!(ei->i_flags &EXT4_DAX_FL ) ||S_ISDIR (mode)))ext4_set_inode_state (inode,EXT4_STATE_MAY_INLINE_DATA ); ret = inode; err =dquot_alloc_inode (inode);
fs/ext4/ioctl.c +6 -0
@@ -315,6 +315,12 @@ static void ext4_dax_dontcache(struct in static bool dax_compatible(struct inode *inode, unsigned int oldflags, unsigned int flags) { + /* Allow the DAX flag to be changed on inline directories */ + if (S_ISDIR(inode->i_mode)) { + flags &= ~EXT4_INLINE_DATA_FL; + oldflags &= ~EXT4_INLINE_DATA_FL; + } + if (flags & EXT4_DAX_FL) { if ((oldflags & EXT4_DAX_MUT_EXCL) || ext4_test_inode_state(inode,
Greg Kroah-Hartman
maintainerPATCH 345/384 ext4: Fix occasional generic/418 failure
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 5899593f51e63dde2f07c67358bd65a641585abb upstream.
Eric has noticed that after pagecache read rework, generic/418 is occasionally failing for ext4 when blocksize < pagesize. In fact, the pagecache rework just made hard to hit race in ext4 more likely. The problem is that since ext4 conversion of direct IO writes to iomap framework (commit 378f32bab371), we update inode size after direct IO write only after invalidating page cache. Thus if buffered read sneaks at unfortunate moment like:
CPU1 - write at offset 1k CPU2 - read from offset 0
iomap_dio_rw(..., IOMAP_DIO_FORCE_WAIT);
ext4_readpage();ext4_handle_inode_extension()
the read will zero out tail of the page as it still sees smaller inode size and thus page cache becomes inconsistent with on-disk contents with all the consequences.
Fix the problem by moving inode size update into end_io handler which gets called before the page cache is invalidated.
--- fs/ext4/file.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
fs/ext4/file.c +21 -4
@@ -371,15 +371,32 @@ truncate:static int ext4_dio_write_end_io (struct kiocb *iocb,ssize_t size,int error,unsigned int flags) { -loff_t offset = iocb->ki_pos; +loff_t pos = iocb->ki_pos;struct inode *inode =file_inode (iocb->ki_filp);if (error)return error; -if (size && flags &IOMAP_DIO_UNWRITTEN ) -return ext4_convert_unwritten_extents (NULL , inode, - offset, size); +if (size && flags &IOMAP_DIO_UNWRITTEN ) { + error =ext4_convert_unwritten_extents (NULL , inode, pos, size); +if (error <0 ) +return error; + } +/* +* If we are extending the file, we have to update i_size here before +* page cache gets invalidated in iomap_dio_rw(). Otherwise racing +* buffered reads could zero out too much from page cache pages. Update +* of on-disk size will happen later in ext4_dio_write_iter() where +* we have enough information to also perform orphan list handling etc. +* Note that we perform all extending writes synchronously under +* i_rwsem held exclusively so i_size update is safe here in that case. +* If the write was not extending, we cannot see pos > i_size here +* because operations reducing i_size like truncate wait for all +* outstanding DIO before updating i_size. +*/ + pos += size; +if (pos >i_size_read (inode)) +i_size_write (inode, pos);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 346/384 media: dvbdev: Fix memory leak in dvb_media_device_free()
In reply to Greg Kroah-HartmanFrom: Peilin Ye <[email protected]>
commit bf9a40ae8d722f281a2721779595d6df1c33a0bf upstream.
dvb_media_device_free() is leaking memory. Free dvbdev->adapter->conn before setting it to NULL, as documented in include/media/media-device.h:
"The media_entity instance itself must be freed explicitly by the driver if required."
--- drivers/media/dvb-core/dvbdev.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/dvb-core/dvbdev.c +1 -0
@@ -241,6 +241,7 @@ static void dvb_media_device_free(structif (dvbdev->adapter->conn) {media_device_unregister_entity (dvbdev->adapter->conn); +kfree (dvbdev->adapter->conn); dvbdev->adapter->conn =NULL ;kfree (dvbdev->adapter->conn_pads); dvbdev->adapter->conn_pads =NULL ;
Greg Kroah-Hartman
maintainerPATCH 347/384 media: dvb-usb: Fix use-after-free access
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit c49206786ee252f28b7d4d155d1fff96f145a05d upstream.
dvb_usb_device_init() copies the properties to the own data, so that the callers can release the original properties later (as done in the commit 299c7007e936 ("media: dw2102: Fix memleak on sequence of probes")). However, it also stores dev->desc pointer that is a reference to the original properties data. Since dev->desc is referred later, it may result in use-after-free, in the worst case, leading to a kernel Oops as reported.
This patch addresses the problem by allocating and copying the properties at first, then get the desc from the copied properties.
--- drivers/media/usb/dvb-usb/dvb-usb-init.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
drivers/media/usb/dvb-usb/dvb-usb-init.c +13 -10
@@ -267,27 +267,30 @@ int dvb_usb_device_init(struct usb_interif (du !=NULL ) *du =NULL ; -if ((desc =dvb_usb_find_device (udev, props, &cold)) ==NULL ) { + d =kzalloc (sizeof (*d),GFP_KERNEL ); +if (!d) { +err ("no memory for 'struct dvb_usb_device'" ); +return -ENOMEM ; + } + +memcpy (&d->props, props,sizeof (struct dvb_usb_device_properties )); + + desc =dvb_usb_find_device (udev, &d->props, &cold); +if (!desc) {deb_err ("something went very wrong, device was not found in current device list - let's see what comes next.\n" ); -return -ENODEV ; + ret = -ENODEV ; + goto error; }if (cold) {info ("found a '%s' in cold state, will try to load a firmware" , desc->name); ret =dvb_usb_download_firmware (udev, props);if (!props->no_reconnect || ret !=0 ) -return ret; + goto error; }info ("found a '%s' in warm state." , desc->name); - d =kzalloc (sizeof (struct dvb_usb_device ),GFP_KERNEL ); -if (d ==NULL ) { -err ("no memory for 'struct dvb_usb_device'" ); -return -ENOMEM ; - } - d->udev = udev; -memcpy (&d->props, props,sizeof (struct dvb_usb_device_properties )); d->desc = desc; d->owner = owner;
Greg Kroah-Hartman
maintainerPATCH 348/384 media: dvb-usb: Fix memory leak at error in dvb_usb_device_init()
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 13a79f14ab285120bc4977e00a7c731e8143f548 upstream.
dvb_usb_device_init() allocates a dvb_usb_device object, but it doesn't release the object by itself even at errors. The object is released in the callee side (dvb_usb_init()) in some error cases via dvb_usb_exit() call, but it also missed the object free in other error paths. And, the caller (it's only dvb_usb_device_init()) doesn't seem caring the resource management as well, hence those memories are leaked.
This patch assures releasing the memory at the error path in dvb_usb_device_init(). Now dvb_usb_init() frees the resources it allocated but leaves the passed dvb_usb_device object intact. In turn, the dvb_usb_device object is released in dvb_usb_device_init() instead.
We could use dvb_usb_exit() function for releasing everything in the callee (as it was used for some error cases in the original code), but releasing the passed object in the callee is non-intuitive and error-prone. So I took this approach (which is more standard in Linus kernel code) although it ended with a bit more open codes.
Along with the change, the patch makes sure that USB intfdata is reset and don't return the bogus pointer to the caller of dvb_usb_device_init() at the error path, too.
--- drivers/media/usb/dvb-usb/dvb-usb-init.c | 47 ++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 16 deletions(-)
drivers/media/usb/dvb-usb/dvb-usb-init.c +31 -16
@@ -170,22 +170,20 @@ static int dvb_usb_init(struct dvb_usb_dif (d->props.priv_init !=NULL ) { ret = d->props.priv_init (d); -if (ret !=0 ) { -kfree (d->priv); - d->priv =NULL ; -return ret; - } +if (ret !=0 ) + goto err_priv_init; } }/* check the capabilities and set appropriate variables */ dvb_usb_device_power_ctrl (d,1 ); -if ((ret =dvb_usb_i2c_init (d)) || - (ret =dvb_usb_adapter_init (d, adapter_nums))) { -dvb_usb_exit (d); -return ret; - } + ret =dvb_usb_i2c_init (d); +if (ret) + goto err_i2c_init; + ret =dvb_usb_adapter_init (d, adapter_nums); +if (ret) + goto err_adapter_init;if ((ret =dvb_usb_remote_init (d)))err ("could not initialize remote control." );
@@ -193,6 +191,17 @@ static int dvb_usb_init(struct dvb_usb_ddvb_usb_device_power_ctrl (d,0 );return 0 ; + +err_adapter_init: +dvb_usb_adapter_exit (d); +err_i2c_init: +dvb_usb_i2c_exit (d); +if (d->priv && d->props.priv_destroy) + d->props.priv_destroy (d); +err_priv_init: +kfree (d->priv); + d->priv =NULL ; +return ret; }/* determine the name and the state of the just found USB device */
@@ -296,15 +305,21 @@ int dvb_usb_device_init(struct usb_interusb_set_intfdata (intf, d); -if (du !=NULL ) + ret =dvb_usb_init (d, adapter_nums); +if (ret) { +info ("%s error while loading driver (%d)" , desc->name, ret); + goto error; + } + +if (du) *du = d; - ret =dvb_usb_init (d, adapter_nums); +info ("%s successfully initialized and connected." , desc->name); +return 0 ; -if (ret ==0 ) -info ("%s successfully initialized and connected." , desc->name); -else -info ("%s error while loading driver (%d)" , desc->name, ret); + error: +usb_set_intfdata (intf,NULL ); +kfree (d);return ret; }EXPORT_SYMBOL (dvb_usb_device_init);
Greg Kroah-Hartman
maintainerPATCH 349/384 media: staging/intel-ipu3: Fix memory leak in imu_fmt
In reply to Greg Kroah-HartmanFrom: Ricardo Ribalda <[email protected]>
commit 3630901933afba1d16c462b04d569b7576339223 upstream.
We are losing the reference to an allocated memory if try. Change the order of the check to avoid that.
--- drivers/staging/media/ipu3/ipu3-v4l2.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/staging/media/ipu3/ipu3-v4l2.c +7 -4
@@ -693,6 +693,13 @@ static int imgu_fmt(struct imgu_device *if (inode ==IMGU_NODE_STAT_3A || inode ==IMGU_NODE_PARAMS )continue ; +/* CSS expects some format on OUT queue */ +if (i !=IPU3_CSS_QUEUE_OUT && + !imgu_pipe->nodes[inode].enabled) { + fmts[i] =NULL ; +continue ; + } +if (try) { fmts[i] = kmemdup(&imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp, sizeof(struct v4l2_pix_format_mplane),
@@ -705,10 +712,6 @@ static int imgu_fmt(struct imgu_device * fmts[i] = &imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp; } -/* CSS expects some format on OUT queue */ -if (i !=IPU3_CSS_QUEUE_OUT && - !imgu_pipe->nodes[inode].enabled) - fmts[i] =NULL ; }if (!try) {
Greg Kroah-Hartman
maintainerPATCH 350/384 media: staging/intel-ipu3: Fix set_fmt error handling
In reply to Greg Kroah-HartmanFrom: Ricardo Ribalda <[email protected]>
commit ad91849996f9dd79741a961fd03585a683b08356 upstream.
If there in an error during a set_fmt, do not overwrite the previous sizes with the invalid config.
Without this patch, v4l2-compliance ends up allocating 4GiB of RAM and causing the following OOPs
[ 38.662975] ipu3-imgu 0000:00:05.0: swiotlb buffer is full (sz: 4096 bytes) [ 38.662980] DMA: Out of SW-IOMMU space for 4096 bytes at device 0000:00:05.0 [ 38.663010] general protection fault: 0000 [#1] PREEMPT SMP
--- drivers/staging/media/ipu3/ipu3-v4l2.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/staging/media/ipu3/ipu3-v4l2.c +5 -0
@@ -669,6 +669,7 @@ static int imgu_fmt(struct imgu_device *struct imgu_css_pipe *css_pipe = &imgu->css.pipes[pipe];struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];struct imgu_v4l2_subdev *imgu_sd = &imgu_pipe->imgu_sd; +struct v4l2_pix_format_mplane fmt_backup;dev_dbg (dev,"set fmt node [%u][%u](try = %u)" , pipe, node, try);
@@ -737,6 +738,7 @@ static int imgu_fmt(struct imgu_device * ret = -EINVAL ; goto out; } + fmt_backup = *fmts[css_q]; *fmts[css_q] = f->fmt.pix_mp;if (try)
@@ -744,6 +746,9 @@ static int imgu_fmt(struct imgu_device *else ret =imgu_css_fmt_set (&imgu->css, fmts, rects, pipe); +if (try || ret <0 ) + *fmts[css_q] = fmt_backup; +/* ret is the binary number in the firmware blob */ if (ret <0 ) goto out;
Greg Kroah-Hartman
maintainerPATCH 351/384 media: staging/intel-ipu3: Fix race condition during set_fmt
In reply to Greg Kroah-HartmanFrom: Ricardo Ribalda <[email protected]>
commit dccfe2548746ca9cca3a20401ece4cf255d1f171 upstream.
Do not modify imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp, until the format has been correctly validated.
Otherwise, even if we use a backup variable, there is a period of time where imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp might have an invalid value that can be used by other functions.
--- drivers/staging/media/ipu3/ipu3-v4l2.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)
drivers/staging/media/ipu3/ipu3-v4l2.c +14 -16
@@ -669,7 +669,6 @@ static int imgu_fmt(struct imgu_device *struct imgu_css_pipe *css_pipe = &imgu->css.pipes[pipe];struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];struct imgu_v4l2_subdev *imgu_sd = &imgu_pipe->imgu_sd; -struct v4l2_pix_format_mplane fmt_backup;dev_dbg (dev,"set fmt node [%u][%u](try = %u)" , pipe, node, try);
@@ -687,6 +686,7 @@ static int imgu_fmt(struct imgu_device *dev_dbg (dev,"IPU3 pipe %u pipe_id = %u" , pipe, css_pipe->pipe_id); + css_q =imgu_node_to_queue (node);for (i =0 ; i <IPU3_CSS_QUEUES ; i++) {unsigned int inode =imgu_map_node (imgu, i);
@@ -701,6 +701,11 @@ static int imgu_fmt(struct imgu_device *continue ; } +if (i == css_q) { + fmts[i] = &f->fmt.pix_mp; +continue ; + } +if (try) { fmts[i] = kmemdup(&imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp, sizeof(struct v4l2_pix_format_mplane),
@@ -729,39 +734,32 @@ static int imgu_fmt(struct imgu_device * rects[IPU3_CSS_RECT_GDC ]->height = pad_fmt.height; } -/* -* imgu doesn't set the node to the value given by user -* before we return success from this function, so set it here. -*/ - css_q =imgu_node_to_queue (node);if (!fmts[css_q]) { ret = -EINVAL ; goto out; } - fmt_backup = *fmts[css_q]; - *fmts[css_q] = f->fmt.pix_mp;if (try) ret =imgu_css_fmt_try (&imgu->css, fmts, rects, pipe);else ret =imgu_css_fmt_set (&imgu->css, fmts, rects, pipe); -if (try || ret <0 ) - *fmts[css_q] = fmt_backup; -/* ret is the binary number in the firmware blob */ if (ret <0 ) goto out; -if (try) - f->fmt.pix_mp = *fmts[css_q]; -else - f->fmt = imgu_pipe->nodes[node].vdev_fmt.fmt; +/* +* imgu doesn't set the node to the value given by user +* before we return success from this function, so set it here. +*/ +if (!try) + imgu_pipe->nodes[node].vdev_fmt.fmt.pix_mp = f->fmt.pix_mp; out:if (try) {for (i =0 ; i <IPU3_CSS_QUEUES ; i++) -kfree (fmts[i]); +if (i != css_q) +kfree (fmts[i]); }return ret;
Greg Kroah-Hartman
maintainerPATCH 352/384 media: v4l2-ctrls: fix reference to freed memory
In reply to Greg Kroah-HartmanFrom: Hans Verkuil <[email protected]>
commit ac34b79da14d67a9b494f6125186becbd067e225 upstream.
When controls are used together with the Request API, then for each request a v4l2_ctrl_handler struct is allocated. This contains the controls that can be set in a request. If a control is *not* set in the request, then the value used in the most recent previous request must be used, or the current value if it is not found in any outstanding requests.
The framework tried to find such a previous request and it would set the 'req' pointer in struct v4l2_ctrl_ref to the v4l2_ctrl_ref of the control in such a previous request. So far, so good. However, when that previous request was applied to the hardware, returned to userspace, and then userspace would re-init or free that request, any 'ref' pointer in still-queued requests would suddenly point to freed memory.
This was not noticed before since the drivers that use this expected that each request would always have the controls set, so there was never any need to find a control in older requests. This requirement was relaxed, and now this bug surfaced.
It was also made worse by changeset2fae4d6aabc8 ("media: v4l2-ctrls: v4l2_ctrl_request_complete() should always set ref->req") which increased the chance of this happening.
The use of the 'req' pointer in v4l2_ctrl_ref was very fragile, so drop this entirely. Instead add a valid_p_req bool to indicate that p_req contains a valid value for this control. And if it is false, then just use the current value of the control.
Note that VIDIOC_G_EXT_CTRLS will always return -EACCES when attempting to get a control from a request until the request is completed. And in that case, all controls in the request will have the control value set (i.e. valid_p_req is true). This means that the whole 'find the most recent previous request containing a control' idea is pointless, and the code can be simplified considerably.
The v4l2_g_ext_ctrls_common() function was refactored a bit to make it more understandable. It also avoids updating volatile controls in a completed request since that was already done when the request was completed.
--- drivers/media/v4l2-core/v4l2-ctrls.c | 137 ++++++++++++++++------------------- include/media/v4l2-ctrls.h | 12 +-- 2 files changed, 70 insertions(+), 79 deletions(-)
drivers/media/v4l2-core/v4l2-ctrls.c +63 -74
@@ -2397,7 +2397,16 @@ static void new_to_req(struct v4l2_ctrl_if (!ref)return ;ptr_to_ptr (ref->ctrl, ref->ctrl->p_new, ref->p_req); - ref->req = ref; + ref->valid_p_req = true; +} + +/* Copy the current value to the request value */ +static void cur_to_req (struct v4l2_ctrl_ref *ref) +{ +if (!ref) +return ; +ptr_to_ptr (ref->ctrl, ref->ctrl->p_cur, ref->p_req); + ref->valid_p_req = true; }/* Copy the request value to the new value */
@@ -2405,8 +2414,8 @@ static void req_to_new(struct v4l2_ctrl_ {if (!ref)return ; -if (ref->req) -ptr_to_ptr (ref->ctrl, ref->req->p_req, ref->ctrl->p_new); +if (ref->valid_p_req) +ptr_to_ptr (ref->ctrl, ref->p_req, ref->ctrl->p_new);else ptr_to_ptr (ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new); }
@@ -3573,39 +3582,8 @@ static void v4l2_ctrl_request_queue(strustruct v4l2_ctrl_handler *hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);struct v4l2_ctrl_handler *main_hdl = obj->priv; -struct v4l2_ctrl_handler *prev_hdl =NULL ; -struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev =NULL ;mutex_lock (main_hdl->lock); -if (list_empty (&main_hdl->requests_queued)) - goto queue; - - prev_hdl =list_last_entry (&main_hdl->requests_queued, - struct v4l2_ctrl_handler, requests_queued); -/* -* Note: prev_hdl and hdl must contain the same list of control -* references, so if any differences are detected then that is a -* driver bug and the WARN_ON is triggered. -*/ -mutex_lock (prev_hdl->lock); - ref_ctrl_prev =list_first_entry (&prev_hdl->ctrl_refs, - struct v4l2_ctrl_ref, node); -list_for_each_entry (ref_ctrl, &hdl->ctrl_refs, node) { -if (ref_ctrl->req) -continue ; -while (ref_ctrl_prev->ctrl->id < ref_ctrl->ctrl->id) { -/* Should never happen, but just in case... */ -if (list_is_last (&ref_ctrl_prev->node, - &prev_hdl->ctrl_refs)) -break ; - ref_ctrl_prev =list_next_entry (ref_ctrl_prev, node); - } -if (WARN_ON (ref_ctrl_prev->ctrl->id != ref_ctrl->ctrl->id)) -break ; - ref_ctrl->req = ref_ctrl_prev->req; - } -mutex_unlock (prev_hdl->lock); -queue:list_add_tail (&hdl->requests_queued, &main_hdl->requests_queued); hdl->request_is_queued = true;mutex_unlock (main_hdl->lock);
@@ -3662,7 +3640,7 @@ v4l2_ctrl_request_hdl_ctrl_find(struct v {struct v4l2_ctrl_ref *ref =find_ref_lock (hdl, id); -return (ref && ref->req == ref) ? ref->ctrl :NULL ; +return (ref && ref->valid_p_req) ? ref->ctrl :NULL ; }EXPORT_SYMBOL_GPL (v4l2_ctrl_request_hdl_ctrl_find);
@@ -3848,7 +3826,13 @@ static int class_check(struct v4l2_ctrl_return find_ref_lock (hdl, which |1 ) ?0 : -EINVAL ; } -/* Get extended controls. Allocates the helpers array if needed. */ +/* +* Get extended controls. Allocates the helpers array if needed. +* +* Note that v4l2_g_ext_ctrls_common() with 'which' set to +* V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was +* completed, and in that case valid_p_req is true for all controls. +*/ static int v4l2_g_ext_ctrls_common (struct v4l2_ctrl_handler *hdl,struct v4l2_ext_controls *cs,struct video_device *vdev)
@@ -3857,9 +3841,10 @@ static int v4l2_g_ext_ctrls_common(strucstruct v4l2_ctrl_helper *helpers = helper;int ret;int i, j; -bool def_value; +bool is_default, is_request; - def_value = (cs->which ==V4L2_CTRL_WHICH_DEF_VAL ); + is_default = (cs->which ==V4L2_CTRL_WHICH_DEF_VAL ); + is_request = (cs->which ==V4L2_CTRL_WHICH_REQUEST_VAL ); cs->error_idx = cs->count; cs->which =V4L2_CTRL_ID2WHICH (cs->which);
@@ -3885,11 +3870,9 @@ static int v4l2_g_ext_ctrls_common(struc ret = -EACCES ;for (i =0 ; !ret && i < cs->count; i++) { -int (*ctrl_to_user)(struct v4l2_ext_control *c, -struct v4l2_ctrl *ctrl);struct v4l2_ctrl *master; - - ctrl_to_user = def_value ? def_to_user : cur_to_user; +bool is_volatile = false; +u32 idx = i;if (helpers[i].mref ==NULL )continue ;
@@ -3899,31 +3882,48 @@ static int v4l2_g_ext_ctrls_common(strucv4l2_ctrl_lock (master); -/* g_volatile_ctrl will update the new control values */ -if (!def_value && +/* +* g_volatile_ctrl will update the new control values. +* This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and +* V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests +* it is v4l2_ctrl_request_complete() that copies the +* volatile controls at the time of request completion +* to the request, so you don't want to do that again. +*/ +if (!is_default && !is_request && ((master->flags &V4L2_CTRL_FLAG_VOLATILE ) || (master->has_volatiles && !is_cur_manual (master)))) {for (j =0 ; j < master->ncontrols; j++)cur_to_new (master->cluster[j]); ret =call_op (master, g_volatile_ctrl); - ctrl_to_user = new_to_user; + is_volatile = true; } -/* If OK, then copy the current (for non-volatile controls) -or the new (for volatile controls) control values to the -caller */ -if (!ret) { -u32 idx = i; -do { -if (helpers[idx].ref->req) - ret =req_to_user (cs->controls + idx, - helpers[idx].ref->req); -else - ret =ctrl_to_user (cs->controls + idx, - helpers[idx].ref->ctrl); - idx = helpers[idx].next; - }while (!ret && idx); +if (ret) { +v4l2_ctrl_unlock (master); +break ; } + +/* +* Copy the default value (if is_default is true), the +* request value (if is_request is true and p_req is valid), +* the new volatile value (if is_volatile is true) or the +* current value. +*/ +do { +struct v4l2_ctrl_ref *ref = helpers[idx].ref; + +if (is_default) + ret =def_to_user (cs->controls + idx, ref->ctrl); +else if (is_request && ref->valid_p_req) + ret =req_to_user (cs->controls + idx, ref); +else if (is_volatile) + ret =new_to_user (cs->controls + idx, ref->ctrl); +else + ret =cur_to_user (cs->controls + idx, ref->ctrl); + idx = helpers[idx].next; + }while (!ret && idx); +v4l2_ctrl_unlock (master); }
@@ -4566,8 +4566,6 @@ void v4l2_ctrl_request_complete(struct munsigned int i;if (ctrl->flags &V4L2_CTRL_FLAG_VOLATILE ) { - ref->req = ref; -v4l2_ctrl_lock (master);/* g_volatile_ctrl will update the current control values */ for (i =0 ; i < master->ncontrols; i++)
@@ -4577,21 +4575,12 @@ void v4l2_ctrl_request_complete(struct mv4l2_ctrl_unlock (master);continue ; } -if (ref->req == ref) +if (ref->valid_p_req)continue ; +/* Copy the current control value into the request */ v4l2_ctrl_lock (ctrl); -if (ref->req) { -ptr_to_ptr (ctrl, ref->req->p_req, ref->p_req); - }else { -ptr_to_ptr (ctrl, ctrl->p_cur, ref->p_req); -/* -* Set ref->req to ensure that when userspace wants to -* obtain the controls of this request it will take -* this value and not the current value of the control. -*/ - ref->req = ref; - } +cur_to_req (ref);v4l2_ctrl_unlock (ctrl); }
@@ -4655,7 +4644,7 @@ int v4l2_ctrl_request_setup(struct mediastruct v4l2_ctrl_ref *r =find_ref (hdl, master->cluster[i]->id); -if (r->req && r == r->req) { +if (r->valid_p_req) { have_new_data = true;break ; }
include/media/v4l2-ctrls.h +7 -5
@@ -301,12 +301,14 @@ struct v4l2_ctrl {* the control has been applied. This prevents applying controls * from a cluster with multiple controls twice (when the first * control of a cluster is applied, they all are). -* @req: If set, this refers to another request that sets this control. +* @valid_p_req: If set, then p_req contains the control value for the request. * @p_req: If the control handler containing this control reference * is bound to a media request, then this points to the -* value of the control that should be applied when the request +* value of the control that must be applied when the request * is executed, or to the value of the control at the time -* that the request was completed. +* that the request was completed. If @valid_p_req is false, +* then this control was never set for this request and the +* control will not be updated when this request is applied. * * Each control handler has a list of these refs. The list_head is used to * keep a sorted-by-control-ID list of all controls, while the next pointer
@@ -319,7 +321,7 @@ struct v4l2_ctrl_ref {struct v4l2_ctrl_helper *helper;bool from_other_dev;bool req_done; -struct v4l2_ctrl_ref *req; +bool valid_p_req;union v4l2_ctrl_ptr p_req; };
@@ -346,7 +348,7 @@ struct v4l2_ctrl_ref {* @error: The error code of the first failed control addition. * @request_is_queued: True if the request was queued. * @requests: List to keep track of open control handler request objects. -* For the parent control handler (@req_obj.req == NULL) this +* For the parent control handler (@req_obj.ops == NULL) this * is the list header. When the parent control handler is * removed, it has to unbind and put all these requests since * they refer to the parent.
Greg Kroah-Hartman
maintainerPATCH 353/384 media: coda: fix macroblocks count control usage
In reply to Greg Kroah-HartmanFrom: Marco Felsch <[email protected]>
commit 0b276e470a4d43e1365d3eb53c608a3d208cabd4 upstream.
Commit b2d3bef1aa78 ("media: coda: Add a V4L2 user for control error macroblocks count") add the control for the decoder devices. But during streamon() this ioctl gets called for all (encoder and decoder) devices and on encoder devices this causes a null pointer exception.
Fix this by setting the control only if it is really accessible.
--- drivers/media/platform/coda/coda-common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/platform/coda/coda-common.c +3 -1
@@ -2062,7 +2062,9 @@ static int coda_start_streaming(struct vif (q_data_dst->fourcc ==V4L2_PIX_FMT_JPEG ) ctx->params.gop_size =1 ; ctx->gopcounter = ctx->params.gop_size -1 ; -v4l2_ctrl_s_ctrl (ctx->mb_err_cnt_ctrl,0 ); +/* Only decoders have this control */ +if (ctx->mb_err_cnt_ctrl) +v4l2_ctrl_s_ctrl (ctx->mb_err_cnt_ctrl,0 ); ret = ctx->ops->start_streaming (ctx);if (ctx->inst_type ==CODA_INST_DECODER ) {
Greg Kroah-Hartman
maintainerPATCH 354/384 media: venus: pm_helpers: Set opp clock name for v1
In reply to Greg Kroah-HartmanFrom: Stanimir Varbanov <[email protected]>
commit 3215887167af7db9af9fa23d61321ebfbd6ed6d3 upstream.
The rate of the core clock is set through devm_pm_opp_set_rate and to avoid errors from it we have to set the name of the clock via dev_pm_opp_set_clkname.
--- drivers/media/platform/qcom/venus/pm_helpers.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
drivers/media/platform/qcom/venus/pm_helpers.c +18 -1
@@ -279,7 +279,22 @@ set_freq:static int core_get_v1 (struct venus_core *core) { -return core_clks_get (core); +int ret; + + ret =core_clks_get (core); +if (ret) +return ret; + + core->opp_table =dev_pm_opp_set_clkname (core->dev,"core" ); +if (IS_ERR (core->opp_table)) +return PTR_ERR (core->opp_table); + +return 0 ; +} + +static void core_put_v1 (struct venus_core *core) +{ +dev_pm_opp_put_clkname (core->opp_table); }static int core_power_v1 (struct venus_core *core,int on)
@@ -296,6 +311,7 @@ static int core_power_v1(struct venus_costatic const struct venus_pm_ops pm_ops_v1 = { .core_get = core_get_v1, + .core_put = core_put_v1, .core_power = core_power_v1, .load_scale = load_scale_v1, };
@@ -368,6 +384,7 @@ static int venc_power_v3(struct device *static const struct venus_pm_ops pm_ops_v3 = { .core_get = core_get_v1, + .core_put = core_put_v1, .core_power = core_power_v1, .vdec_get = vdec_get_v3, .vdec_power = vdec_power_v3,
Greg Kroah-Hartman
maintainerPATCH 355/384 media: venus: venc_ctrls: Change default header mode
In reply to Greg Kroah-HartmanFrom: Stanimir Varbanov <[email protected]>
commit 39a6b9185d305d236bff625509ee63801b50301b upstream.
It is observed that on Venus v1 the default header-mode is producing a bitstream which is not playble. Change the default header-mode to joined with 1st frame.
--- drivers/media/platform/qcom/venus/venc_ctrls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/qcom/venus/venc_ctrls.c +1 -1
@@ -359,7 +359,7 @@ int venc_ctrl_init(struct venus_inst *inV4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME , ~((1 <<V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE ) | (1 <<V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME )), - V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE); + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
Greg Kroah-Hartman
maintainerPATCH 356/384 media: venus: hfi_cmds: Support plane-actual-info property from v1
In reply to Greg Kroah-HartmanFrom: Stanimir Varbanov <[email protected]>
commit 15447d18b1b877d9c6f979bd00088e470a4e0e9f upstream.
The property is supported from v1 and upwards. So move it to set_property_1x.
--- drivers/media/platform/qcom/venus/hfi_cmds.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
drivers/media/platform/qcom/venus/hfi_cmds.c +12 -12
@@ -1039,6 +1039,18 @@ static int pkt_session_set_property_1x(s pkt->shdr.hdr.size +=sizeof (u32) +sizeof (*hierp);break ; } +case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO : { +struct hfi_uncompressed_plane_actual_info *in = pdata; +struct hfi_uncompressed_plane_actual_info *info = prop_data; + + info->buffer_type = in->buffer_type; + info->num_planes = in->num_planes; + info->plane_format[0 ] = in->plane_format[0 ]; +if (in->num_planes >1 ) + info->plane_format[1 ] = in->plane_format[1 ]; + pkt->shdr.hdr.size +=sizeof (u32) +sizeof (*info); +break ; + }/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */ case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS :
@@ -1205,18 +1217,6 @@ pkt_session_set_property_4xx(struct hfi_ pkt->shdr.hdr.size +=sizeof (u32) +sizeof (*cu);break ; } -case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO : { -struct hfi_uncompressed_plane_actual_info *in = pdata; -struct hfi_uncompressed_plane_actual_info *info = prop_data; - - info->buffer_type = in->buffer_type; - info->num_planes = in->num_planes; - info->plane_format[0 ] = in->plane_format[0 ]; -if (in->num_planes >1 ) - info->plane_format[1 ] = in->plane_format[1 ]; - pkt->shdr.hdr.size +=sizeof (u32) +sizeof (*info); -break ; - }case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE :case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER :case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE :
Greg Kroah-Hartman
maintainerPATCH 357/384 media: venus: hfi_parser: Dont initialize parser on v1
In reply to Greg Kroah-HartmanFrom: Stanimir Varbanov <[email protected]>
commit 834124c596e2dddbbdba06620835710ccca32fd0 upstream.
The Venus v1 behaves differently comparing with the other Venus version in respect to capability parsing and when they are send to the driver. So we don't need to initialize hfi parser for multiple invocations like what we do for > v1 Venus versions.
--- drivers/media/platform/qcom/venus/hfi_parser.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/media/platform/qcom/venus/hfi_parser.c +4 -2
@@ -277,8 +277,10 @@ u32 hfi_parser(struct venus_core *core,parser_init (inst, &codecs, &domain); - core->codecs_count =0 ; -memset (core->caps,0 ,sizeof (core->caps)); +if (core->res->hfi_version >HFI_VERSION_1XX ) { + core->codecs_count =0 ; +memset (core->caps,0 ,sizeof (core->caps)); + }while (words_count) { data = word +1 ;
Greg Kroah-Hartman
maintainerPATCH 358/384 media: venus: hfi_parser: Check for instance after hfi platform get
In reply to Greg Kroah-HartmanFrom: Stanimir Varbanov <[email protected]>
commit 9b5d8fd580caa898c6e1b8605c774f2517f786ab upstream.
The inst function argument is != NULL only for Venus v1 and we did not migrate v1 to a hfi_platform abstraction yet. So check for instance != NULL only after hfi_platform_get returns no error.
--- drivers/media/platform/qcom/venus/hfi_parser.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/media/platform/qcom/venus/hfi_parser.c +3 -3
@@ -235,13 +235,13 @@ static int hfi_platform_parser(struct veu32 enc_codecs, dec_codecs, count =0 ;unsigned int entries; -if (inst) -return 0 ; - plat =hfi_platform_get (core->res->hfi_version);if (!plat)return -EINVAL ; +if (inst) +return 0 ; +if (plat->codecs) plat->codecs (&enc_codecs, &dec_codecs, &count);
Greg Kroah-Hartman
maintainerPATCH 359/384 io_uring: remove extra sqpoll submission halting
In reply to Greg Kroah-HartmanFrom: Pavel Begunkov <[email protected]>
commit 3b763ba1c77da5806e4fdc5684285814fe970c98 upstream.
SQPOLL task won't submit requests for a context that is currently dying, so no need to remove ctx from sqd_list prior the main loop of io_ring_exit_work(). Kill it, will be removed by io_sq_thread_finish() and only brings confusion and lockups.
--- fs/io_uring.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
fs/io_uring.c +4 -8
@@ -6710,6 +6710,10 @@ static int __io_sq_thread(struct io_ringif (!list_empty (&ctx->iopoll_list))io_do_iopoll (ctx, &nr_events,0 ); +/* +* Don't submit if refs are dying, good for io_uring_register(), +* but also it is relied upon by io_ring_exit_work() +*/ if (to_submit &&likely (!percpu_ref_is_dying (&ctx->refs)) && !(ctx->flags &IORING_SETUP_R_DISABLED )) ret =io_submit_sqes (ctx, to_submit);
@@ -8576,14 +8580,6 @@ static void io_ring_exit_work(struct worstruct io_tctx_node *node;int ret; -/* prevent SQPOLL from submitting new requests */ -if (ctx->sq_data) { -io_sq_thread_park (ctx->sq_data); -list_del_init (&ctx->sqd_list); -io_sqd_update_thread_idle (ctx->sq_data); -io_sq_thread_unpark (ctx->sq_data); - } -/* * If we're doing polled IO and end up having requests being * submitted async (out-of-line), then completions can come in while
Greg Kroah-Hartman
maintainerPATCH 360/384 io_uring: fix shared sqpoll cancellation hangs
In reply to Greg Kroah-HartmanFrom: Pavel Begunkov <[email protected]>
commit 734551df6f9bedfbefcd113ede665945e9de0b99 upstream.
[ 736.982891] INFO: task iou-sqp-4294:4295 blocked for more than 122 seconds. [ 736.982897] Call Trace: [ 736.982901] schedule+0x68/0xe0 [ 736.982903] io_uring_cancel_sqpoll+0xdb/0x110 [ 736.982908] io_sqpoll_cancel_cb+0x24/0x30 [ 736.982911] io_run_task_work_head+0x28/0x50 [ 736.982913] io_sq_thread+0x4e3/0x720
We call io_uring_cancel_sqpoll() one by one for each ctx either in sq_thread() itself or via task works, and it's intended to cancel all requests of a specified context. However the function uses per-task counters to track the number of inflight requests, so it counts more requests than available via currect io_uring ctx and goes to sleep for them to appear (e.g. from IRQ), that will never happen.
Cancel a bit more than before, i.e. all ctxs that share sqpoll and continue to use shared counters. Don't forget that we should not remove ctx from the list before running that task_work sqpoll-cancel, otherwise the function wouldn't be able to find the context and will hang.
--- fs/io_uring.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
fs/io_uring.c +14 -13
@@ -1008,7 +1008,7 @@ static void io_uring_del_task_file(unsigstatic void io_uring_try_cancel_requests (struct io_ring_ctx *ctx,struct task_struct *task,struct files_struct *files); -static void io_uring_cancel_sqpoll (struct io_ring_ctx *ctx); +static void io_uring_cancel_sqpoll (struct io_sq_data *sqd);static void destroy_fixed_rsrc_ref_node (struct fixed_rsrc_ref_node *ref_node);static struct fixed_rsrc_ref_node *alloc_fixed_rsrc_ref_node (struct io_ring_ctx *ctx);
@@ -6836,15 +6836,14 @@ static int io_sq_thread(void *data) timeout = jiffies + sqd->sq_thread_idle; } -list_for_each_entry (ctx, &sqd->ctx_list, sqd_list) -io_uring_cancel_sqpoll (ctx); +io_uring_cancel_sqpoll (sqd); sqd->thread =NULL ;list_for_each_entry (ctx, &sqd->ctx_list, sqd_list)io_ring_set_wakeup_flag (ctx); -mutex_unlock (&sqd->lock); -io_run_task_work ();io_run_task_work_head (&sqd->park_task_work); +mutex_unlock (&sqd->lock); +complete (&sqd->exited);do_exit (0 ); }
@@ -8931,11 +8930,11 @@ static s64 tctx_inflight(struct io_uringstatic void io_sqpoll_cancel_cb (struct callback_head *cb) { struct io_tctx_exit *work = container_of(cb, struct io_tctx_exit, task_work); -struct io_ring_ctx *ctx = work->ctx; -struct io_sq_data *sqd = ctx->sq_data; +struct io_sq_data *sqd = work->ctx->sq_data;if (sqd->thread) -io_uring_cancel_sqpoll (ctx); +io_uring_cancel_sqpoll (sqd); +list_del_init (&work->ctx->sqd_list);complete (&work->completion); }
@@ -8946,7 +8945,6 @@ static void io_sqpoll_cancel_sync(structstruct task_struct *task;io_sq_thread_park (sqd); -list_del_init (&ctx->sqd_list);io_sqd_update_thread_idle (sqd); task = sqd->thread;if (task) {
@@ -8954,6 +8952,8 @@ static void io_sqpoll_cancel_sync(structinit_task_work (&work.task_work, io_sqpoll_cancel_cb);io_task_work_add_head (&sqd->park_task_work, &work.task_work);wake_up_process (task); + }else { +list_del_init (&ctx->sqd_list); }io_sq_thread_unpark (sqd);
@@ -8987,14 +8987,14 @@ void __io_uring_files_cancel(struct file }/* should only be called by SQPOLL task */ -static void io_uring_cancel_sqpoll (struct io_ring_ctx *ctx) +static void io_uring_cancel_sqpoll (struct io_sq_data *sqd) { -struct io_sq_data *sqd = ctx->sq_data;struct io_uring_task *tctx = current->io_uring; +struct io_ring_ctx *ctx;s64 inflight;DEFINE_WAIT (wait); -WARN_ON_ONCE (!sqd || ctx->sq_data->thread != current); +WARN_ON_ONCE (!sqd || sqd->thread != current);atomic_inc (&tctx->in_idle); do {
@@ -9002,7 +9002,8 @@ static void io_uring_cancel_sqpoll(struc inflight =tctx_inflight (tctx);if (!inflight)break ; -io_uring_try_cancel_requests (ctx, current,NULL ); +list_for_each_entry (ctx, &sqd->ctx_list, sqd_list) +io_uring_try_cancel_requests (ctx, current,NULL );prepare_to_wait (&tctx->wait, &wait,TASK_UNINTERRUPTIBLE );/*
Greg Kroah-Hartman
maintainerPATCH 361/384 io_uring: fix work_exit sqpoll cancellations
In reply to Greg Kroah-HartmanFrom: Pavel Begunkov <[email protected]>
commit 28090c133869b461c5366195a856d73469ab87d9 upstream.
After closing an SQPOLL ring, io_ring_exit_work() kicks in and starts doing cancellations via io_uring_try_cancel_requests(). It will go through io_uring_try_cancel_iowq(), which uses ctx->tctx_list, but as SQPOLL task don't have a ctx note, its io-wq won't be reachable and so is left not cancelled.
It will eventually cancelled when one of the tasks dies, but if a thread group survives for long and changes rings, it will spawn lots of unreclaimed resources and live locked works.
Cancel SQPOLL task's io-wq separately in io_ring_exit_work().
--- fs/io_uring.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-)
fs/io_uring.c +18 -7
@@ -8571,6 +8571,13 @@ static void io_tctx_exit_cb(struct callbcomplete (&work->completion); } +static bool io_cancel_ctx_cb (struct io_wq_work *work,void *data) +{ + struct io_kiocb *req = container_of(work, struct io_kiocb, work); + +return req->ctx == data; +} +static void io_ring_exit_work (struct work_struct *work) { struct io_ring_ctx *ctx = container_of(work, struct io_ring_ctx, exit_work);
@@ -8587,6 +8594,17 @@ static void io_ring_exit_work(struct wor*/ do {io_uring_try_cancel_requests (ctx,NULL ,NULL ); +if (ctx->sq_data) { +struct io_sq_data *sqd = ctx->sq_data; +struct task_struct *tsk; + +io_sq_thread_park (sqd); + tsk = sqd->thread; +if (tsk && tsk->io_uring && tsk->io_uring->io_wq) +io_wq_cancel_cb (tsk->io_uring->io_wq, + io_cancel_ctx_cb, ctx, true); +io_sq_thread_unpark (sqd); + }WARN_ON_ONCE (time_after (jiffies, timeout)); }while (!wait_for_completion_timeout (&ctx->ref_comp,HZ /20 ));
@@ -8731,13 +8749,6 @@ static bool io_cancel_defer_files(structreturn true; } -static bool io_cancel_ctx_cb (struct io_wq_work *work,void *data) -{ - struct io_kiocb *req = container_of(work, struct io_kiocb, work); - -return req->ctx == data; -} -static bool io_uring_try_cancel_iowq (struct io_ring_ctx *ctx) {struct io_tctx_node *node;
Greg Kroah-Hartman
maintainerPATCH 362/384 io_uring: Check current->io_uring in io_uring_cancel_sqpoll
In reply to Greg Kroah-HartmanFrom: Palash Oswal <[email protected]>
commit 6d042ffb598ed83e7d5623cc961d249def5b9829 upstream.
syzkaller identified KASAN: null-ptr-deref Write in io_uring_cancel_sqpoll.
io_uring_cancel_sqpoll is called by io_sq_thread before calling io_uring_alloc_task_context. This leads to current->io_uring being NULL. io_uring_cancel_sqpoll should not have to deal with threads where current->io_uring is NULL.
In order to cast a wider safety net, perform input sanitisation directly in io_uring_cancel_sqpoll and return for NULL value of current->io_uring. This is safe since if current->io_uring isn't set, then there's no way for the task to have submitted any requests.
--- fs/io_uring.c | 2 ++ 1 file changed, 2 insertions(+)
fs/io_uring.c +2 -0
@@ -9005,6 +9005,8 @@ static void io_uring_cancel_sqpoll(strucs64 inflight;DEFINE_WAIT (wait); +if (!current->io_uring) +return ;WARN_ON_ONCE (!sqd || sqd->thread != current);atomic_inc (&tctx->in_idle);
Greg Kroah-Hartman
maintainerPATCH 363/384 usb: gadget: dummy_hcd: fix gpf in gadget_setup
In reply to Greg Kroah-HartmanFrom: Anirudh Rayabharam <[email protected]>
commit 4a5d797a9f9c4f18585544237216d7812686a71f upstream.
Fix a general protection fault reported by syzbot due to a race between gadget_setup() and gadget_unbind() in raw_gadget.
The gadget core is supposed to guarantee that there won't be any more callbacks to the gadget driver once the driver's unbind routine is called. That guarantee is enforced in usb_gadget_remove_driver as follows:
usb_gadget_disconnect(udc->gadget);
if (udc->gadget->irq)
synchronize_irq(udc->gadget->irq);
udc->driver->unbind(udc->gadget);
usb_gadget_udc_stop(udc);usb_gadget_disconnect turns off the pullup resistor, telling the host that the gadget is no longer connected and preventing the transmission of any more USB packets. Any packets that have already been received are sure to processed by the UDC driver's interrupt handler by the time synchronize_irq returns.
But this doesn't work with dummy_hcd, because dummy_hcd doesn't use interrupts; it uses a timer instead. It does have code to emulate the effect of synchronize_irq, but that code doesn't get invoked at the right time -- it currently runs in usb_gadget_udc_stop, after the unbind callback instead of before. Indeed, there's no way for usb_gadget_remove_driver to invoke this code before the unbind callback.
To fix this, move the synchronize_irq() emulation code to dummy_pullup so that it runs before unbind. Also, add a comment explaining why it is necessary to have it there.
--- drivers/usb/gadget/udc/dummy_hcd.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
drivers/usb/gadget/udc/dummy_hcd.c +15 -8
@@ -903,6 +903,21 @@ static int dummy_pullup(struct usb_gadgespin_lock_irqsave (&dum->lock, flags); dum->pullup = (value !=0 );set_link_state (dum_hcd); +if (value ==0 ) { +/* +* Emulate synchronize_irq(): wait for callbacks to finish. +* This seems to be the best place to emulate the call to +* synchronize_irq() that's in usb_gadget_remove_driver(). +* Doing it in dummy_udc_stop() would be too late since it +* is called after the unbind callback and unbind shouldn't +* be invoked until all the other callbacks are finished. +*/ +while (dum->callback_usage >0 ) { +spin_unlock_irqrestore (&dum->lock, flags); +usleep_range (1000 ,2000 ); +spin_lock_irqsave (&dum->lock, flags); + } + }spin_unlock_irqrestore (&dum->lock, flags);usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum_hcd));
@@ -1004,14 +1019,6 @@ static int dummy_udc_stop(struct usb_gadspin_lock_irq (&dum->lock); dum->ints_enabled =0 ;stop_activity (dum); - -/* emulate synchronize_irq(): wait for callbacks to finish */ -while (dum->callback_usage >0 ) { -spin_unlock_irq (&dum->lock); -usleep_range (1000 ,2000 ); -spin_lock_irq (&dum->lock); - } - dum->driver =NULL ;spin_unlock_irq (&dum->lock);
Greg Kroah-Hartman
maintainerPATCH 364/384 usb: gadget: Fix double free of device descriptor pointers
In reply to Greg Kroah-HartmanFrom: Hemant Kumar <[email protected]>
commit 43c4cab006f55b6ca549dd1214e22f5965a8675f upstream.
Upon driver unbind usb_free_all_descriptors() function frees all speed descriptor pointers without setting them to NULL. In case gadget speed changes (i.e from super speed plus to super speed) after driver unbind only upto super speed descriptor pointers get populated. Super speed plus desc still holds the stale (already freed) pointer. Fix this issue by setting all descriptor pointers to NULL after freeing them in usb_free_all_descriptors().
--- drivers/usb/gadget/config.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/gadget/config.c +4 -0
@@ -194,9 +194,13 @@ EXPORT_SYMBOL_GPL(usb_assign_descriptorsvoid usb_free_all_descriptors (struct usb_function *f) {usb_free_descriptors (f->fs_descriptors); + f->fs_descriptors =NULL ;usb_free_descriptors (f->hs_descriptors); + f->hs_descriptors =NULL ;usb_free_descriptors (f->ss_descriptors); + f->ss_descriptors =NULL ;usb_free_descriptors (f->ssp_descriptors); + f->ssp_descriptors =NULL ; }EXPORT_SYMBOL_GPL (usb_free_all_descriptors);
Greg Kroah-Hartman
maintainerPATCH 365/384 usb: gadget/function/f_fs string table fix for multiple languages
In reply to Greg Kroah-HartmanFrom: Dean Anderson <[email protected]>
commit 55b74ce7d2ce0b0058f3e08cab185a0afacfe39e upstream.
Fixes bug with the handling of more than one language in the string table in f_fs.c.str_count was not reset for subsequent language codes. str_count-- "rolls under" and processes u32 max strings on the processing of the second language entry.
The existing bug can be reproduced by adding a second language table to the structure "strings" in tools/usb/ffs-test.c.
--- drivers/usb/gadget/function/f_fs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/gadget/function/f_fs.c +2 -1
@@ -2640,6 +2640,7 @@ static int __ffs_data_got_strings(struct do { /* lang_count > 0 so we can use do-while */ unsigned needed = needed_count; + u32 str_per_lang = str_count; if (len < 3) goto error_free;
@@ -2675,7 +2676,7 @@ static int __ffs_data_got_strings(struct data += length +1 ; len -= length +1 ; - }while (--str_count); + }while (--str_per_lang); s->id =0 ;/* terminator */ s->s =NULL ;
Greg Kroah-Hartman
maintainerPATCH 366/384 usb: dwc3: gadget: Remove FS bInterval_m1 limitation
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit 3232a3ce55edfc0d7f8904543b4088a5339c2b2b upstream.
The programming guide incorrectly stated that the DCFG.bInterval_m1 must be set to 0 when operating in fullspeed. There's no such limitation for all IPs. See DWC_usb3x programming guide section 3.2.2.1.
--- drivers/usb/dwc3/gadget.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/usb/dwc3/gadget.c +6 -4
@@ -608,12 +608,14 @@ static int dwc3_gadget_set_ep_config(stru8 bInterval_m1;/* -* Valid range for DEPCFG.bInterval_m1 is from 0 to 13, and it -* must be set to 0 when the controller operates in full-speed. +* Valid range for DEPCFG.bInterval_m1 is from 0 to 13. +* +* NOTE: The programming guide incorrectly stated bInterval_m1 +* must be set to 0 when operating in fullspeed. Internally the +* controller does not have this limitation. See DWC_usb3x +* programming guide section 3.2.2.1. */ bInterval_m1 =min_t (u8, desc->bInterval -1 ,13 ); -if (dwc->gadget->speed ==USB_SPEED_FULL ) - bInterval_m1 =0 ;if (usb_endpoint_type (desc) ==USB_ENDPOINT_XFER_INT && dwc->gadget->speed ==USB_SPEED_FULL )
Greg Kroah-Hartman
maintainerPATCH 367/384 usb: dwc3: gadget: Fix START_TRANSFER link state check
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit c560e76319a94a3b9285bc426c609903408e4826 upstream.
The START_TRANSFER command needs to be executed while in ON/U0 link state (with an exception during register initialization). Don't use dwc->link_state to check this since the driver only tracks the link state when the link state change interrupt is enabled. Check the link state from DSTS register instead.
Note that often the host already brings the device out of low power before it sends/requests the next transfer. So, the user won't see any issue when the device starts transfer then. This issue is more noticeable in cases when the device delays starting transfer, which can happen during delayed control status after the host put the device in low power.
--- drivers/usb/dwc3/gadget.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/usb/dwc3/gadget.c +7 -6
@@ -308,13 +308,12 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ }if (DWC3_DEPCMD_CMD (cmd) ==DWC3_DEPCMD_STARTTRANSFER ) { -int needs_wakeup; +int link_state; - needs_wakeup = (dwc->link_state ==DWC3_LINK_STATE_U1 || - dwc->link_state ==DWC3_LINK_STATE_U2 || - dwc->link_state ==DWC3_LINK_STATE_U3 ); - -if (unlikely (needs_wakeup)) { + link_state =dwc3_gadget_get_link_state (dwc); +if (link_state ==DWC3_LINK_STATE_U1 || + link_state ==DWC3_LINK_STATE_U2 || + link_state ==DWC3_LINK_STATE_U3 ) { ret =__dwc3_gadget_wakeup (dwc);dev_WARN_ONCE (dwc->dev, ret,"wakeup failed --> %d\n" , ret);
@@ -1975,6 +1974,8 @@ static int __dwc3_gadget_wakeup(struct dcase DWC3_LINK_STATE_RESET :case DWC3_LINK_STATE_RX_DET :/* in HS, means Early Suspend */ case DWC3_LINK_STATE_U3 :/* in HS, means SUSPEND */ +case DWC3_LINK_STATE_U2 :/* in HS, means Sleep (L1) */ +case DWC3_LINK_STATE_U1 :case DWC3_LINK_STATE_RESUME :break ;default :
Greg Kroah-Hartman
maintainerPATCH 368/384 usb: dwc3: core: Do core softreset when switch mode
In reply to Greg Kroah-HartmanFrom: Yu Chen <[email protected]>
commit f88359e1588b85cf0e8209ab7d6620085f3441d9 upstream.
From: John Stultz <[email protected]>
According to the programming guide, to switch mode for DRD controller, the driver needs to do the following.
To switch from device to host:
1. Reset controller with GCTL.CoreSoftReset
2. Set GCTL.PrtCapDir(host mode)
3. Reset the host with USBCMD.HCRESET
4. Then follow up with the initializing host registers sequence
To switch from host to device:
1. Reset controller with GCTL.CoreSoftReset
2. Set GCTL.PrtCapDir(device mode)
3. Reset the device with DCTL.CSftRst
4. Then follow up with the initializing registers sequence
Currently we're missing step 1) to do GCTL.CoreSoftReset and step 3) of switching from host to device. John Stult reported a lockup issue seen with HiKey960 platform without these steps[1]. Similar issue is observed with Ferry's testing platform[2].
So, apply the required steps along with some fixes to Yu Chen's and John Stultz's version. The main fixes to their versions are the missing wait for clocks synchronization before clearing GCTL.CoreSoftReset and only apply DCTL.CSftRst when switching from host to device.
[1] https://lore.kernel.org/linux-usb/[email protected]/
[2] https://lore.kernel.org/linux-usb/[email protected]/
--- drivers/usb/dwc3/core.c | 27 +++++++++++++++++++++++++++ drivers/usb/dwc3/core.h | 5 +++++ 2 files changed, 32 insertions(+)
drivers/usb/dwc3/core.c +27 -0
@@ -114,6 +114,8 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u dwc->current_dr_role = mode; } +static int dwc3_core_soft_reset (struct dwc3 *dwc); +static void __dwc3_set_mode (struct work_struct *work) {struct dwc3 *dwc =work_to_dwc (work);
@@ -121,6 +123,8 @@ static void __dwc3_set_mode(struct work_int ret;u32 reg; +mutex_lock (&dwc->mutex); +pm_runtime_get_sync (dwc->dev);if (dwc->current_dr_role ==DWC3_GCTL_PRTCAP_OTG )
@@ -154,6 +158,25 @@ static void __dwc3_set_mode(struct work_break ; } +/* For DRD host or device mode only */ +if (dwc->desired_dr_role !=DWC3_GCTL_PRTCAP_OTG ) { + reg =dwc3_readl (dwc->regs,DWC3_GCTL ); + reg |=DWC3_GCTL_CORESOFTRESET ; +dwc3_writel (dwc->regs,DWC3_GCTL , reg); + +/* +* Wait for internal clocks to synchronized. DWC_usb31 and +* DWC_usb32 may need at least 50ms (less for DWC_usb3). To +* keep it consistent across different IPs, let's wait up to +* 100ms before clearing GCTL.CORESOFTRESET. +*/ +msleep (100 ); + + reg =dwc3_readl (dwc->regs,DWC3_GCTL ); + reg &= ~DWC3_GCTL_CORESOFTRESET ; +dwc3_writel (dwc->regs,DWC3_GCTL , reg); + } +spin_lock_irqsave (&dwc->lock, flags);dwc3_set_prtcap (dwc, dwc->desired_dr_role);
@@ -178,6 +201,8 @@ static void __dwc3_set_mode(struct work_ }break ;case DWC3_GCTL_PRTCAP_DEVICE : +dwc3_core_soft_reset (dwc); +dwc3_event_buffers_setup (dwc);if (dwc->usb2_phy)
@@ -200,6 +225,7 @@ static void __dwc3_set_mode(struct work_ out:pm_runtime_mark_last_busy (dwc->dev);pm_runtime_put_autosuspend (dwc->dev); +mutex_unlock (&dwc->mutex); }void dwc3_set_mode (struct dwc3 *dwc,u32 mode)
@@ -1545,6 +1571,7 @@ static int dwc3_probe(struct platform_dedwc3_cache_hwparams (dwc);spin_lock_init (&dwc->lock); +mutex_init (&dwc->mutex);pm_runtime_set_active (dev);pm_runtime_use_autosuspend (dev);
drivers/usb/dwc3/core.h +5 -0
@@ -13,6 +13,7 @@#include <linux/device.h> #include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/ioport.h> #include <linux/list.h> #include <linux/bitops.h>
@@ -946,6 +947,7 @@ struct dwc3_scratchpad_array {* @scratch_addr: dma address of scratchbuf * @ep0_in_setup: one control transfer is completed and enter setup phase * @lock: for synchronizing +* @mutex: for mode switching * @dev: pointer to our struct device * @sysdev: pointer to the DMA-capable device * @xhci: pointer to our xHCI child
@@ -1086,6 +1088,9 @@ struct dwc3 {/* device lock */ spinlock_t lock; +/* mode switching lock */ +struct mutex mutex; +struct device *dev;struct device *sysdev;
Greg Kroah-Hartman
maintainerPATCH 369/384 usb: dwc2: Fix session request interrupt handler
In reply to Greg Kroah-HartmanFrom: Artur Petrosyan <[email protected]>
commit 42b32b164acecd850edef010915a02418345a033 upstream.
According to programming guide in host mode, port
power must be turned on in session request
interrupt handlers.
--- drivers/usb/dwc2/core_intr.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/usb/dwc2/core_intr.c +8 -0
@@ -307,6 +307,7 @@ static void dwc2_handle_conn_id_status_cstatic void dwc2_handle_session_req_intr (struct dwc2_hsotg *hsotg) {int ret; +u32 hprt0;/* Clear interrupt */ dwc2_writel (hsotg,GINTSTS_SESSREQINT ,GINTSTS );
@@ -327,6 +328,13 @@ static void dwc2_handle_session_req_intr* established */ dwc2_hsotg_disconnect (hsotg); + }else { +/* Turn on the port power bit. */ + hprt0 =dwc2_read_hprt0 (hsotg); + hprt0 |=HPRT0_PWR ; +dwc2_writel (hsotg, hprt0,HPRT0 ); +/* Connect hcd after port power is set. */ +dwc2_hcd_connect (hsotg); } }
Greg Kroah-Hartman
maintainerPATCH 370/384 PCI: dwc: Move iATU detection earlier
In reply to Greg Kroah-HartmanFrom: Hou Zhiqiang <[email protected]>
commit 8bcca26585585ae4b44d25d30f351ad0afa4976b upstream.
dw_pcie_ep_init() depends on the detected iATU region numbers to allocate the in/outbound window management bitmap. It fails after 281f1f99cf3a ("PCI: dwc: Detect number of iATU windows").
Move the iATU region detection into a new function, move the detection to the very beginning of dw_pcie_host_init() and dw_pcie_ep_init(). Also remove it from the dw_pcie_setup(), since it's more like a software initialization step than hardware setup.
--- drivers/pci/controller/dwc/pcie-designware-ep.c | 2 ++ drivers/pci/controller/dwc/pcie-designware-host.c | 1 + drivers/pci/controller/dwc/pcie-designware.c | 11 ++++++++--- drivers/pci/controller/dwc/pcie-designware.h | 1 + 4 files changed, 12 insertions(+), 3 deletions(-)
drivers/pci/controller/dwc/pcie-designware-ep.c +2 -0
@@ -705,6 +705,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *e } } +dw_pcie_iatu_detect (pci); + res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"addr_space" );if (!res)return -EINVAL ;
drivers/pci/controller/dwc/pcie-designware-host.c +1 -0
@@ -398,6 +398,7 @@ int dw_pcie_host_init(struct pcie_port *if (ret) goto err_free_msi; } +dw_pcie_iatu_detect (pci);dw_pcie_setup_rc (pp);dw_pcie_msi_init (pp);
drivers/pci/controller/dwc/pcie-designware.c +8 -3
@@ -660,11 +660,9 @@ static void dw_pcie_iatu_detect_regions( pci->num_ob_windows = ob; } -void dw_pcie_setup (struct dw_pcie *pci) +void dw_pcie_iatu_detect (struct dw_pcie *pci) { -u32 val;struct device *dev = pci->dev; -struct device_node *np = dev->of_node;struct platform_device *pdev =to_platform_device (dev); if (pci->version >= 0x480A || (!pci->version &&
@@ -693,6 +691,13 @@ void dw_pcie_setup(struct dw_pcie *pci)dev_info (pci->dev,"Detected iATU regions: %u outbound, %u inbound" , pci->num_ob_windows, pci->num_ib_windows); +} + +void dw_pcie_setup (struct dw_pcie *pci) +{ +u32 val; +struct device *dev = pci->dev; +struct device_node *np = dev->of_node;if (pci->link_gen >0 )dw_pcie_link_set_max_speed (pci, pci->link_gen);
drivers/pci/controller/dwc/pcie-designware.h +1 -0
@@ -306,6 +306,7 @@ int dw_pcie_prog_inbound_atu(struct dw_pvoid dw_pcie_disable_atu (struct dw_pcie *pci,int index,enum dw_pcie_region_type type);void dw_pcie_setup (struct dw_pcie *pci); +void dw_pcie_iatu_detect (struct dw_pcie *pci);static inline void dw_pcie_writel_dbi (struct dw_pcie *pci,u32 reg,u32 val) {
Greg Kroah-Hartman
maintainerPATCH 371/384 tty: fix memory leak in vc_deallocate
In reply to Greg Kroah-HartmanFrom: Pavel Skripkin <[email protected]>
commit 211b4d42b70f1c1660feaa968dac0efc2a96ac4d upstream.
syzbot reported memory leak in tty/vt.
The problem was in VT_DISALLOCATE ioctl cmd. After allocating unimap with PIO_UNIMAP it wasn't freed via VT_DISALLOCATE, but vc_cons[currcons].d was zeroed.
--- drivers/tty/vt/vt.c | 1 + 1 file changed, 1 insertion(+)
drivers/tty/vt/vt.c +1 -0
@@ -1381,6 +1381,7 @@ struct vc_data *vc_deallocate(unsigned iatomic_notifier_call_chain (&vt_notifier_list,VT_DEALLOCATE , ¶m);vcs_remove_sysfs (currcons);visual_deinit (vc); +con_free_unimap (vc);put_pid (vc->vt_pid);vc_uniscr_set (vc,NULL );kfree (vc->vc_screenbuf);
Greg Kroah-Hartman
maintainerPATCH 372/384 rsi: Use resume_noirq for SDIO
In reply to Greg Kroah-HartmanFrom: Marek Vasut <[email protected]>
commit c434e5e48dc4e626364491455f97e2db0aa137b1 upstream.
The rsi_resume() does access the bus to enable interrupts on the RSI SDIO WiFi card, however when calling sdio_claim_host() in the resume path, it is possible the bus is already claimed and sdio_claim_host() spins indefinitelly. Enable the SDIO card interrupts in resume_noirq instead to prevent anything else from claiming the SDIO bus first.
--- drivers/net/wireless/rsi/rsi_91x_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/rsi/rsi_91x_sdio.c +1 -1
@@ -1513,7 +1513,7 @@ static int rsi_restore(struct device *de }static const struct dev_pm_ops rsi_pm_ops = { .suspend = rsi_suspend, - .resume = rsi_resume, + .resume_noirq = rsi_resume, .freeze = rsi_freeze, .thaw = rsi_thaw, .restore = rsi_restore,
Greg Kroah-Hartman
maintainerPATCH 373/384 tools/power turbostat: Fix offset overflow issue in index converting
In reply to Greg Kroah-HartmanFrom: Calvin Walton <[email protected]>
commit 13a779de4175df602366d129e41782ad7168cef0 upstream.
The idx_to_offset() function returns type int (32-bit signed), but MSR_PKG_ENERGY_STAT is u32 and would be interpreted as a negative number. The end result is that it hits the if (offset < 0) check in update_msr_sum() which prevents the timer callback from updating the stat in the background when long durations are used. The similar issue exists in offset_to_idx() and update_msr_sum(). Fix this issue by converting the 'int' to 'off_t' accordingly.
--- tools/power/x86/turbostat/turbostat.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
tools/power/x86/turbostat/turbostat.c +6 -5
@@ -291,9 +291,9 @@ struct msr_sum_array {/* The percpu MSR sum array.*/ struct msr_sum_array *per_cpu_msr_sum; -int idx_to_offset (int idx) +off_t idx_to_offset (int idx) { -int offset; +off_t offset;switch (idx) {case IDX_PKG_ENERGY :
@@ -323,7 +323,7 @@ int idx_to_offset(int idx)return offset; } -int offset_to_idx (int offset) +int offset_to_idx (off_t offset) {int idx;
@@ -3276,7 +3276,7 @@ static int update_msr_sum(struct thread_for (i =IDX_PKG_ENERGY ; i <IDX_COUNT ; i++) {unsigned long long msr_cur, msr_last; -int offset; +off_t offset;if (!idx_valid (i))continue ;
@@ -3285,7 +3285,8 @@ static int update_msr_sum(struct thread_continue ; ret =get_msr (cpu, offset, &msr_cur);if (ret) { -fprintf (outf,"Can not update msr(0x%x)\n" , offset); +fprintf (outf,"Can not update msr(0x%llx)\n" , + (unsigned long long )offset);continue ; }
Greg Kroah-Hartman
maintainerPATCH 374/384 tracing: Map all PIDs to command lines
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit 785e3c0a3a870e72dc530856136ab4c8dd207128 upstream.
The default max PID is set by PID_MAX_DEFAULT, and the tracing infrastructure uses this number to map PIDs to the comm names of the tasks, such output of the trace can show names from the recorded PIDs in the ring buffer. This mapping is also exported to user space via the "saved_cmdlines" file in the tracefs directory.
But currently the mapping expects the PIDs to be less than PID_MAX_DEFAULT, which is the default maximum and not the real maximum. Recently, systemd will increases the maximum value of a PID on the system, and when tasks are traced that have a PID higher than PID_MAX_DEFAULT, its comm is not recorded. This leads to the entire trace to have "<...>" as the comm name, which is pretty useless.
Instead, keep the array mapping the size of PID_MAX_DEFAULT, but instead of just mapping the index to the comm, map a mask of the PID (PID_MAX_DEFAULT - 1) to the comm, and find the full PID from the map_cmdline_to_pid array (that already exists).
This bug goes back to the beginning of ftrace, but hasn't been an issue until user space started increasing the maximum value of PIDs.
--- kernel/trace/trace.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-)
kernel/trace/trace.c +15 -26
@@ -2390,14 +2390,13 @@ static void tracing_stop_tr(struct tracestatic int trace_save_cmdline (struct task_struct *tsk) { -unsigned pid, idx; +unsigned tpid, idx;/* treat recording of idle task as a success */ if (!tsk->pid)return 1 ; -if (unlikely (tsk->pid >PID_MAX_DEFAULT )) -return 0 ; + tpid = tsk->pid & (PID_MAX_DEFAULT -1 );/* * It's not the end of the world if we don't get
@@ -2408,26 +2407,15 @@ static int trace_save_cmdline(struct tasif (!arch_spin_trylock (&trace_cmdline_lock))return 0 ; - idx = savedcmd->map_pid_to_cmdline[tsk->pid]; + idx = savedcmd->map_pid_to_cmdline[tpid];if (idx ==NO_CMDLINE_MAP ) { idx = (savedcmd->cmdline_idx +1 ) % savedcmd->cmdline_num; -/* -* Check whether the cmdline buffer at idx has a pid -* mapped. We are going to overwrite that entry so we -* need to clear the map_pid_to_cmdline. Otherwise we -* would read the new comm for the old pid. -*/ - pid = savedcmd->map_cmdline_to_pid[idx]; -if (pid !=NO_CMDLINE_MAP ) - savedcmd->map_pid_to_cmdline[pid] =NO_CMDLINE_MAP ; - - savedcmd->map_cmdline_to_pid[idx] = tsk->pid; - savedcmd->map_pid_to_cmdline[tsk->pid] = idx; - + savedcmd->map_pid_to_cmdline[tpid] = idx; savedcmd->cmdline_idx = idx; } + savedcmd->map_cmdline_to_pid[idx] = tsk->pid;set_cmdline (idx, tsk->comm);arch_spin_unlock (&trace_cmdline_lock);
@@ -2438,6 +2426,7 @@ static int trace_save_cmdline(struct tasstatic void __trace_find_cmdline (int pid,char comm[]) {unsigned map; +int tpid;if (!pid) {strcpy (comm,"<idle>" );
@@ -2449,16 +2438,16 @@ static void __trace_find_cmdline(int pidreturn ; } -if (pid >PID_MAX_DEFAULT ) { -strcpy (comm,"<...>" ); -return ; + tpid = pid & (PID_MAX_DEFAULT -1 ); + map = savedcmd->map_pid_to_cmdline[tpid]; +if (map !=NO_CMDLINE_MAP ) { + tpid = savedcmd->map_cmdline_to_pid[map]; +if (tpid == pid) { +strlcpy (comm,get_saved_cmdlines (map),TASK_COMM_LEN ); +return ; + } } - - map = savedcmd->map_pid_to_cmdline[pid]; -if (map !=NO_CMDLINE_MAP ) -strlcpy (comm,get_saved_cmdlines (map),TASK_COMM_LEN ); -else -strcpy (comm,"<...>" ); +strcpy (comm,"<...>" ); }void trace_find_cmdline (int pid,char comm[])
Greg Kroah-Hartman
maintainerPATCH 375/384 tracing: Restructure trace_clock_global() to never block
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit aafe104aa9096827a429bc1358f8260ee565b7cc upstream.
It was reported that a fix to the ring buffer recursion detection would cause a hung machine when performing suspend / resume testing. The following backtrace was extracted from debugging that case:
Call Trace: trace_clock_global+0x91/0xa0 __rb_reserve_next+0x237/0x460 ring_buffer_lock_reserve+0x12a/0x3f0 trace_buffer_lock_reserve+0x10/0x50 __trace_graph_return+0x1f/0x80 trace_graph_return+0xb7/0xf0 ? trace_clock_global+0x91/0xa0 ftrace_return_to_handler+0x8b/0xf0 ? pv_hash+0xa0/0xa0 return_to_handler+0x15/0x30 ? ftrace_graph_caller+0xa0/0xa0 ? trace_clock_global+0x91/0xa0 ? __rb_reserve_next+0x237/0x460 ? ring_buffer_lock_reserve+0x12a/0x3f0 ? trace_event_buffer_lock_reserve+0x3c/0x120 ? trace_event_buffer_reserve+0x6b/0xc0 ? trace_event_raw_event_device_pm_callback_start+0x125/0x2d0 ? dpm_run_callback+0x3b/0xc0 ? pm_ops_is_empty+0x50/0x50 ? platform_get_irq_byname_optional+0x90/0x90 ? trace_device_pm_callback_start+0x82/0xd0 ? dpm_run_callback+0x49/0xc0
With the following RIP:
RIP: 0010:native_queued_spin_lock_slowpath+0x69/0x200
Since the fix to the recursion detection would allow a single recursion to happen while tracing, this lead to the trace_clock_global() taking a spin lock and then trying to take it again:
ring_buffer_lock_reserve() {
trace_clock_global() {
arch_spin_lock() {
queued_spin_lock_slowpath() {
/* lock taken */
(something else gets traced by function graph tracer)
ring_buffer_lock_reserve() {
trace_clock_global() {
arch_spin_lock() {
queued_spin_lock_slowpath() {
/* DEAD LOCK! */Tracing should *never* block, as it can lead to strange lockups like the above.
Restructure the trace_clock_global() code to instead of simply taking a lock to update the recorded "prev_time" simply use it, as two events happening on two different CPUs that calls this at the same time, really doesn't matter which one goes first. Use a trylock to grab the lock for updating the prev_time, and if it fails, simply try again the next time. If it failed to be taken, that means something else is already updating it.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=212761
--- kernel/trace/trace_clock.c | 48 ++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 16 deletions(-)
kernel/trace/trace_clock.c +32 -16
@@ -95,33 +95,49 @@ u64 notrace trace_clock_global(void) {unsigned long flags;int this_cpu; -u64 now; +u64 now, prev_time;raw_local_irq_save (flags); this_cpu =raw_smp_processor_id (); - now =sched_clock_cpu (this_cpu); +/* -* If in an NMI context then dont risk lockups and return the -* cpu_clock() time: +* The global clock "guarantees" that the events are ordered +* between CPUs. But if two events on two different CPUS call +* trace_clock_global at roughly the same time, it really does +* not matter which one gets the earlier time. Just make sure +* that the same CPU will always show a monotonic clock. +* +* Use a read memory barrier to get the latest written +* time that was recorded. */ -if (unlikely (in_nmi ())) - goto out; +smp_rmb (); + prev_time =READ_ONCE (trace_clock_struct.prev_time); + now =sched_clock_cpu (this_cpu); -arch_spin_lock (&trace_clock_struct.lock); +/* Make sure that now is always greater than prev_time */ +if ((s64)(now - prev_time) <0 ) + now = prev_time +1 ;/* -* TODO: if this happens often then maybe we should reset -* my_scd->clock to prev_time+1, to make sure -* we start ticking with the local clock from now on? +* If in an NMI context then dont risk lockups and simply return +* the current time. */ -if ((s64)(now - trace_clock_struct.prev_time) <0 ) - now = trace_clock_struct.prev_time +1 ; - - trace_clock_struct.prev_time = now; - -arch_spin_unlock (&trace_clock_struct.lock); +if (unlikely (in_nmi ())) + goto out; +/* Tracing can cause strange recursion, always use a try lock */ +if (arch_spin_trylock (&trace_clock_struct.lock)) { +/* Reread prev_time in case it was already updated */ + prev_time =READ_ONCE (trace_clock_struct.prev_time); +if ((s64)(now - prev_time) <0 ) + now = prev_time +1 ; + + trace_clock_struct.prev_time = now; + +/* The unlock acts as the wmb for the above rmb */ +arch_spin_unlock (&trace_clock_struct.lock); + } out:raw_local_irq_restore (flags);
Greg Kroah-Hartman
maintainerPATCH 376/384 dm persistent data: packed struct should have an aligned() attribute too
In reply to Greg Kroah-HartmanFrom: Joe Thornber <[email protected]>
commit a88b2358f1da2c9f9fcc432f2e0a79617fea397c upstream.
Otherwise most non-x86 architectures (e.g. riscv, arm) will resort to byte-by-byte access.
--- drivers/md/persistent-data/dm-btree-internal.h | 4 ++-- drivers/md/persistent-data/dm-space-map-common.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
drivers/md/persistent-data/dm-btree-internal.h +2 -2
@@ -34,12 +34,12 @@ struct node_header {__le32 max_entries;__le32 value_size;__le32 padding; -} __packed; +} __attribute__((packed, aligned(8)));struct btree_node {struct node_header header;__le64 keys[]; -} __packed; +} __attribute__((packed,aligned (8 )));/*
drivers/md/persistent-data/dm-space-map-common.h +4 -4
@@ -33,7 +33,7 @@ struct disk_index_entry {__le64 blocknr;__le32 nr_free;__le32 none_free_before; -} __packed; +} __attribute__ ((packed, aligned(8)));#define MAX_METADATA_BITMAPS 255
@@ -43,7 +43,7 @@ struct disk_metadata_index {__le64 blocknr;struct disk_index_entry index[MAX_METADATA_BITMAPS ]; -} __packed; +} __attribute__ ((packed, aligned(8)));struct ll_disk ;
@@ -86,7 +86,7 @@ struct disk_sm_root {__le64 nr_allocated;__le64 bitmap_root;__le64 ref_count_root; -} __packed; +} __attribute__ ((packed, aligned(8)));#define ENTRIES_PER_BYTE 4
@@ -94,7 +94,7 @@ struct disk_bitmap_header {__le32 csum;__le32 not_used;__le64 blocknr; -} __packed; +} __attribute__ ((packed, aligned(8)));enum allocation_event {SM_NONE ,
Greg Kroah-Hartman
maintainerPATCH 377/384 dm space map common: fix division bug in sm_ll_find_free_block()
In reply to Greg Kroah-HartmanFrom: Joe Thornber <[email protected]>
commit 5208692e80a1f3c8ce2063a22b675dd5589d1d80 upstream.
This division bug meant the search for free metadata space could skip the final allocation bitmap's worth of entries. Fix affects DM thinp, cache and era targets.
--- drivers/md/persistent-data/dm-space-map-common.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/md/persistent-data/dm-space-map-common.c +2 -0
@@ -339,6 +339,8 @@ int sm_ll_find_free_block(struct ll_disk*/ begin =do_div (index_begin, ll->entries_per_block); end =do_div (end, ll->entries_per_block); +if (end ==0 ) + end = ll->entries_per_block;for (i = index_begin; i < index_end; i++, begin =0 ) {struct dm_block *blk;
Greg Kroah-Hartman
maintainerPATCH 378/384 dm integrity: fix missing goto in bitmap_flush_interval error handling
In reply to Greg Kroah-HartmanFrom: Tian Tao <[email protected]>
commit 17e9e134a8efabbbf689a0904eee92bb5a868172 upstream.
--- drivers/md/dm-integrity.c | 1 + 1 file changed, 1 insertion(+)
drivers/md/dm-integrity.c +1 -0
@@ -4039,6 +4039,7 @@ static int dm_integrity_ctr(struct dm_taif (val >= (uint64_t )UINT_MAX *1000 /HZ ) { r = -EINVAL ; ti->error ="Invalid bitmap_flush_interval argument" ; + goto bad; } ic->bitmap_flush_interval =msecs_to_jiffies (val); }else if (!strncmp (opt_string,"internal_hash:" ,strlen ("internal_hash:" ))) {
Greg Kroah-Hartman
maintainerPATCH 379/384 dm rq: fix double free of blk_mq_tag_set in dev remove after table load fails
In reply to Greg Kroah-HartmanFrom: Benjamin Block <[email protected]>
commit 8e947c8f4a5620df77e43c9c75310dc510250166 upstream.
When loading a device-mapper table for a request-based mapped device, and the allocation/initialization of the blk_mq_tag_set for the device fails, a following device remove will cause a double free.
E.g. (dmesg):
device-mapper: core: Cannot initialize queue for request-based dm-mq mapped device
device-mapper: ioctl: unable to set up device queue for new table.
Unable to handle kernel pointer dereference in virtual kernel address space
Failing address: 0305e098835de000 TEID: 0305e098835de803
Fault in home space mode while using kernel ASCE.
AS:000000025efe0007 R3:0000000000000024
Oops: 0038 ilc:3 [#1] SMP
Modules linked in: ... lots of modules ...
Supported: Yes, External
CPU: 0 PID: 7348 Comm: multipathd Kdump: loaded Tainted: G W X 5.3.18-53-default #1 SLE15-SP3
Hardware name: IBM 8561 T01 7I2 (LPAR)
Krnl PSW : 0704e00180000000 000000025e368eca (kfree+0x42/0x330)
R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0 RI:0 EA:3
Krnl GPRS: 000000000000004a 000000025efe5230 c1773200d779968d 0000000000000000
000000025e520270 000000025e8d1b40 0000000000000003 00000007aae10000
000000025e5202a2 0000000000000001 c1773200d779968d 0305e098835de640
00000007a8170000 000003ff80138650 000000025e5202a2 000003e00396faa8
Krnl Code: 000000025e368eb8: c4180041e100 lgrl %r1,25eba50b8
000000025e368ebe: ecba06b93a55 risbg %r11,%r10,6,185,58
#000000025e368ec4: e3b010000008 ag %r11,0(%r1)
>000000025e368eca: e310b0080004 lg %r1,8(%r11)
000000025e368ed0: a7110001 tmll %r1,1
000000025e368ed4: a7740129 brc 7,25e369126
000000025e368ed8: e320b0080004 lg %r2,8(%r11)
000000025e368ede: b904001b lgr %r1,%r11
Call Trace:
[<000000025e368eca>] kfree+0x42/0x330
[<000000025e5202a2>] blk_mq_free_tag_set+0x72/0xb8
[<000003ff801316a8>] dm_mq_cleanup_mapped_device+0x38/0x50 [dm_mod]
[<000003ff80120082>] free_dev+0x52/0xd0 [dm_mod]
[<000003ff801233f0>] __dm_destroy+0x150/0x1d0 [dm_mod]
[<000003ff8012bb9a>] dev_remove+0x162/0x1c0 [dm_mod]
[<000003ff8012a988>] ctl_ioctl+0x198/0x478 [dm_mod]
[<000003ff8012ac8a>] dm_ctl_ioctl+0x22/0x38 [dm_mod]
[<000000025e3b11ee>] ksys_ioctl+0xbe/0xe0
[<000000025e3b127a>] __s390x_sys_ioctl+0x2a/0x40
[<000000025e8c15ac>] system_call+0xd8/0x2c8
Last Breaking-Event-Address:
[<000000025e52029c>] blk_mq_free_tag_set+0x6c/0xb8
Kernel panic - not syncing: Fatal exception: panic_on_oopsWhen allocation/initialization of the blk_mq_tag_set fails in dm_mq_init_request_queue(), it is uninitialized/freed, but the pointer is not reset to NULL; so when dev_remove() later gets into dm_mq_cleanup_mapped_device() it sees the pointer and tries to uninitialize and free it again.
Fix this by setting the pointer to NULL in dm_mq_init_request_queue() error-handling. Also set it to NULL in dm_mq_cleanup_mapped_device().
--- drivers/md/dm-rq.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/md/dm-rq.c +2 -0
@@ -569,6 +569,7 @@ out_tag_set:blk_mq_free_tag_set (md->tag_set); out_kfree_tag_set:kfree (md->tag_set); + md->tag_set =NULL ;return err; }
@@ -578,6 +579,7 @@ void dm_mq_cleanup_mapped_device(structif (md->tag_set) {blk_mq_free_tag_set (md->tag_set);kfree (md->tag_set); + md->tag_set =NULL ; } }
Greg Kroah-Hartman
maintainerPATCH 380/384 pinctrl: Ingenic: Add missing pins to the JZ4770 MAC MII group.
In reply to Greg Kroah-HartmanFrom: 周琰杰 (Zhou Yanjie) <[email protected]>
commit 65afd97630a9d6dd9ea83ff182dfdb15bc58c5d1 upstream.
The MII group of JZ4770's MAC should have 7 pins, add missing pins to the MII group.
--- drivers/pinctrl/pinctrl-ingenic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/pinctrl/pinctrl-ingenic.c +3 -1
@@ -667,7 +667,9 @@ static int jz4770_pwm_pwm7_pins[] = { 0xstatic int jz4770_mac_rmii_pins[] = {0xa9 ,0xab ,0xaa ,0xac ,0xa5 ,0xa4 ,0xad ,0xae ,0xa6 ,0xa8 , }; -static int jz4770_mac_mii_pins[] = {0xa7 ,0xaf , }; +static int jz4770_mac_mii_pins[] = { +0x7b ,0x7a ,0x7d ,0x7c ,0xa7 ,0x24 ,0xaf , +};static const struct group_desc jz4770_groups[] = {INGENIC_PIN_GROUP ("uart0-data" , jz4770_uart0_data,0 ),
Greg Kroah-Hartman
maintainerPATCH 381/384 pinctrl: Ingenic: Add support for read the pin configuration of X1830.
In reply to Greg Kroah-HartmanFrom: 周琰杰 (Zhou Yanjie) <[email protected]>
commit 1d0bd580ef83b78a10c0b37f3313eaa59d8c80db upstream.
Add X1830 support in "ingenic_pinconf_get()", so that it can read the configuration of X1830 SoC correctly.
--- drivers/pinctrl/pinctrl-ingenic.c | 40 +++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-)
drivers/pinctrl/pinctrl-ingenic.c +31 -9
@@ -2109,26 +2109,48 @@ static int ingenic_pinconf_get(struct pienum pin_config_param param =pinconf_to_config_param (*config);unsigned int idx = pin %PINS_PER_GPIO_CHIP ;unsigned int offt = pin /PINS_PER_GPIO_CHIP ; -bool pull; +unsigned int bias; +bool pull, pullup, pulldown; -if (jzpc->info->version >=ID_JZ4770 ) - pull = !ingenic_get_pin_config (jzpc, pin,JZ4770_GPIO_PEN ); -else - pull = !ingenic_get_pin_config (jzpc, pin,JZ4740_GPIO_PULL_DIS ); +if (jzpc->info->version >=ID_X1830 ) { +unsigned int half =PINS_PER_GPIO_CHIP /2 ; +unsigned int idxh = (pin % half) *2 ; + +if (idx < half) +regmap_read (jzpc->map, offt * jzpc->info->reg_offset + +X1830_GPIO_PEL , &bias); +else +regmap_read (jzpc->map, offt * jzpc->info->reg_offset + +X1830_GPIO_PEH , &bias); + + bias = (bias >> idxh) & (GPIO_PULL_UP |GPIO_PULL_DOWN ); + + pullup = (bias ==GPIO_PULL_UP ) && (jzpc->info->pull_ups[offt] &BIT (idx)); + pulldown = (bias ==GPIO_PULL_DOWN ) && (jzpc->info->pull_downs[offt] &BIT (idx)); + + }else { +if (jzpc->info->version >=ID_JZ4770 ) + pull = !ingenic_get_pin_config (jzpc, pin,JZ4770_GPIO_PEN ); +else + pull = !ingenic_get_pin_config (jzpc, pin,JZ4740_GPIO_PULL_DIS ); + + pullup = pull && (jzpc->info->pull_ups[offt] &BIT (idx)); + pulldown = pull && (jzpc->info->pull_downs[offt] &BIT (idx)); + }switch (param) {case PIN_CONFIG_BIAS_DISABLE : -if (pull) +if (pullup || pulldown)return -EINVAL ;break ;case PIN_CONFIG_BIAS_PULL_UP : -if (!pull || !(jzpc->info->pull_ups[offt] &BIT (idx))) +if (!pullup)return -EINVAL ;break ;case PIN_CONFIG_BIAS_PULL_DOWN : -if (!pull || !(jzpc->info->pull_downs[offt] &BIT (idx))) +if (!pulldown)return -EINVAL ;break ;
@@ -2146,7 +2168,7 @@ static void ingenic_set_bias(struct ingeif (jzpc->info->version >=ID_X1830 ) {unsigned int idx = pin %PINS_PER_GPIO_CHIP ;unsigned int half =PINS_PER_GPIO_CHIP /2 ; -unsigned int idxh = pin % half *2 ; +unsigned int idxh = (pin % half) *2 ;unsigned int offt = pin /PINS_PER_GPIO_CHIP ;if (idx < half) {
Greg Kroah-Hartman
maintainerPATCH 382/384 lib/vsprintf.c: remove leftover f and F cases from bstr_printf()
In reply to Greg Kroah-HartmanFrom: Rasmus Villemoes <[email protected]>
commit 84696cfaf4d90945eb2a8302edc6cf627db56b84 upstream.
Commit 9af7706492f9 ("lib/vsprintf: Remove support for %pF and %pf in favour of %pS and %ps") removed support for %pF and %pf, and correctly removed the handling of those cases in vbin_printf(). However, the corresponding cases in bstr_printf() were left behind.
In the same series, %pf was re-purposed for dealing with fwnodes (3bd32d6a2ee6, "lib/vsprintf: Add %pfw conversion specifier for printing fwnode names").
So should anyone use %pf with the binary printf routines, vbin_printf() would (correctly, as it involves dereferencing the pointer) do the string formatting to the u32 array, but bstr_printf() would not copy the string from the u32 array, but instead interpret the first sizeof(void*) bytes of the formatted string as a pointer - which generally won't end well (also, all subsequent get_args would be out of sync).
--- lib/vsprintf.c | 2 -- 1 file changed, 2 deletions(-)
lib/vsprintf.c +0 -2
@@ -3135,8 +3135,6 @@ int bstr_printf(char *buf, size_t size,switch (*fmt) {case 'S' :case 's' : -case 'F' : -case 'f' :case 'x' :case 'K' :case 'e' :
Greg Kroah-Hartman
maintainerPATCH 383/384 thermal/drivers/cpufreq_cooling: Fix slab OOB issue
In reply to Greg Kroah-HartmanFrom: brian-sy yang <[email protected]>
commit 34ab17cc6c2c1ac93d7e5d53bb972df9a968f085 upstream.
Slab OOB issue is scanned by KASAN in cpu_power_to_freq(). If power is limited below the power of OPP0 in EM table, it will cause slab out-of-bound issue with negative array index.
Return the lowest frequency if limited power cannot found a suitable OPP in EM table to fix this issue.
Backtrace: [<ffffffd02d2a37f0>] die+0x104/0x5ac [<ffffffd02d2a5630>] bug_handler+0x64/0xd0 [<ffffffd02d288ce4>] brk_handler+0x160/0x258 [<ffffffd02d281e5c>] do_debug_exception+0x248/0x3f0 [<ffffffd02d284488>] el1_dbg+0x14/0xbc [<ffffffd02d75d1d4>] __kasan_report+0x1dc/0x1e0 [<ffffffd02d75c2e0>] kasan_report+0x10/0x20 [<ffffffd02d75def8>] __asan_report_load8_noabort+0x18/0x28 [<ffffffd02e6fce5c>] cpufreq_power2state+0x180/0x43c [<ffffffd02e6ead80>] power_actor_set_power+0x114/0x1d4 [<ffffffd02e6fac24>] allocate_power+0xaec/0xde0 [<ffffffd02e6f9f80>] power_allocator_throttle+0x3ec/0x5a4 [<ffffffd02e6ea888>] handle_thermal_trip+0x160/0x294 [<ffffffd02e6edd08>] thermal_zone_device_check+0xe4/0x154 [<ffffffd02d351cb4>] process_one_work+0x5e4/0xe28 [<ffffffd02d352f44>] worker_thread+0xa4c/0xfac [<ffffffd02d360124>] kthread+0x33c/0x358 [<ffffffd02d289940>] ret_from_fork+0xc/0x18
--- drivers/thermal/cpufreq_cooling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/thermal/cpufreq_cooling.c +1 -1
@@ -125,7 +125,7 @@ static u32 cpu_power_to_freq(struct cpuf {int i; -for (i = cpufreq_cdev->max_level; i >=0 ; i--) { +for (i = cpufreq_cdev->max_level; i >0 ; i--) {if (power >= cpufreq_cdev->em->table[i].power)break ; }
Greg Kroah-Hartman
maintainerPATCH 384/384 thermal/core/fair share: Lock the thermal zone while looping over instances
In reply to Greg Kroah-HartmanFrom: Lukasz Luba <[email protected]>
commit fef05776eb02238dcad8d5514e666a42572c3f32 upstream.
The tz->lock must be hold during the looping over the instances in that thermal zone. This lock was missing in the governor code since the beginning, so it's hard to point into a particular commit.
--- drivers/thermal/gov_fair_share.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/thermal/gov_fair_share.c +4 -0
@@ -82,6 +82,8 @@ static int fair_share_throttle(struct thint total_instance =0 ;int cur_trip_level =get_trip_level (tz); +mutex_lock (&tz->lock); +list_for_each_entry (instance, &tz->thermal_instances, tz_node) {if (instance->trip != trip)continue ;
@@ -110,6 +112,8 @@ static int fair_share_throttle(struct thmutex_unlock (&instance->cdev->lock);thermal_cdev_update (cdev); } + +mutex_unlock (&tz->lock);return 0 ; }
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.3-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.12.y
and the diffstat can be found below.thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v5.12:
12 builds: 12 pass, 0 fail
28 boots: 28 pass, 0 fail
104 tests: 104 pass, 0 failLinux version: 5.12.3-rc1-g47db4685df62
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra194-p2972-0000, tegra194-p3509-0000+p3668-0000,
tegra20-ventana, tegra210-p2371-2180,
tegra210-p3450-0000, tegra30-cardhu-a04Jon
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.3-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.12.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB, using 32-bit and 64-bit ARM kernels:
Signature · 1 line
Florian
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.3-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.12.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
## Build
* kernel: 5.12.3-rc1
* git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
* git branch: linux-5.12.y
* git commit: 47db4685df6206a3e39f7d56d6402b56e151373b
* git describe: v5.12.2-385-g47db4685df62
* test details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.12.y/build/v5.12.2-385-g47db4685df62
## No regressions (compared to v5.12.2-284-g66353c8ef656)
## No fixes (compared to v5.12.2-284-g66353c8ef656)
## Test result summary
total: 76372, pass: 64454, fail: 1319, skip: 10599, xfail: 0,
## Build Summary
* arc: 10 total, 10 passed, 0 failed
* arm: 193 total, 193 passed, 0 failed
* arm64: 27 total, 27 passed, 0 failed
* i386: 26 total, 26 passed, 0 failed
* mips: 45 total, 45 passed, 0 failed
* parisc: 9 total, 9 passed, 0 failed
* powerpc: 27 total, 27 passed, 0 failed
* riscv: 21 total, 21 passed, 0 failed
* s390: 18 total, 18 passed, 0 failed
* sh: 18 total, 18 passed, 0 failed
* sparc: 9 total, 9 passed, 0 failed
* x86_64: 27 total, 27 passed, 0 failed
## Test suites summary
* fwts
* igt-gpu-tools
* kselftest-android
* kselftest-breakpoints
* kselftest-capabilities
* kselftest-cgroup
* kselftest-clone3
* kselftest-core
* kselftest-cpu-hotplug
* kselftest-cpufreq
* kselftest-drivers
* kselftest-efivarfs
* kselftest-filesystems
* kselftest-firmware
* kselftest-fpu
* kselftest-futex
* kselftest-gpio
* kselftest-ipc
* kselftest-ir
* kselftest-kcmp
* kselftest-kvm
* kselftest-lib
* kselftest-lkdtm
* kselftest-membarrier
* kselftest-memfd
* kselftest-memory-hotplug
* kselftest-mincore
* kselftest-mount
* kselftest-mqueue
* kselftest-net
* kselftest-netfilter
* kselftest-nsfs
* kselftest-openat2
* kselftest-pid_namespace
* kselftest-pidfd
* kselftest-proc
* kselftest-pstore
* kselftest-rseq
* kselftest-rtc
* kselftest-seccomp
* kselftest-sigaltstack
* kselftest-size
* kselftest-splice
* kselftest-static_keys
* kselftest-sync
* kselftest-sysctl
* kselftest-timens
* kselftest-timers
* kselftest-tmpfs
* kselftest-tpm2
* kselftest-user
* kselftest-vm
* kselftest-zram
* kunit
* kvm-unit-tests
* libhugetlbfs
* linux-log-parser
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-controllers-tests
* ltp-cpuhotplug-tests
* ltp-crypto-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-open-posix-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* ltp-tracing-tests
* network-basic-tests
* packetdrill
* perf
* rcutorture
* v4l2-compliance
--
Linaro LKFT
https://lkft.linaro.org
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.3-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.12.y
and the diffstat can be found below.thanks,
greg k-h
5.12.3-rc1 Successfully Compiled and booted on my Raspberry PI 4b (8g) (bcm2711)
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
Build results:
total: 151 pass: 151 fail: 0 Qemu test results: total: 462 pass: 462 fail: 0
Guenter
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.3-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.12.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and boot hangs. I will start bisect
thanks,
-- Shuah
Shuah Khan
Tested-byQuoted 12 lines · Shuah Khan
Quoted 11 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.3-rc1.gz
Quoted 9 lines
Quoted 8 lines
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.thanks,
greg k-h
5.12.3-rc2 compiled and booted on my test system with 79fcd446e7e1 ("drm/amdgpu: Fix memory leak") reverted. No dmesg regressions.
thanks,
-- Shuah
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.12.3 release. There are 384 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 12 May 2021 10:19:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.3-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.12.y
and the diffstat can be found below.thanks,
greg k-h
Tested rc2 against the Fedora build system (aarch64, armv7, ppc64le, s390x, x86_64), and boot tested x86_64. No regressions.