]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Jun 2024 12:32:39 +0000 (14:32 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Jun 2024 12:32:39 +0000 (14:32 +0200)
added patches:
input-try-trimming-too-long-modalias-strings.patch
xsk-validate-user-input-for-xdp_-umem-completion-_fill_ring.patch

queue-4.19/input-try-trimming-too-long-modalias-strings.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/xsk-validate-user-input-for-xdp_-umem-completion-_fill_ring.patch [new file with mode: 0644]

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 (file)
index 0000000..9334beb
--- /dev/null
@@ -0,0 +1,212 @@
+From 0774d19038c496f0c3602fb505c43e1b2d8eed85 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Mon, 29 Apr 2024 14:50:41 -0700
+Subject: Input: try trimming too long modalias strings
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+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 <jandryuk@gmail.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+Tested-by: Jason Andryuk <jandryuk@gmail.com>
+Link: https://lore.kernel.org/r/ZjAWMQCJdrxZkvkB@google.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jason Andryuk <jason.andryuk@amd.com>
+---
+
+---
+ 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;
index 6d9562ef0d46b0dd8c61a14de37824a7a0fffb0c..12f41668314b77f0d95a1fdb9906afa561fbe8cc 100644 (file)
@@ -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 (file)
index 0000000..6938432
--- /dev/null
@@ -0,0 +1,188 @@
+From 237f3cf13b20db183d3706d997eedc3c49eacd44 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+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 <edumazet@google.com>
+
+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:
+ <TASK>
+  __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
+ </TASK>
+
+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 <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: "Björn Töpel" <bjorn@kernel.org>
+Cc: Magnus Karlsson <magnus.karlsson@intel.com>
+Cc: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Cc: Jonathan Lemon <jonathan.lemon@gmail.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20240404202738.3634547-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[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 <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;