1
0
Fork 0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-01-26 02:25:00 -05:00
linux/lib
Stephen Brennan d1dc87763f assoc_array: Fix BUG_ON during garbage collect
A rare BUG_ON triggered in assoc_array_gc:

    [3430308.818153] kernel BUG at lib/assoc_array.c:1609!

Which corresponded to the statement currently at line 1593 upstream:

    BUG_ON(assoc_array_ptr_is_meta(p));

Using the data from the core dump, I was able to generate a userspace
reproducer[1] and determine the cause of the bug.

[1]: https://github.com/brenns10/kernel_stuff/tree/master/assoc_array_gc

After running the iterator on the entire branch, an internal tree node
looked like the following:

    NODE (nr_leaves_on_branch: 3)
      SLOT [0] NODE (2 leaves)
      SLOT [1] NODE (1 leaf)
      SLOT [2..f] NODE (empty)

In the userspace reproducer, the pr_devel output when compressing this
node was:

    -- compress node 0x5607cc089380 --
    free=0, leaves=0
    [0] retain node 2/1 [nx 0]
    [1] fold node 1/1 [nx 0]
    [2] fold node 0/1 [nx 2]
    [3] fold node 0/2 [nx 2]
    [4] fold node 0/3 [nx 2]
    [5] fold node 0/4 [nx 2]
    [6] fold node 0/5 [nx 2]
    [7] fold node 0/6 [nx 2]
    [8] fold node 0/7 [nx 2]
    [9] fold node 0/8 [nx 2]
    [10] fold node 0/9 [nx 2]
    [11] fold node 0/10 [nx 2]
    [12] fold node 0/11 [nx 2]
    [13] fold node 0/12 [nx 2]
    [14] fold node 0/13 [nx 2]
    [15] fold node 0/14 [nx 2]
    after: 3

At slot 0, an internal node with 2 leaves could not be folded into the
node, because there was only one available slot (slot 0). Thus, the
internal node was retained. At slot 1, the node had one leaf, and was
able to be folded in successfully. The remaining nodes had no leaves,
and so were removed. By the end of the compression stage, there were 14
free slots, and only 3 leaf nodes. The tree was ascended and then its
parent node was compressed. When this node was seen, it could not be
folded, due to the internal node it contained.

The invariant for compression in this function is: whenever
nr_leaves_on_branch < ASSOC_ARRAY_FAN_OUT, the node should contain all
leaf nodes. The compression step currently cannot guarantee this, given
the corner case shown above.

To fix this issue, retry compression whenever we have retained a node,
and yet nr_leaves_on_branch < ASSOC_ARRAY_FAN_OUT. This second
compression will then allow the node in slot 1 to be folded in,
satisfying the invariant. Below is the output of the reproducer once the
fix is applied:

    -- compress node 0x560e9c562380 --
    free=0, leaves=0
    [0] retain node 2/1 [nx 0]
    [1] fold node 1/1 [nx 0]
    [2] fold node 0/1 [nx 2]
    [3] fold node 0/2 [nx 2]
    [4] fold node 0/3 [nx 2]
    [5] fold node 0/4 [nx 2]
    [6] fold node 0/5 [nx 2]
    [7] fold node 0/6 [nx 2]
    [8] fold node 0/7 [nx 2]
    [9] fold node 0/8 [nx 2]
    [10] fold node 0/9 [nx 2]
    [11] fold node 0/10 [nx 2]
    [12] fold node 0/11 [nx 2]
    [13] fold node 0/12 [nx 2]
    [14] fold node 0/13 [nx 2]
    [15] fold node 0/14 [nx 2]
    internal nodes remain despite enough space, retrying
    -- compress node 0x560e9c562380 --
    free=14, leaves=1
    [0] fold node 2/15 [nx 0]
    after: 3

Changes
=======
DH:
 - Use false instead of 0.
 - Reorder the inserted lines in a couple of places to put retained before
   next_slot.

ver #2)
 - Fix typo in pr_devel, correct comparison to "<="

Fixes: 3cb989501c ("Add a generic associative array implementation.")
Cc: <stable@vger.kernel.org>
Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Andrew Morton <akpm@linux-foundation.org>
cc: keyrings@vger.kernel.org
Link: https://lore.kernel.org/r/20220511225517.407935-1-stephen.s.brennan@oracle.com/ # v1
Link: https://lore.kernel.org/r/20220512215045.489140-1-stephen.s.brennan@oracle.com/ # v2
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-01 18:29:06 -07:00
..
842
crypto Revert "crypto: poly1305 - cleanup stray CRYPTO_LIB_POLY1305_RSIZE" 2022-05-28 10:04:06 -07:00
dim dim: initialize all struct fields 2022-05-09 17:20:37 -07:00
fonts
kunit kunit: fix executor OOM error handling logic on non-UML 2022-05-17 10:01:40 -06:00
livepatch
lz4 lz4: fix LZ4_decompress_safe_partial read out of bound 2022-04-08 14:20:36 -10:00
lzo
math
mpi lib/mpi: export mpi_rshift 2022-03-03 10:47:52 +12:00
pldmfw
raid6 lib/raid6: Include <asm/ppc-opcode.h> for VPERMXOR 2022-03-08 15:20:21 -08:00
reed_solomon
test_fortify fortify: Detect struct member overflows in memset() at compile-time 2022-02-13 16:50:06 -08:00
vdso
xz
zlib_deflate
zlib_dfltcc
zlib_inflate
zstd
.gitignore bootconfig: Support embedding a bootconfig file in kernel 2022-04-26 17:58:51 -04:00
argv_split.c
ashldi3.c
ashrdi3.c
asn1_decoder.c
asn1_encoder.c
assoc_array.c assoc_array: Fix BUG_ON during garbage collect 2022-06-01 18:29:06 -07:00
atomic64.c
atomic64_test.c
audit.c
bcd.c
bch.c
bitfield_kunit.c
bitmap.c lib: bitmap: fix many kernel-doc warnings 2022-03-23 19:00:33 -07:00
bitrev.c
bootconfig-data.S bootconfig: Support embedding a bootconfig file in kernel 2022-04-26 17:58:51 -04:00
bootconfig.c bootconfig: Support embedding a bootconfig file in kernel 2022-04-26 17:58:51 -04:00
bsearch.c
btree.c
bucket_locks.c
bug.c bug: Use normal relative pointers in 'struct bug_entry' 2022-05-19 23:46:10 +02:00
build_OID_registry
buildid.c
bust_spinlocks.c
check_signature.c
checksum.c
clz_ctz.c
clz_tab.c
cmdline.c
cmdline_kunit.c
cmpdi2.c
compat_audit.c
cpu_rmap.c
cpumask.c
crc-ccitt.c
crc-itu-t.c
crc-t10dif.c
crc4.c
crc7.c
crc8.c
crc16.c
crc32.c
crc32defs.h
crc32test.c lib/crc32test: correct printed bytes count 2022-01-31 11:21:43 +11:00
crc64-rocksoft.c crypto: add rocksoft 64b crc guard tag framework 2022-03-07 12:48:35 -07:00
crc64.c lib: add rocksoft model crc64 2022-03-07 12:48:35 -07:00
ctype.c
debug_info.c
debug_locks.c
debugobjects.c debugobjects: Convert to SPDX license identifier 2022-05-13 12:35:17 +02:00
dec_and_lock.c
decompress.c
decompress_bunzip2.c
decompress_inflate.c
decompress_unlz4.c
decompress_unlzma.c
decompress_unlzo.c
decompress_unxz.c
decompress_unzstd.c
devmem_is_allowed.c
devres.c
digsig.c
dump_stack.c printk: rename cpulock functions 2022-04-22 21:30:57 +02:00
dynamic_debug.c
dynamic_queue_limits.c
earlycpio.c
errname.c
error-inject.c
errseq.c
extable.c
fault-inject-usercopy.c
fault-inject.c mm: fix missing handler for __GFP_NOWARN 2022-05-19 14:08:55 -07:00
fdt.c
fdt_addresses.c
fdt_empty_tree.c
fdt_ro.c
fdt_rw.c
fdt_strerror.c
fdt_sw.c
fdt_wip.c
find_bit.c
find_bit_benchmark.c
flex_proportions.c
gen_crc32table.c
gen_crc64table.c lib: add rocksoft model crc64 2022-03-07 12:48:35 -07:00
genalloc.c
generic-radix-tree.c
glob.c lib: remove back_str initialization 2022-04-29 14:38:01 -07:00
globtest.c
hexdump.c hex2bin: fix access beyond string end 2022-04-27 10:57:33 -07:00
hweight.c
idr.c
inflate.c
interval_tree.c
interval_tree_test.c
iomap.c
iomap_copy.c
iommu-helper.c
iov_iter.c lib/iov_iter: initialize "flags" in new pipe_buffer 2022-02-21 10:16:39 -05:00
irq_poll.c lib/irq_poll: Prevent softirq pending leak in irq_poll_cpu_dead() 2022-04-13 21:32:21 +02:00
irq_regs.c
is_single_threaded.c
kasprintf.c
Kconfig lib: add generic polynomial calculation 2022-05-22 11:32:30 -07:00
Kconfig.debug cxl for 5.19 2022-05-27 21:24:19 -07:00
Kconfig.kasan kasan: clean-up kconfig options descriptions 2022-05-13 07:20:19 -07:00
Kconfig.kcsan objtool: Make noinstr hacks optional 2022-04-22 12:32:04 +02:00
Kconfig.kfence kfence: allow use of a deferrable timer 2022-03-22 15:57:11 -07:00
Kconfig.kgdb
Kconfig.ubsan objtool: Add CONFIG_OBJTOOL 2022-04-22 12:32:03 +02:00
kfifo.c
klist.c
kobject.c kobject: kobj_type: remove default_attrs 2022-04-05 15:39:19 +02:00
kobject_uevent.c
kstrtox.c lib/kstrtox.c: add "false"/"true" support to kstrtobool() 2022-05-13 07:20:13 -07:00
kstrtox.h
libcrc32c.c
linear_ranges.c
list-test.c list: test: Test the hlist structure 2022-04-05 13:32:27 -06:00
list_debug.c
list_sort.c
llist.c
locking-selftest-hardirq.h
locking-selftest-mutex.h
locking-selftest-rlock-hardirq.h
locking-selftest-rlock-softirq.h
locking-selftest-rlock.h
locking-selftest-rsem.h
locking-selftest-rtmutex.h
locking-selftest-softirq.h
locking-selftest-spin-hardirq.h
locking-selftest-spin-softirq.h
locking-selftest-spin.h
locking-selftest-wlock-hardirq.h
locking-selftest-wlock-softirq.h
locking-selftest-wlock.h
locking-selftest-wsem.h
locking-selftest.c
lockref.c locking/lockref: Use try_cmpxchg64 in CMPXCHG_LOOP macro 2022-05-26 09:52:53 -07:00
logic_iomem.c lib/logic_iomem: correct fallback config references 2022-03-11 10:42:56 +01:00
logic_pio.c
lru_cache.c
lshrdi3.c
Makefile tracing updates for 5.19: 2022-05-29 10:31:36 -07:00
memcat_p.c
memcpy_kunit.c
memory-notifier-error-inject.c
memregion.c
memweight.c
muldi3.c
net_utils.c
netdev-notifier-error-inject.c
nlattr.c
nmi_backtrace.c printk: rename cpulock functions 2022-04-22 21:30:57 +02:00
nodemask.c
notifier-error-inject.c
notifier-error-inject.h
objagg.c
of-reconfig-notifier-error-inject.c
oid_registry.c
once.c
overflow_kunit.c lib: overflow: Convert to Kunit 2022-02-27 09:29:02 -08:00
packing.c
parman.c
parser.c
pci_iomap.c
percpu-refcount.c percpu_ref_init(): clean ->percpu_count_ref on failure 2022-05-18 02:20:17 -04:00
percpu_counter.c
percpu_test.c
plist.c
pm-notifier-error-inject.c
polynomial.c lib: add generic polynomial calculation 2022-05-22 11:32:30 -07:00
radix-tree.c
random32.c random32: use real rng for non-deterministic randomness 2022-05-18 15:53:52 +02:00
ratelimit.c
rbtree.c
rbtree_test.c
ref_tracker.c ref_tracker: remove filter_irq_stacks() call 2022-02-06 11:05:28 +00:00
refcount.c
rhashtable.c
sbitmap.c lib/sbitmap: allocate sb->map via kvzalloc_node 2022-03-21 20:01:34 -06:00
scatterlist.c
seq_buf.c
sg_pool.c
sg_split.c
sha1.c
show_mem.c
siphash.c siphash: use one source of truth for siphash permutations 2022-05-18 15:53:52 +02:00
slub_kunit.c mm/slub, kunit: Make slub_kunit unaffected by user specified flags 2022-04-06 10:11:48 +02:00
smp_processor_id.c
sort.c lib/sort: Add priv pointer to swap function 2022-03-17 20:17:18 -07:00
stackdepot.c lib/stackdepot: allow requesting early initialization dynamically 2022-04-06 10:55:50 +02:00
stackinit_kunit.c lib: stackinit: Convert to KUnit 2022-03-21 08:13:04 -07:00
stmp_device.c
string.c lib/string.c: simplify str[c]spn 2022-04-29 14:38:01 -07:00
string_helpers.c lib/string_helpers: fix not adding strarray to device's resource list 2022-05-12 20:38:36 -07:00
strncpy_from_user.c lib/strn*,objtool: Enforce user_access_begin() rules 2022-04-19 21:58:47 +02:00
strnlen_user.c lib/strn*,objtool: Enforce user_access_begin() rules 2022-04-19 21:58:47 +02:00
syscall.c
test-kstrtox.c
test-string_helpers.c
test_bitmap.c
test_bitops.c
test_bits.c
test_blackhole_dev.c
test_bpf.c bpf, tests: Add load store test case for tail call 2022-04-01 00:27:52 +02:00
test_debug_virtual.c
test_firmware.c
test_fprobe.c fprobe: Add a selftest for fprobe 2022-03-17 20:17:14 -07:00
test_fpu.c
test_free_pages.c
test_hash.c
test_hexdump.c
test_hmm.c mm: remove the extra ZONE_DEVICE struct page refcount 2022-03-03 12:47:33 -05:00
test_hmm_uapi.h
test_ida.c
test_kasan.c kasan: test: Use NULL macros 2022-04-04 14:29:20 -06:00
test_kasan_module.c
test_kmod.c lib/test: use after free in register_test_dev_kmod() 2022-03-29 15:13:36 -07:00
test_kprobes.c
test_linear_ranges.c
test_list_sort.c
test_lockup.c lib/test_lockup: fix kernel pointer check for separate address spaces 2022-02-25 09:36:06 +01:00
test_memcat_p.c
test_meminit.c lib/test_meminit: optimize do_kmem_cache_rcu_persistent() test 2022-04-29 14:38:00 -07:00
test_min_heap.c
test_module.c
test_objagg.c
test_parman.c
test_printf.c
test_ref_tracker.c
test_rhashtable.c
test_scanf.c
test_siphash.c
test_sort.c
test_static_key_base.c
test_static_keys.c
test_string.c lib/test_string.c: add strspn and strcspn tests 2022-04-29 14:38:00 -07:00
test_strscpy.c
test_sysctl.c selftests/sysctl: add sysctl macro test 2022-05-03 10:15:07 +02:00
test_ubsan.c
test_user_copy.c
test_uuid.c
test_vmalloc.c
test_xarray.c XArray: Fix xas_create_range() when multi-order entry present 2022-03-28 19:25:11 -04:00
textsearch.c
timerqueue.c
ts_bm.c
ts_fsm.c
ts_kmp.c
ubsan.c ubsan: no need to unset panic_on_warn in ubsan_epilogue() 2022-03-23 19:00:35 -07:00
ubsan.h
ucmpdi2.c
ucs2_string.c
usercopy.c
uuid.c
vsprintf.c random: remove mostly unused async readiness notifier 2022-05-19 16:54:15 +02:00
win_minmax.c
xarray.c XArray: Disallow sibling entries of nodes 2022-04-22 15:35:40 -04:00
xxhash.c