From: Greg Kroah-Hartman Date: Mon, 17 Jun 2024 12:32:39 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v6.1.95~120 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=898b0bdd7638b951265783a9edf13336ec25861c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: input-try-trimming-too-long-modalias-strings.patch xsk-validate-user-input-for-xdp_-umem-completion-_fill_ring.patch --- diff --git a/queue-4.19/input-try-trimming-too-long-modalias-strings.patch b/queue-4.19/input-try-trimming-too-long-modalias-strings.patch new file mode 100644 index 00000000000..9334bebdf72 --- /dev/null +++ b/queue-4.19/input-try-trimming-too-long-modalias-strings.patch @@ -0,0 +1,212 @@ +From 0774d19038c496f0c3602fb505c43e1b2d8eed85 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Mon, 29 Apr 2024 14:50:41 -0700 +Subject: Input: try trimming too long modalias strings + +From: Dmitry Torokhov + +commit 0774d19038c496f0c3602fb505c43e1b2d8eed85 upstream. + +If an input device declares too many capability bits then modalias +string for such device may become too long and not fit into uevent +buffer, resulting in failure of sending said uevent. This, in turn, +may prevent userspace from recognizing existence of such devices. + +This is typically not a concern for real hardware devices as they have +limited number of keys, but happen with synthetic devices such as +ones created by xen-kbdfront driver, which creates devices as being +capable of delivering all possible keys, since it doesn't know what +keys the backend may produce. + +To deal with such devices input core will attempt to trim key data, +in the hope that the rest of modalias string will fit in the given +buffer. When trimming key data it will indicate that it is not +complete by placing "+," sign, resulting in conversions like this: + +old: k71,72,73,74,78,7A,7B,7C,7D,8E,9E,A4,AD,E0,E1,E4,F8,174, +new: k71,72,73,74,78,7A,7B,7C,+, + +This should allow existing udev rules continue to work with existing +devices, and will also allow writing more complex rules that would +recognize trimmed modalias and check input device characteristics by +other means (for example by parsing KEY= data in uevent or parsing +input device sysfs attributes). + +Note that the driver core may try adding more uevent environment +variables once input core is done adding its own, so when forming +modalias we can not use the entire available buffer, so we reduce +it by somewhat an arbitrary amount (96 bytes). + +Reported-by: Jason Andryuk +Reviewed-by: Peter Hutterer +Tested-by: Jason Andryuk +Link: https://lore.kernel.org/r/ZjAWMQCJdrxZkvkB@google.com +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Jason Andryuk +--- + +--- + drivers/input/input.c | 105 ++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 90 insertions(+), 15 deletions(-) + +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -1337,19 +1337,19 @@ static int input_print_modalias_bits(cha + char name, unsigned long *bm, + unsigned int min_bit, unsigned int max_bit) + { +- int len = 0, i; ++ int bit = min_bit; ++ int len = 0; + + len += snprintf(buf, max(size, 0), "%c", name); +- for (i = min_bit; i < max_bit; i++) +- if (bm[BIT_WORD(i)] & BIT_MASK(i)) +- len += snprintf(buf + len, max(size - len, 0), "%X,", i); ++ for_each_set_bit_from(bit, bm, max_bit) ++ len += snprintf(buf + len, max(size - len, 0), "%X,", bit); + return len; + } + +-static int input_print_modalias(char *buf, int size, struct input_dev *id, +- int add_cr) ++static int input_print_modalias_parts(char *buf, int size, int full_len, ++ struct input_dev *id) + { +- int len; ++ int len, klen, remainder, space; + + len = snprintf(buf, max(size, 0), + "input:b%04Xv%04Xp%04Xe%04X-", +@@ -1358,8 +1358,49 @@ static int input_print_modalias(char *bu + + len += input_print_modalias_bits(buf + len, size - len, + 'e', id->evbit, 0, EV_MAX); +- len += input_print_modalias_bits(buf + len, size - len, ++ ++ /* ++ * Calculate the remaining space in the buffer making sure we ++ * have place for the terminating 0. ++ */ ++ space = max(size - (len + 1), 0); ++ ++ klen = input_print_modalias_bits(buf + len, size - len, + 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX); ++ len += klen; ++ ++ /* ++ * If we have more data than we can fit in the buffer, check ++ * if we can trim key data to fit in the rest. We will indicate ++ * that key data is incomplete by adding "+" sign at the end, like ++ * this: * "k1,2,3,45,+,". ++ * ++ * Note that we shortest key info (if present) is "k+," so we ++ * can only try to trim if key data is longer than that. ++ */ ++ if (full_len && size < full_len + 1 && klen > 3) { ++ remainder = full_len - len; ++ /* ++ * We can only trim if we have space for the remainder ++ * and also for at least "k+," which is 3 more characters. ++ */ ++ if (remainder <= space - 3) { ++ int i; ++ /* ++ * We are guaranteed to have 'k' in the buffer, so ++ * we need at least 3 additional bytes for storing ++ * "+," in addition to the remainder. ++ */ ++ for (i = size - 1 - remainder - 3; i >= 0; i--) { ++ if (buf[i] == 'k' || buf[i] == ',') { ++ strcpy(buf + i + 1, "+,"); ++ len = i + 3; /* Not counting '\0' */ ++ break; ++ } ++ } ++ } ++ } ++ + len += input_print_modalias_bits(buf + len, size - len, + 'r', id->relbit, 0, REL_MAX); + len += input_print_modalias_bits(buf + len, size - len, +@@ -1375,12 +1416,25 @@ static int input_print_modalias(char *bu + len += input_print_modalias_bits(buf + len, size - len, + 'w', id->swbit, 0, SW_MAX); + +- if (add_cr) +- len += snprintf(buf + len, max(size - len, 0), "\n"); +- + return len; + } + ++static int input_print_modalias(char *buf, int size, struct input_dev *id) ++{ ++ int full_len; ++ ++ /* ++ * Printing is done in 2 passes: first one figures out total length ++ * needed for the modalias string, second one will try to trim key ++ * data in case when buffer is too small for the entire modalias. ++ * If the buffer is too small regardless, it will fill as much as it ++ * can (without trimming key data) into the buffer and leave it to ++ * the caller to figure out what to do with the result. ++ */ ++ full_len = input_print_modalias_parts(NULL, 0, 0, id); ++ return input_print_modalias_parts(buf, size, full_len, id); ++} ++ + static ssize_t input_dev_show_modalias(struct device *dev, + struct device_attribute *attr, + char *buf) +@@ -1388,7 +1442,9 @@ static ssize_t input_dev_show_modalias(s + struct input_dev *id = to_input_dev(dev); + ssize_t len; + +- len = input_print_modalias(buf, PAGE_SIZE, id, 1); ++ len = input_print_modalias(buf, PAGE_SIZE, id); ++ if (len < PAGE_SIZE - 2) ++ len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + + return min_t(int, len, PAGE_SIZE); + } +@@ -1561,6 +1617,23 @@ static int input_add_uevent_bm_var(struc + return 0; + } + ++/* ++ * This is a pretty gross hack. When building uevent data the driver core ++ * may try adding more environment variables to kobj_uevent_env without ++ * telling us, so we have no idea how much of the buffer we can use to ++ * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially ++ * reduce amount of memory we will use for the modalias environment variable. ++ * ++ * The potential additions are: ++ * ++ * SEQNUM=18446744073709551615 - (%llu - 28 bytes) ++ * HOME=/ (6 bytes) ++ * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes) ++ * ++ * 68 bytes total. Allow extra buffer - 96 bytes ++ */ ++#define UEVENT_ENV_EXTRA_LEN 96 ++ + static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, + struct input_dev *dev) + { +@@ -1570,9 +1643,11 @@ static int input_add_uevent_modalias_var + return -ENOMEM; + + len = input_print_modalias(&env->buf[env->buflen - 1], +- sizeof(env->buf) - env->buflen, +- dev, 0); +- if (len >= (sizeof(env->buf) - env->buflen)) ++ (int)sizeof(env->buf) - env->buflen - ++ UEVENT_ENV_EXTRA_LEN, ++ dev); ++ if (len >= ((int)sizeof(env->buf) - env->buflen - ++ UEVENT_ENV_EXTRA_LEN)) + return -ENOMEM; + + env->buflen += len; diff --git a/queue-4.19/series b/queue-4.19/series index 6d9562ef0d4..12f41668314 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -33,3 +33,5 @@ mei-me-release-irq-in-mei_me_pci_resume-error-path.patch jfs-xattr-fix-buffer-overflow-for-invalid-xattr.patch xhci-apply-reset-resume-quirk-to-etron-ej188-xhci-host.patch xhci-apply-broken-streams-quirk-to-etron-ej188-xhci-host.patch +input-try-trimming-too-long-modalias-strings.patch +xsk-validate-user-input-for-xdp_-umem-completion-_fill_ring.patch diff --git a/queue-4.19/xsk-validate-user-input-for-xdp_-umem-completion-_fill_ring.patch b/queue-4.19/xsk-validate-user-input-for-xdp_-umem-completion-_fill_ring.patch new file mode 100644 index 00000000000..693843200cb --- /dev/null +++ b/queue-4.19/xsk-validate-user-input-for-xdp_-umem-completion-_fill_ring.patch @@ -0,0 +1,188 @@ +From 237f3cf13b20db183d3706d997eedc3c49eacd44 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 4 Apr 2024 20:27:38 +0000 +Subject: xsk: validate user input for XDP_{UMEM|COMPLETION}_FILL_RING +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +commit 237f3cf13b20db183d3706d997eedc3c49eacd44 upstream. + +syzbot reported an illegal copy in xsk_setsockopt() [1] + +Make sure to validate setsockopt() @optlen parameter. + +[1] + + BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] + BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline] + BUG: KASAN: slab-out-of-bounds in xsk_setsockopt+0x909/0xa40 net/xdp/xsk.c:1420 +Read of size 4 at addr ffff888028c6cde3 by task syz-executor.0/7549 + +CPU: 0 PID: 7549 Comm: syz-executor.0 Not tainted 6.8.0-syzkaller-08951-gfe46a7dd189e #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x241/0x360 lib/dump_stack.c:114 + print_address_description mm/kasan/report.c:377 [inline] + print_report+0x169/0x550 mm/kasan/report.c:488 + kasan_report+0x143/0x180 mm/kasan/report.c:601 + copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] + copy_from_sockptr include/linux/sockptr.h:55 [inline] + xsk_setsockopt+0x909/0xa40 net/xdp/xsk.c:1420 + do_sock_setsockopt+0x3af/0x720 net/socket.c:2311 + __sys_setsockopt+0x1ae/0x250 net/socket.c:2334 + __do_sys_setsockopt net/socket.c:2343 [inline] + __se_sys_setsockopt net/socket.c:2340 [inline] + __x64_sys_setsockopt+0xb5/0xd0 net/socket.c:2340 + do_syscall_64+0xfb/0x240 + entry_SYSCALL_64_after_hwframe+0x6d/0x75 +RIP: 0033:0x7fb40587de69 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 e1 20 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007fb40665a0c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 +RAX: ffffffffffffffda RBX: 00007fb4059abf80 RCX: 00007fb40587de69 +RDX: 0000000000000005 RSI: 000000000000011b RDI: 0000000000000006 +RBP: 00007fb4058ca47a R08: 0000000000000002 R09: 0000000000000000 +R10: 0000000020001980 R11: 0000000000000246 R12: 0000000000000000 +R13: 000000000000000b R14: 00007fb4059abf80 R15: 00007fff57ee4d08 + + +Allocated by task 7549: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:370 [inline] + __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:387 + kasan_kmalloc include/linux/kasan.h:211 [inline] + __do_kmalloc_node mm/slub.c:3966 [inline] + __kmalloc+0x233/0x4a0 mm/slub.c:3979 + kmalloc include/linux/slab.h:632 [inline] + __cgroup_bpf_run_filter_setsockopt+0xd2f/0x1040 kernel/bpf/cgroup.c:1869 + do_sock_setsockopt+0x6b4/0x720 net/socket.c:2293 + __sys_setsockopt+0x1ae/0x250 net/socket.c:2334 + __do_sys_setsockopt net/socket.c:2343 [inline] + __se_sys_setsockopt net/socket.c:2340 [inline] + __x64_sys_setsockopt+0xb5/0xd0 net/socket.c:2340 + do_syscall_64+0xfb/0x240 + entry_SYSCALL_64_after_hwframe+0x6d/0x75 + +The buggy address belongs to the object at ffff888028c6cde0 + which belongs to the cache kmalloc-8 of size 8 +The buggy address is located 1 bytes to the right of + allocated 2-byte region [ffff888028c6cde0, ffff888028c6cde2) + +The buggy address belongs to the physical page: +page:ffffea0000a31b00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888028c6c9c0 pfn:0x28c6c +anon flags: 0xfff00000000800(slab|node=0|zone=1|lastcpupid=0x7ff) +page_type: 0xffffffff() +raw: 00fff00000000800 ffff888014c41280 0000000000000000 dead000000000001 +raw: ffff888028c6c9c0 0000000080800057 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 0, migratetype Unmovable, gfp_mask 0x112cc0(GFP_USER|__GFP_NOWARN|__GFP_NORETRY), pid 6648, tgid 6644 (syz-executor.0), ts 133906047828, free_ts 133859922223 + set_page_owner include/linux/page_owner.h:31 [inline] + post_alloc_hook+0x1ea/0x210 mm/page_alloc.c:1533 + prep_new_page mm/page_alloc.c:1540 [inline] + get_page_from_freelist+0x33ea/0x3580 mm/page_alloc.c:3311 + __alloc_pages+0x256/0x680 mm/page_alloc.c:4569 + __alloc_pages_node include/linux/gfp.h:238 [inline] + alloc_pages_node include/linux/gfp.h:261 [inline] + alloc_slab_page+0x5f/0x160 mm/slub.c:2175 + allocate_slab mm/slub.c:2338 [inline] + new_slab+0x84/0x2f0 mm/slub.c:2391 + ___slab_alloc+0xc73/0x1260 mm/slub.c:3525 + __slab_alloc mm/slub.c:3610 [inline] + __slab_alloc_node mm/slub.c:3663 [inline] + slab_alloc_node mm/slub.c:3835 [inline] + __do_kmalloc_node mm/slub.c:3965 [inline] + __kmalloc_node+0x2db/0x4e0 mm/slub.c:3973 + kmalloc_node include/linux/slab.h:648 [inline] + __vmalloc_area_node mm/vmalloc.c:3197 [inline] + __vmalloc_node_range+0x5f9/0x14a0 mm/vmalloc.c:3392 + __vmalloc_node mm/vmalloc.c:3457 [inline] + vzalloc+0x79/0x90 mm/vmalloc.c:3530 + bpf_check+0x260/0x19010 kernel/bpf/verifier.c:21162 + bpf_prog_load+0x1667/0x20f0 kernel/bpf/syscall.c:2895 + __sys_bpf+0x4ee/0x810 kernel/bpf/syscall.c:5631 + __do_sys_bpf kernel/bpf/syscall.c:5738 [inline] + __se_sys_bpf kernel/bpf/syscall.c:5736 [inline] + __x64_sys_bpf+0x7c/0x90 kernel/bpf/syscall.c:5736 + do_syscall_64+0xfb/0x240 + entry_SYSCALL_64_after_hwframe+0x6d/0x75 +page last free pid 6650 tgid 6647 stack trace: + reset_page_owner include/linux/page_owner.h:24 [inline] + free_pages_prepare mm/page_alloc.c:1140 [inline] + free_unref_page_prepare+0x95d/0xa80 mm/page_alloc.c:2346 + free_unref_page_list+0x5a3/0x850 mm/page_alloc.c:2532 + release_pages+0x2117/0x2400 mm/swap.c:1042 + tlb_batch_pages_flush mm/mmu_gather.c:98 [inline] + tlb_flush_mmu_free mm/mmu_gather.c:293 [inline] + tlb_flush_mmu+0x34d/0x4e0 mm/mmu_gather.c:300 + tlb_finish_mmu+0xd4/0x200 mm/mmu_gather.c:392 + exit_mmap+0x4b6/0xd40 mm/mmap.c:3300 + __mmput+0x115/0x3c0 kernel/fork.c:1345 + exit_mm+0x220/0x310 kernel/exit.c:569 + do_exit+0x99e/0x27e0 kernel/exit.c:865 + do_group_exit+0x207/0x2c0 kernel/exit.c:1027 + get_signal+0x176e/0x1850 kernel/signal.c:2907 + arch_do_signal_or_restart+0x96/0x860 arch/x86/kernel/signal.c:310 + exit_to_user_mode_loop kernel/entry/common.c:105 [inline] + exit_to_user_mode_prepare include/linux/entry-common.h:328 [inline] + __syscall_exit_to_user_mode_work kernel/entry/common.c:201 [inline] + syscall_exit_to_user_mode+0xc9/0x360 kernel/entry/common.c:212 + do_syscall_64+0x10a/0x240 arch/x86/entry/common.c:89 + entry_SYSCALL_64_after_hwframe+0x6d/0x75 + +Memory state around the buggy address: + ffff888028c6cc80: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc + ffff888028c6cd00: fa fc fc fc fa fc fc fc 00 fc fc fc 06 fc fc fc +>ffff888028c6cd80: fa fc fc fc fa fc fc fc fa fc fc fc 02 fc fc fc + ^ + ffff888028c6ce00: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc + ffff888028c6ce80: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc + +Fixes: 423f38329d26 ("xsk: add umem fill queue support and mmap") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Cc: "Björn Töpel" +Cc: Magnus Karlsson +Cc: Maciej Fijalkowski +Cc: Jonathan Lemon +Acked-by: Daniel Borkmann +Link: https://lore.kernel.org/r/20240404202738.3634547-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +[shung-hsi.yu: two additional changes not present in the original + 1. Check optlen in the XDP_UMEM_REG case as well. It was added in commit + c05cd36458147 ("xsk: add support to allow unaligned chunk placement") but + seems like too big of a change for stable + 2. copy_from_sockptr() in the context was replace copy_from_usr() + because commit a7b75c5a8c414 ("net: pass a sockptr_t into + ->setsockopt") was not present] +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + net/xdp/xsk.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -515,6 +515,8 @@ static int xsk_setsockopt(struct socket + struct xdp_umem_reg mr; + struct xdp_umem *umem; + ++ if (optlen < sizeof(mr)) ++ return -EINVAL; + if (copy_from_user(&mr, optval, sizeof(mr))) + return -EFAULT; + +@@ -542,6 +544,8 @@ static int xsk_setsockopt(struct socket + struct xsk_queue **q; + int entries; + ++ if (optlen < sizeof(entries)) ++ return -EINVAL; + if (copy_from_user(&entries, optval, sizeof(entries))) + return -EFAULT; +