From: Sasha Levin Date: Thu, 25 May 2023 14:38:25 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: review~93 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0cae8cc437d322e73d37adcfc0b13b1edcb28858;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/lib-string_helpers-introduce-string_upper-and-string.patch b/queue-5.4/lib-string_helpers-introduce-string_upper-and-string.patch new file mode 100644 index 00000000000..f84db401c0d --- /dev/null +++ b/queue-5.4/lib-string_helpers-introduce-string_upper-and-string.patch @@ -0,0 +1,56 @@ +From 02e325a33a43b8f2755b4ac7c84ca6f939c348a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2020 15:01:53 +0300 +Subject: lib/string_helpers: Introduce string_upper() and string_lower() + helpers + +From: Vadim Pasternak + +[ Upstream commit 58eeba0bdb52afe5c18ce2a760ca9fe2901943e9 ] + +Provide the helpers for string conversions to upper and lower cases. + +Signed-off-by: Vadim Pasternak +Signed-off-by: Andy Shevchenko +Stable-dep-of: 3c0f4f09c063 ("usb: gadget: u_ether: Fix host MAC address case") +Signed-off-by: Sasha Levin +--- + include/linux/string_helpers.h | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h +index c289551322342..86f150c2a6b66 100644 +--- a/include/linux/string_helpers.h ++++ b/include/linux/string_helpers.h +@@ -2,6 +2,7 @@ + #ifndef _LINUX_STRING_HELPERS_H_ + #define _LINUX_STRING_HELPERS_H_ + ++#include + #include + + struct file; +@@ -75,6 +76,20 @@ static inline int string_escape_str_any_np(const char *src, char *dst, + return string_escape_str(src, dst, sz, ESCAPE_ANY_NP, only); + } + ++static inline void string_upper(char *dst, const char *src) ++{ ++ do { ++ *dst++ = toupper(*src); ++ } while (*src++); ++} ++ ++static inline void string_lower(char *dst, const char *src) ++{ ++ do { ++ *dst++ = tolower(*src); ++ } while (*src++); ++} ++ + char *kstrdup_quotable(const char *src, gfp_t gfp); + char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp); + char *kstrdup_quotable_file(struct file *file, gfp_t gfp); +-- +2.39.2 + diff --git a/queue-5.4/s390-qdio-fix-do_sqbs-inline-assembly-constraint.patch b/queue-5.4/s390-qdio-fix-do_sqbs-inline-assembly-constraint.patch new file mode 100644 index 00000000000..3242248d75b --- /dev/null +++ b/queue-5.4/s390-qdio-fix-do_sqbs-inline-assembly-constraint.patch @@ -0,0 +1,66 @@ +From c7999a94e8b938b88af625f10a82266e33b328a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 May 2023 17:04:41 +0200 +Subject: s390/qdio: fix do_sqbs() inline assembly constraint + +From: Heiko Carstens + +[ Upstream commit 2862a2fdfae875888e3c1c3634e3422e01d98147 ] + +Use "a" constraint instead of "d" constraint to pass the state parameter to +the do_sqbs() inline assembly. This prevents that general purpose register +zero is used for the state parameter. + +If the compiler would select general purpose register zero this would be +problematic for the used instruction in rsy format: the register used for +the state parameter is a base register. If the base register is general +purpose register zero the contents of the register are unexpectedly ignored +when the instruction is executed. + +This only applies to z/VM guests using QIOASSIST with dedicated (pass through) +QDIO-based devices such as FCP [zfcp driver] as well as real OSA or +HiperSockets [qeth driver]. + +A possible symptom for this case using zfcp is the following repeating kernel +message pattern: + +zfcp : A QDIO problem occurred +zfcp : A QDIO problem occurred +zfcp : qdio: ZFCP on SC using AI:1 QEBSM:1 PRI:1 TDD:1 SIGA: W +zfcp : A QDIO problem occurred +zfcp : A QDIO problem occurred + +Each of the qdio problem message can be accompanied by the following entries +for the affected subchannel in +/sys/kernel/debug/s390dbf/qdio_error/hex_ascii for zfcp or qeth: + + ccq: 69.... + SQBS ERROR. + +Reviewed-by: Benjamin Block +Cc: Steffen Maier +Fixes: 8129ee164267 ("[PATCH] s390: qdio V=V pass-through") +Cc: +Signed-off-by: Heiko Carstens +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + drivers/s390/cio/qdio.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h +index e91d2a589957c..c78651be8d139 100644 +--- a/drivers/s390/cio/qdio.h ++++ b/drivers/s390/cio/qdio.h +@@ -95,7 +95,7 @@ static inline int do_sqbs(u64 token, unsigned char state, int queue, + " lgr 1,%[token]\n" + " .insn rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])" + : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart) +- : [state] "d" ((unsigned long)state), [token] "d" (token) ++ : [state] "a" ((unsigned long)state), [token] "d" (token) + : "memory", "cc", "1"); + *count = _ccq & 0xff; + *start = _queuestart & 0xff; +-- +2.39.2 + diff --git a/queue-5.4/s390-qdio-get-rid-of-register-asm.patch b/queue-5.4/s390-qdio-get-rid-of-register-asm.patch new file mode 100644 index 00000000000..655fb68d00f --- /dev/null +++ b/queue-5.4/s390-qdio-get-rid-of-register-asm.patch @@ -0,0 +1,172 @@ +From 8ba8fe03e1edee1fac51624210f3739c490406cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Jun 2021 15:26:16 +0200 +Subject: s390/qdio: get rid of register asm + +From: Heiko Carstens + +[ Upstream commit d3e2ff5436d6ee38b572ba5c01dc7994769bec54 ] + +Reviewed-by: Benjamin Block +Signed-off-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Stable-dep-of: 2862a2fdfae8 ("s390/qdio: fix do_sqbs() inline assembly constraint") +Signed-off-by: Sasha Levin +--- + drivers/s390/cio/qdio.h | 25 ++++++++------- + drivers/s390/cio/qdio_main.c | 62 +++++++++++++++++++----------------- + 2 files changed, 46 insertions(+), 41 deletions(-) + +diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h +index 3b0a4483a2520..e91d2a589957c 100644 +--- a/drivers/s390/cio/qdio.h ++++ b/drivers/s390/cio/qdio.h +@@ -88,15 +88,15 @@ enum qdio_irq_states { + static inline int do_sqbs(u64 token, unsigned char state, int queue, + int *start, int *count) + { +- register unsigned long _ccq asm ("0") = *count; +- register unsigned long _token asm ("1") = token; + unsigned long _queuestart = ((unsigned long)queue << 32) | *start; ++ unsigned long _ccq = *count; + + asm volatile( +- " .insn rsy,0xeb000000008A,%1,0,0(%2)" +- : "+d" (_ccq), "+d" (_queuestart) +- : "d" ((unsigned long)state), "d" (_token) +- : "memory", "cc"); ++ " lgr 1,%[token]\n" ++ " .insn rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])" ++ : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart) ++ : [state] "d" ((unsigned long)state), [token] "d" (token) ++ : "memory", "cc", "1"); + *count = _ccq & 0xff; + *start = _queuestart & 0xff; + +@@ -106,16 +106,17 @@ static inline int do_sqbs(u64 token, unsigned char state, int queue, + static inline int do_eqbs(u64 token, unsigned char *state, int queue, + int *start, int *count, int ack) + { +- register unsigned long _ccq asm ("0") = *count; +- register unsigned long _token asm ("1") = token; + unsigned long _queuestart = ((unsigned long)queue << 32) | *start; + unsigned long _state = (unsigned long)ack << 63; ++ unsigned long _ccq = *count; + + asm volatile( +- " .insn rrf,0xB99c0000,%1,%2,0,0" +- : "+d" (_ccq), "+d" (_queuestart), "+d" (_state) +- : "d" (_token) +- : "memory", "cc"); ++ " lgr 1,%[token]\n" ++ " .insn rrf,0xb99c0000,%[qs],%[state],%[ccq],0" ++ : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart), ++ [state] "+&d" (_state) ++ : [token] "d" (token) ++ : "memory", "cc", "1"); + *count = _ccq & 0xff; + *start = _queuestart & 0xff; + *state = _state & 0xff; +diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c +index 5b63c505a2f7c..620655bcbe80d 100644 +--- a/drivers/s390/cio/qdio_main.c ++++ b/drivers/s390/cio/qdio_main.c +@@ -31,38 +31,41 @@ MODULE_DESCRIPTION("QDIO base support"); + MODULE_LICENSE("GPL"); + + static inline int do_siga_sync(unsigned long schid, +- unsigned int out_mask, unsigned int in_mask, ++ unsigned long out_mask, unsigned long in_mask, + unsigned int fc) + { +- register unsigned long __fc asm ("0") = fc; +- register unsigned long __schid asm ("1") = schid; +- register unsigned long out asm ("2") = out_mask; +- register unsigned long in asm ("3") = in_mask; + int cc; + + asm volatile( ++ " lgr 0,%[fc]\n" ++ " lgr 1,%[schid]\n" ++ " lgr 2,%[out]\n" ++ " lgr 3,%[in]\n" + " siga 0\n" +- " ipm %0\n" +- " srl %0,28\n" +- : "=d" (cc) +- : "d" (__fc), "d" (__schid), "d" (out), "d" (in) : "cc"); ++ " ipm %[cc]\n" ++ " srl %[cc],28\n" ++ : [cc] "=&d" (cc) ++ : [fc] "d" (fc), [schid] "d" (schid), ++ [out] "d" (out_mask), [in] "d" (in_mask) ++ : "cc", "0", "1", "2", "3"); + return cc; + } + +-static inline int do_siga_input(unsigned long schid, unsigned int mask, +- unsigned int fc) ++static inline int do_siga_input(unsigned long schid, unsigned long mask, ++ unsigned long fc) + { +- register unsigned long __fc asm ("0") = fc; +- register unsigned long __schid asm ("1") = schid; +- register unsigned long __mask asm ("2") = mask; + int cc; + + asm volatile( ++ " lgr 0,%[fc]\n" ++ " lgr 1,%[schid]\n" ++ " lgr 2,%[mask]\n" + " siga 0\n" +- " ipm %0\n" +- " srl %0,28\n" +- : "=d" (cc) +- : "d" (__fc), "d" (__schid), "d" (__mask) : "cc"); ++ " ipm %[cc]\n" ++ " srl %[cc],28\n" ++ : [cc] "=&d" (cc) ++ : [fc] "d" (fc), [schid] "d" (schid), [mask] "d" (mask) ++ : "cc", "0", "1", "2"); + return cc; + } + +@@ -78,23 +81,24 @@ static inline int do_siga_input(unsigned long schid, unsigned int mask, + * Note: For IQDC unicast queues only the highest priority queue is processed. + */ + static inline int do_siga_output(unsigned long schid, unsigned long mask, +- unsigned int *bb, unsigned int fc, ++ unsigned int *bb, unsigned long fc, + unsigned long aob) + { +- register unsigned long __fc asm("0") = fc; +- register unsigned long __schid asm("1") = schid; +- register unsigned long __mask asm("2") = mask; +- register unsigned long __aob asm("3") = aob; + int cc; + + asm volatile( ++ " lgr 0,%[fc]\n" ++ " lgr 1,%[schid]\n" ++ " lgr 2,%[mask]\n" ++ " lgr 3,%[aob]\n" + " siga 0\n" +- " ipm %0\n" +- " srl %0,28\n" +- : "=d" (cc), "+d" (__fc), "+d" (__aob) +- : "d" (__schid), "d" (__mask) +- : "cc"); +- *bb = __fc >> 31; ++ " lgr %[fc],0\n" ++ " ipm %[cc]\n" ++ " srl %[cc],28\n" ++ : [cc] "=&d" (cc), [fc] "+&d" (fc) ++ : [schid] "d" (schid), [mask] "d" (mask), [aob] "d" (aob) ++ : "cc", "0", "1", "2", "3"); ++ *bb = fc >> 31; + return cc; + } + +-- +2.39.2 + diff --git a/queue-5.4/series b/queue-5.4/series index 4adf3365b75..12bec450850 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -113,3 +113,10 @@ netfilter-nf_tables-hold-mutex-on-netns-pre_exit-pat.patch hid-wacom-force-pen-out-of-prox-if-no-events-have-been-received-in-a-while.patch hid-wacom-add-new-intuos-pro-small-pth-460-device-ids.patch hid-wacom-add-three-styli-to-wacom_intuos_get_tool_type.patch +lib-string_helpers-introduce-string_upper-and-string.patch +usb-gadget-u_ether-convert-prints-to-device-prints.patch +usb-gadget-u_ether-fix-host-mac-address-case.patch +vc_screen-rewrite-vcs_size-to-accept-vc-not-inode.patch +vc_screen-reload-load-of-struct-vc_data-pointer-in-v.patch +s390-qdio-get-rid-of-register-asm.patch +s390-qdio-fix-do_sqbs-inline-assembly-constraint.patch diff --git a/queue-5.4/usb-gadget-u_ether-convert-prints-to-device-prints.patch b/queue-5.4/usb-gadget-u_ether-convert-prints-to-device-prints.patch new file mode 100644 index 00000000000..628f1c6922e --- /dev/null +++ b/queue-5.4/usb-gadget-u_ether-convert-prints-to-device-prints.patch @@ -0,0 +1,86 @@ +From 89dabfe5f65fc6a339be9846f0b305c7a13cf210 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Feb 2023 12:53:18 +0000 +Subject: usb: gadget: u_ether: Convert prints to device prints + +From: Jon Hunter + +[ Upstream commit 938fc645317632d79c048608689683b5437496ea ] + +The USB ethernet gadget driver implements its own print macros which +call printk. Device drivers should use the device prints that print the +device name. Fortunately, the same macro names are defined in the header +file 'linux/usb/composite.h' and these use the device prints. Therefore, +remove the local definitions in the USB ethernet gadget driver and use +those in 'linux/usb/composite.h'. The only difference is that now the +device name is printed instead of the ethernet interface name. + +Tested using ethernet gadget on Jetson AGX Orin. + +Signed-off-by: Jon Hunter +Tested-by: Jon Hunter +Link: https://lore.kernel.org/r/20230209125319.18589-1-jonathanh@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 3c0f4f09c063 ("usb: gadget: u_ether: Fix host MAC address case") +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/function/u_ether.c | 36 +-------------------------- + 1 file changed, 1 insertion(+), 35 deletions(-) + +diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c +index 3f053b11e2cee..d9f9c7a678d8b 100644 +--- a/drivers/usb/gadget/function/u_ether.c ++++ b/drivers/usb/gadget/function/u_ether.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include "u_ether.h" + +@@ -102,41 +103,6 @@ static inline int qlen(struct usb_gadget *gadget, unsigned qmult) + + /*-------------------------------------------------------------------------*/ + +-/* REVISIT there must be a better way than having two sets +- * of debug calls ... +- */ +- +-#undef DBG +-#undef VDBG +-#undef ERROR +-#undef INFO +- +-#define xprintk(d, level, fmt, args...) \ +- printk(level "%s: " fmt , (d)->net->name , ## args) +- +-#ifdef DEBUG +-#undef DEBUG +-#define DBG(dev, fmt, args...) \ +- xprintk(dev , KERN_DEBUG , fmt , ## args) +-#else +-#define DBG(dev, fmt, args...) \ +- do { } while (0) +-#endif /* DEBUG */ +- +-#ifdef VERBOSE_DEBUG +-#define VDBG DBG +-#else +-#define VDBG(dev, fmt, args...) \ +- do { } while (0) +-#endif /* DEBUG */ +- +-#define ERROR(dev, fmt, args...) \ +- xprintk(dev , KERN_ERR , fmt , ## args) +-#define INFO(dev, fmt, args...) \ +- xprintk(dev , KERN_INFO , fmt , ## args) +- +-/*-------------------------------------------------------------------------*/ +- + /* NETWORK DRIVER HOOKUP (to the layer above this driver) */ + + static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) +-- +2.39.2 + diff --git a/queue-5.4/usb-gadget-u_ether-fix-host-mac-address-case.patch b/queue-5.4/usb-gadget-u_ether-fix-host-mac-address-case.patch new file mode 100644 index 00000000000..2ff61473316 --- /dev/null +++ b/queue-5.4/usb-gadget-u_ether-fix-host-mac-address-case.patch @@ -0,0 +1,64 @@ +From d3a0a436d0cea7e59ed2a33a98e0d417764a9567 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 May 2023 16:36:40 +0200 +Subject: usb: gadget: u_ether: Fix host MAC address case +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Konrad Gräfe + +[ Upstream commit 3c0f4f09c063e143822393d99cb2b19a85451c07 ] + +The CDC-ECM specification [1] requires to send the host MAC address as +an uppercase hexadecimal string in chapter "5.4 Ethernet Networking +Functional Descriptor": + The Unicode character is chosen from the set of values 30h through + 39h and 41h through 46h (0-9 and A-F). + +However, snprintf(.., "%pm", ..) generates a lowercase MAC address +string. While most host drivers are tolerant to this, UsbNcm.sys on +Windows 10 is not. Instead it uses a different MAC address with all +bytes set to zero including and after the first byte containing a +lowercase letter. On Windows 11 Microsoft fixed it, but apparently they +did not backport the fix. + +This change fixes the issue by upper-casing the MAC to comply with the +specification. + +[1]: https://www.usb.org/document-library/class-definitions-communication-devices-12, file ECM120.pdf + +Fixes: bcd4a1c40bee ("usb: gadget: u_ether: construct with default values and add setters/getters") +Cc: stable@vger.kernel.org +Signed-off-by: Konrad Gräfe +Link: https://lore.kernel.org/r/20230505143640.443014-1-k.graefe@gateware.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/function/u_ether.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c +index d9f9c7a678d8b..af3cb3bfdc29a 100644 +--- a/drivers/usb/gadget/function/u_ether.c ++++ b/drivers/usb/gadget/function/u_ether.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + + #include "u_ether.h" +@@ -940,6 +941,8 @@ int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len) + dev = netdev_priv(net); + snprintf(host_addr, len, "%pm", dev->host_mac); + ++ string_upper(host_addr, host_addr); ++ + return strlen(host_addr); + } + EXPORT_SYMBOL_GPL(gether_get_host_addr_cdc); +-- +2.39.2 + diff --git a/queue-5.4/vc_screen-reload-load-of-struct-vc_data-pointer-in-v.patch b/queue-5.4/vc_screen-reload-load-of-struct-vc_data-pointer-in-v.patch new file mode 100644 index 00000000000..e23dfcfa6b0 --- /dev/null +++ b/queue-5.4/vc_screen-reload-load-of-struct-vc_data-pointer-in-v.patch @@ -0,0 +1,120 @@ +From e50829937cbc170854c92f65775fb4d3835c946a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 May 2023 06:08:48 -0500 +Subject: vc_screen: reload load of struct vc_data pointer in vcs_write() to + avoid UAF +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: George Kennedy + +[ Upstream commit 8fb9ea65c9d1338b0d2bb0a9122dc942cdd32357 ] + +After a call to console_unlock() in vcs_write() the vc_data struct can be +freed by vc_port_destruct(). Because of that, the struct vc_data pointer +must be reloaded in the while loop in vcs_write() after console_lock() to +avoid a UAF when vcs_size() is called. + +Syzkaller reported a UAF in vcs_size(). + +BUG: KASAN: slab-use-after-free in vcs_size (drivers/tty/vt/vc_screen.c:215) +Read of size 4 at addr ffff8880beab89a8 by task repro_vcs_size/4119 + +Call Trace: + +__asan_report_load4_noabort (mm/kasan/report_generic.c:380) +vcs_size (drivers/tty/vt/vc_screen.c:215) +vcs_write (drivers/tty/vt/vc_screen.c:664) +vfs_write (fs/read_write.c:582 fs/read_write.c:564) +... + + +Allocated by task 1213: +kmalloc_trace (mm/slab_common.c:1064) +vc_allocate (./include/linux/slab.h:559 ./include/linux/slab.h:680 + drivers/tty/vt/vt.c:1078 drivers/tty/vt/vt.c:1058) +con_install (drivers/tty/vt/vt.c:3334) +tty_init_dev (drivers/tty/tty_io.c:1303 drivers/tty/tty_io.c:1415 + drivers/tty/tty_io.c:1392) +tty_open (drivers/tty/tty_io.c:2082 drivers/tty/tty_io.c:2128) +chrdev_open (fs/char_dev.c:415) +do_dentry_open (fs/open.c:921) +vfs_open (fs/open.c:1052) +... + +Freed by task 4116: +kfree (mm/slab_common.c:1016) +vc_port_destruct (drivers/tty/vt/vt.c:1044) +tty_port_destructor (drivers/tty/tty_port.c:296) +tty_port_put (drivers/tty/tty_port.c:312) +vt_disallocate_all (drivers/tty/vt/vt_ioctl.c:662 (discriminator 2)) +vt_ioctl (drivers/tty/vt/vt_ioctl.c:903) +tty_ioctl (drivers/tty/tty_io.c:2778) +... + +The buggy address belongs to the object at ffff8880beab8800 + which belongs to the cache kmalloc-1k of size 1024 +The buggy address is located 424 bytes inside of + freed 1024-byte region [ffff8880beab8800, ffff8880beab8c00) + +The buggy address belongs to the physical page: +page:00000000afc77580 refcount:1 mapcount:0 mapping:0000000000000000 + index:0x0 pfn:0xbeab8 +head:00000000afc77580 order:3 entire_mapcount:0 nr_pages_mapped:0 + pincount:0 +flags: 0xfffffc0010200(slab|head|node=0|zone=1|lastcpupid=0x1fffff) +page_type: 0xffffffff() +raw: 000fffffc0010200 ffff888100042dc0 ffffea000426de00 dead000000000002 +raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8880beab8880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8880beab8900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +>ffff8880beab8980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff8880beab8a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8880beab8a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +================================================================== +Disabling lock debugging due to kernel taint + +Fixes: ac751efa6a0d ("console: rename acquire/release_console_sem() to console_lock/unlock()") +Cc: stable +Reported-by: syzkaller +Signed-off-by: George Kennedy +Reviewed-by: Thomas Weißschuh +Link: https://lore.kernel.org/r/1683889728-10411-1-git-send-email-george.kennedy@oracle.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/vt/vc_screen.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c +index 48d74269f1d59..a6813e3393ece 100644 +--- a/drivers/tty/vt/vc_screen.c ++++ b/drivers/tty/vt/vc_screen.c +@@ -523,10 +523,17 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) + } + } + +- /* The vcs_size might have changed while we slept to grab +- * the user buffer, so recheck. ++ /* The vc might have been freed or vcs_size might have changed ++ * while we slept to grab the user buffer, so recheck. + * Return data written up to now on failure. + */ ++ vc = vcs_vc(inode, &viewed); ++ if (!vc) { ++ if (written) ++ break; ++ ret = -ENXIO; ++ goto unlock_out; ++ } + size = vcs_size(vc, attr, false); + if (size < 0) { + if (written) +-- +2.39.2 + diff --git a/queue-5.4/vc_screen-rewrite-vcs_size-to-accept-vc-not-inode.patch b/queue-5.4/vc_screen-rewrite-vcs_size-to-accept-vc-not-inode.patch new file mode 100644 index 00000000000..4726ad48693 --- /dev/null +++ b/queue-5.4/vc_screen-rewrite-vcs_size-to-accept-vc-not-inode.patch @@ -0,0 +1,126 @@ +From d7bd6c079c8655b9b6cb4bfd889911abfdbc7e47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Aug 2020 10:56:55 +0200 +Subject: vc_screen: rewrite vcs_size to accept vc, not inode + +From: Jiri Slaby + +[ Upstream commit 71d4abfab322e827a75304431fe0fad3c805cb80 ] + +It is weird to fetch the information from the inode over and over. Read +and write already have the needed information, so rewrite vcs_size to +accept a vc, attr and unicode and adapt vcs_lseek to that. + +Also make sure all sites check the return value of vcs_size for errors. + +And document it using kernel-doc. + +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20200818085706.12163-5-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 8fb9ea65c9d1 ("vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF") +Signed-off-by: Sasha Levin +--- + drivers/tty/vt/vc_screen.c | 46 ++++++++++++++++++++++++-------------- + 1 file changed, 29 insertions(+), 17 deletions(-) + +diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c +index 90de3331e4a51..48d74269f1d59 100644 +--- a/drivers/tty/vt/vc_screen.c ++++ b/drivers/tty/vt/vc_screen.c +@@ -200,39 +200,47 @@ vcs_vc(struct inode *inode, int *viewed) + return vc_cons[currcons].d; + } + +-/* +- * Returns size for VC carried by inode. ++/** ++ * vcs_size -- return size for a VC in @vc ++ * @vc: which VC ++ * @attr: does it use attributes? ++ * @unicode: is it unicode? ++ * + * Must be called with console_lock. + */ +-static int +-vcs_size(struct inode *inode) ++static int vcs_size(const struct vc_data *vc, bool attr, bool unicode) + { + int size; +- struct vc_data *vc; + + WARN_CONSOLE_UNLOCKED(); + +- vc = vcs_vc(inode, NULL); +- if (!vc) +- return -ENXIO; +- + size = vc->vc_rows * vc->vc_cols; + +- if (use_attributes(inode)) { +- if (use_unicode(inode)) ++ if (attr) { ++ if (unicode) + return -EOPNOTSUPP; +- size = 2*size + HEADER_SIZE; +- } else if (use_unicode(inode)) ++ ++ size = 2 * size + HEADER_SIZE; ++ } else if (unicode) + size *= 4; ++ + return size; + } + + static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) + { ++ struct inode *inode = file_inode(file); ++ struct vc_data *vc; + int size; + + console_lock(); +- size = vcs_size(file_inode(file)); ++ vc = vcs_vc(inode, NULL); ++ if (!vc) { ++ console_unlock(); ++ return -ENXIO; ++ } ++ ++ size = vcs_size(vc, use_attributes(inode), use_unicode(inode)); + console_unlock(); + if (size < 0) + return size; +@@ -294,7 +302,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) + * as copy_to_user at the end of this loop + * could sleep. + */ +- size = vcs_size(inode); ++ size = vcs_size(vc, attr, uni_mode); + if (size < 0) { + ret = size; + break; +@@ -476,7 +484,11 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) + if (!vc) + goto unlock_out; + +- size = vcs_size(inode); ++ size = vcs_size(vc, attr, false); ++ if (size < 0) { ++ ret = size; ++ goto unlock_out; ++ } + ret = -EINVAL; + if (pos < 0 || pos > size) + goto unlock_out; +@@ -515,7 +527,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) + * the user buffer, so recheck. + * Return data written up to now on failure. + */ +- size = vcs_size(inode); ++ size = vcs_size(vc, attr, false); + if (size < 0) { + if (written) + break; +-- +2.39.2 +