diff --git a/.gitignore b/.gitignore index e69de29..3dae703 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/kernel-5.14.0-162.6.1.el9_1.src.rpm +SOURCES/v0.9.7.tar.gz diff --git a/.kpatch-patch-5_14_0-162_6_1.metadata b/.kpatch-patch-5_14_0-162_6_1.metadata index e69de29..e214ac6 100644 --- a/.kpatch-patch-5_14_0-162_6_1.metadata +++ b/.kpatch-patch-5_14_0-162_6_1.metadata @@ -0,0 +1,2 @@ +967b98a8ed7c7d6d4f25f5f7e5b1f911272cfaa6 SOURCES/kernel-5.14.0-162.6.1.el9_1.src.rpm +da88fa82b005bbafc1719c59bd00847ce2a22a60 SOURCES/v0.9.7.tar.gz diff --git a/SOURCES/CVE-2022-2959.patch b/SOURCES/CVE-2022-2959.patch new file mode 100644 index 0000000..aeea166 --- /dev/null +++ b/SOURCES/CVE-2022-2959.patch @@ -0,0 +1,160 @@ +From cd24a1fbd0abbaed922df6f88a4c166642240c18 Mon Sep 17 00:00:00 2001 +From: Yannick Cote +Date: Mon, 12 Dec 2022 12:34:49 -0500 +Subject: [KPATCH CVE-2022-2959] kpatch fixes for CVE-2022-2959 + +Kernels: +5.14.0-162.6.1.el9_1 + + +Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-9/-/merge_requests/12 +Approved-by: Joe Lawrence (@joe.lawrence) +Changes since last build: +[x86_64]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +intel_gt.o: changed function: intel_gt_invalidate_tlbs +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +[ppc64le]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +--------------------------- + +Modifications: none + +commit c08a6dbfd89b0d7dfbc0726eeee3bb7289b59af8 +Author: Ian Kent +Date: Tue Nov 15 14:08:25 2022 +0800 + + pipe: Fix missing lock in pipe_resize_ring() + + Bugzilla: https://bugzilla.redhat.com/2141631 + CVE: CVE-2022-2959 + Y-Commit: 713162e02d3aca87567fc906879e972491ca045d + + O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141632 + Status: Linus + O-CVE: CVE-2022-2959 + + commit 189b0ddc245139af81198d1a3637cac74f96e13a + From: David Howells + Date: 2022-05-26 07:34:52 +0100 + + pipe: Fix missing lock in pipe_resize_ring() + + pipe_resize_ring() needs to take the pipe->rd_wait.lock spinlock to + prevent post_one_notification() from trying to insert into the ring + whilst the ring is being replaced. + + The occupancy check must be done after the lock is taken, and the lock + must be taken after the new ring is allocated. + + The bug can lead to an oops looking something like: + + BUG: KASAN: use-after-free in post_one_notification.isra.0+0x62e/0x840 + Read of size 4 at addr ffff88801cc72a70 by task poc/27196 + ... + Call Trace: + post_one_notification.isra.0+0x62e/0x840 + __post_watch_notification+0x3b7/0x650 + key_create_or_update+0xb8b/0xd20 + __do_sys_add_key+0x175/0x340 + __x64_sys_add_key+0xbe/0x140 + do_syscall_64+0x5c/0xc0 + entry_SYSCALL_64_after_hwframe+0x44/0xae + + Reported by Selim Enes Karaduman @Enesdex working with Trend Micro Zero + Day Initiative. + + Fixes: c73be61cede5 ("pipe: Add general notification queue support") + Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-17291 + Signed-off-by: David Howells + Signed-off-by: Linus Torvalds + + Signed-off-by: Ian Kent + Signed-off-by: Patrick Talbert + +Signed-off-by: Yannick Cote +--- + fs/pipe.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/fs/pipe.c b/fs/pipe.c +index 751d5b36c84b..4a1c6ef9493d 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -1244,30 +1244,33 @@ unsigned int round_pipe_size(unsigned long size) + + /* + * Resize the pipe ring to a number of slots. ++ * ++ * Note the pipe can be reduced in capacity, but only if the current ++ * occupancy doesn't exceed nr_slots; if it does, EBUSY will be ++ * returned instead. + */ + int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots) + { + struct pipe_buffer *bufs; + unsigned int head, tail, mask, n; + +- /* +- * We can shrink the pipe, if arg is greater than the ring occupancy. +- * Since we don't expect a lot of shrink+grow operations, just free and +- * allocate again like we would do for growing. If the pipe currently +- * contains more buffers than arg, then return busy. +- */ +- mask = pipe->ring_size - 1; +- head = pipe->head; +- tail = pipe->tail; +- n = pipe_occupancy(pipe->head, pipe->tail); +- if (nr_slots < n) +- return -EBUSY; +- + bufs = kcalloc(nr_slots, sizeof(*bufs), + GFP_KERNEL_ACCOUNT | __GFP_NOWARN); + if (unlikely(!bufs)) + return -ENOMEM; + ++ spin_lock_irq(&pipe->rd_wait.lock); ++ mask = pipe->ring_size - 1; ++ head = pipe->head; ++ tail = pipe->tail; ++ ++ n = pipe_occupancy(head, tail); ++ if (nr_slots < n) { ++ spin_unlock_irq(&pipe->rd_wait.lock); ++ kfree(bufs); ++ return -EBUSY; ++ } ++ + /* + * The pipe array wraps around, so just start the new one at zero + * and adjust the indices. +@@ -1299,6 +1302,8 @@ int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots) + pipe->tail = tail; + pipe->head = head; + ++ spin_unlock_irq(&pipe->rd_wait.lock); ++ + /* This might have made more room for writers */ + wake_up_interruptible(&pipe->wr_wait); + return 0; +-- +2.39.0 + + diff --git a/SOURCES/CVE-2022-2964.patch b/SOURCES/CVE-2022-2964.patch new file mode 100644 index 0000000..66fdeff --- /dev/null +++ b/SOURCES/CVE-2022-2964.patch @@ -0,0 +1,348 @@ +From 87f7a20da7834fef4fe45c42a10faeb3f1c07dbc Mon Sep 17 00:00:00 2001 +From: Yannick Cote +Date: Mon, 12 Dec 2022 12:13:31 -0500 +Subject: [KPATCH CVE-2022-2964] kpatch fixes for CVE-2022-2964 + +Kernels: +5.14.0-162.6.1.el9_1 + + +Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-9/-/merge_requests/11 +Approved-by: Joe Lawrence (@joe.lawrence) +Changes since last build: +[x86_64]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +intel_gt.o: changed function: intel_gt_invalidate_tlbs +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +[ppc64le]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +--------------------------- + +Modifications: none + +commit 6274d41609abb0959136a4a2ee687d79fa765a14 +Author: Jose Ignacio Tornos Martinez +Date: Tue Nov 15 17:07:42 2022 +0100 + + net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup + + Bugzilla: https://bugzilla.redhat.com/2142722 + CVE: CVE-2022-2964 + Y-Commit: 1851b951feb91882a180d1c4924d7f03389a9435 + + O-Bugzilla: https://bugzilla.redhat.com/2142723 + O-CVE: CVE-2022-2964 + + commit 57bc3d3ae8c14df3ceb4e17d26ddf9eeab304581 + Author: Jann Horn + Date: Wed Jan 26 14:14:52 2022 +0100 + + net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup + + ax88179_rx_fixup() contains several out-of-bounds accesses that can be + triggered by a malicious (or defective) USB device, in particular: + + - The metadata array (hdr_off..hdr_off+2*pkt_cnt) can be out of bounds, + causing OOB reads and (on big-endian systems) OOB endianness flips. + - A packet can overlap the metadata array, causing a later OOB + endianness flip to corrupt data used by a cloned SKB that has already + been handed off into the network stack. + - A packet SKB can be constructed whose tail is far beyond its end, + causing out-of-bounds heap data to be considered part of the SKB's + data. + + I have tested that this can be used by a malicious USB device to send a + bogus ICMPv6 Echo Request and receive an ICMPv6 Echo Reply in response + that contains random kernel heap data. + It's probably also possible to get OOB writes from this on a + little-endian system somehow - maybe by triggering skb_cow() via IP + options processing -, but I haven't tested that. + + Fixes: e2ca90c276e1 ("ax88179_178a: ASIX AX88179_178A USB 3.0/2.0 to gigabit ethernet adapter driver") + Cc: stable@kernel.org + Signed-off-by: Jann Horn + Signed-off-by: Greg Kroah-Hartman + + Signed-off-by: Jose Ignacio Tornos Martinez + + Signed-off-by: Patrick Talbert + +commit ed49211cd6a1a99bc1e3450fbafaf75865e11037 +Author: Jose Ignacio Tornos Martinez +Date: Wed Nov 16 12:43:01 2022 +0100 + + net: usb: ax88179_178a: Fix packet receiving + + Bugzilla: https://bugzilla.redhat.com/2142722 + CVE: CVE-2022-2964 + Y-Commit: c18d44fdacbbf489eb38e2db9b0ae66b4ad036dd + + O-Bugzilla: https://bugzilla.redhat.com/2142723 + O-CVE: CVE-2022-2964 + + commit f8ebb3ac881b17712e1d5967c97ab1806b16d3d6 + Author: Jose Alonso + Date: Tue Jun 28 12:13:02 2022 -0300 + + net: usb: ax88179_178a: Fix packet receiving + + This patch corrects packet receiving in ax88179_rx_fixup. + + - problem observed: + ifconfig shows allways a lot of 'RX Errors' while packets + are received normally. + + This occurs because ax88179_rx_fixup does not recognise properly + the usb urb received. + The packets are normally processed and at the end, the code exits + with 'return 0', generating RX Errors. + (pkt_cnt==-2 and ptk_hdr over field rx_hdr trying to identify + another packet there) + + This is a usb urb received by "tcpdump -i usbmon2 -X" on a + little-endian CPU: + 0x0000: eeee f8e3 3b19 87a0 94de 80e3 daac 0800 + ^ packet 1 start (pkt_len = 0x05ec) + ^^^^ IP alignment pseudo header + ^ ethernet packet start + last byte ethernet packet v + padding (8-bytes aligned) vvvv vvvv + 0x05e0: c92d d444 1420 8a69 83dd 272f e82b 9811 + 0x05f0: eeee f8e3 3b19 87a0 94de 80e3 daac 0800 + ... ^ packet 2 + 0x0be0: eeee f8e3 3b19 87a0 94de 80e3 daac 0800 + ... + 0x1130: 9d41 9171 8a38 0ec5 eeee f8e3 3b19 87a0 + ... + 0x1720: 8cfc 15ff 5e4c e85c eeee f8e3 3b19 87a0 + ... + 0x1d10: ecfa 2a3a 19ab c78c eeee f8e3 3b19 87a0 + ... + 0x2070: eeee f8e3 3b19 87a0 94de 80e3 daac 0800 + ... ^ packet 7 + 0x2120: 7c88 4ca5 5c57 7dcc 0d34 7577 f778 7e0a + 0x2130: f032 e093 7489 0740 3008 ec05 0000 0080 + ====1==== ====2==== + hdr_off ^ + pkt_len = 0x05ec ^^^^ + AX_RXHDR_*=0x00830 ^^^^ ^ + pkt_len = 0 ^^^^ + AX_RXHDR_DROP_ERR=0x80000000 ^^^^ ^ + 0x2140: 3008 ec05 0000 0080 3008 5805 0000 0080 + 0x2150: 3008 ec05 0000 0080 3008 ec05 0000 0080 + 0x2160: 3008 5803 0000 0080 3008 c800 0000 0080 + ===11==== ===12==== ===13==== ===14==== + 0x2170: 0000 0000 0e00 3821 + ^^^^ ^^^^ rx_hdr + ^^^^ pkt_cnt=14 + ^^^^ hdr_off=0x2138 + ^^^^ ^^^^ padding + + The dump shows that pkt_cnt is the number of entrys in the + per-packet metadata. It is "2 * packet count". + Each packet have two entrys. The first have a valid + value (pkt_len and AX_RXHDR_*) and the second have a + dummy-header 0x80000000 (pkt_len=0 with AX_RXHDR_DROP_ERR). + Why exists dummy-header for each packet?!? + My guess is that this was done probably to align the + entry for each packet to 64-bits and maintain compatibility + with old firmware. + There is also a padding (0x00000000) before the rx_hdr to + align the end of rx_hdr to 64-bit. + Note that packets have a alignment of 64-bits (8-bytes). + + This patch assumes that the dummy-header and the last + padding are optional. So it preserves semantics and + recognises the same valid packets as the current code. + + This patch was made using only the dumpfile information and + tested with only one device: + 0b95:1790 ASIX Electronics Corp. AX88179 Gigabit Ethernet + + Fixes: 57bc3d3ae8c1 ("net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup") + Fixes: e2ca90c276e1 ("ax88179_178a: ASIX AX88179_178A USB 3.0/2.0 to gigabit ethernet adapter driver") + Signed-off-by: Jose Alonso + Acked-by: Paolo Abeni + Link: https://lore.kernel.org/r/d6970bb04bf67598af4d316eaeb1792040b18cfd.camel@gmail.com + Signed-off-by: Paolo Abeni + + Signed-off-by: Jose Ignacio Tornos Martinez + + Signed-off-by: Patrick Talbert + +Signed-off-by: Yannick Cote +--- + drivers/net/usb/ax88179_178a.c | 113 +++++++++++++++++++++++++-------- + 1 file changed, 87 insertions(+), 26 deletions(-) + +diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c +index 5ed59d9dd631..5aa4e53a6d75 100644 +--- a/drivers/net/usb/ax88179_178a.c ++++ b/drivers/net/usb/ax88179_178a.c +@@ -1467,58 +1467,119 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + u16 hdr_off; + u32 *pkt_hdr; + +- /* This check is no longer done by usbnet */ +- if (skb->len < dev->net->hard_header_len) ++ /* At the end of the SKB, there's a header telling us how many packets ++ * are bundled into this buffer and where we can find an array of ++ * per-packet metadata (which contains elements encoded into u16). ++ */ ++ ++ /* SKB contents for current firmware: ++ * ++ * ... ++ * ++ * ++ * ... ++ * ++ * ++ * ++ * where: ++ * contains pkt_len bytes: ++ * 2 bytes of IP alignment pseudo header ++ * packet received ++ * contains 4 bytes: ++ * pkt_len and fields AX_RXHDR_* ++ * 0-7 bytes to terminate at ++ * 8 bytes boundary (64-bit). ++ * 4 bytes to make rx_hdr terminate at ++ * 8 bytes boundary (64-bit) ++ * contains 4 bytes: ++ * pkt_len=0 and AX_RXHDR_DROP_ERR ++ * contains 4 bytes: ++ * pkt_cnt and hdr_off (offset of ++ * ) ++ * ++ * pkt_cnt is number of entrys in the per-packet metadata. ++ * In current firmware there is 2 entrys per packet. ++ * The first points to the packet and the ++ * second is a dummy header. ++ * This was done probably to align fields in 64-bit and ++ * maintain compatibility with old firmware. ++ * This code assumes that and are ++ * optional. ++ */ ++ ++ if (skb->len < 4) + return 0; +- + skb_trim(skb, skb->len - 4); + rx_hdr = get_unaligned_le32(skb_tail_pointer(skb)); +- + pkt_cnt = (u16)rx_hdr; + hdr_off = (u16)(rx_hdr >> 16); ++ ++ if (pkt_cnt == 0) ++ return 0; ++ ++ /* Make sure that the bounds of the metadata array are inside the SKB ++ * (and in front of the counter at the end). ++ */ ++ if (pkt_cnt * 4 + hdr_off > skb->len) ++ return 0; + pkt_hdr = (u32 *)(skb->data + hdr_off); + +- while (pkt_cnt--) { ++ /* Packets must not overlap the metadata array */ ++ skb_trim(skb, hdr_off); ++ ++ for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) { ++ u16 pkt_len_plus_padd; + u16 pkt_len; + + le32_to_cpus(pkt_hdr); + pkt_len = (*pkt_hdr >> 16) & 0x1fff; ++ pkt_len_plus_padd = (pkt_len + 7) & 0xfff8; ++ ++ /* Skip dummy header used for alignment ++ */ ++ if (pkt_len == 0) ++ continue; ++ ++ if (pkt_len_plus_padd > skb->len) ++ return 0; + + /* Check CRC or runt packet */ +- if ((*pkt_hdr & AX_RXHDR_CRC_ERR) || +- (*pkt_hdr & AX_RXHDR_DROP_ERR)) { +- skb_pull(skb, (pkt_len + 7) & 0xFFF8); +- pkt_hdr++; ++ if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) || ++ pkt_len < 2 + ETH_HLEN) { ++ dev->net->stats.rx_errors++; ++ skb_pull(skb, pkt_len_plus_padd); + continue; + } + +- if (pkt_cnt == 0) { +- skb->len = pkt_len; ++ /* last packet */ ++ if (pkt_len_plus_padd == skb->len) { ++ skb_trim(skb, pkt_len); ++ + /* Skip IP alignment pseudo header */ + skb_pull(skb, 2); +- skb_set_tail_pointer(skb, skb->len); +- skb->truesize = pkt_len + sizeof(struct sk_buff); ++ ++ skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd); + ax88179_rx_checksum(skb, pkt_hdr); + return 1; + } + + ax_skb = skb_clone(skb, GFP_ATOMIC); +- if (ax_skb) { +- ax_skb->len = pkt_len; +- /* Skip IP alignment pseudo header */ +- skb_pull(ax_skb, 2); +- skb_set_tail_pointer(ax_skb, ax_skb->len); +- ax_skb->truesize = pkt_len + sizeof(struct sk_buff); +- ax88179_rx_checksum(ax_skb, pkt_hdr); +- usbnet_skb_return(dev, ax_skb); +- } else { ++ if (!ax_skb) + return 0; +- } ++ skb_trim(ax_skb, pkt_len); ++ ++ /* Skip IP alignment pseudo header */ ++ skb_pull(ax_skb, 2); ++ ++ skb->truesize = pkt_len_plus_padd + ++ SKB_DATA_ALIGN(sizeof(struct sk_buff)); ++ ax88179_rx_checksum(ax_skb, pkt_hdr); ++ usbnet_skb_return(dev, ax_skb); + +- skb_pull(skb, (pkt_len + 7) & 0xFFF8); +- pkt_hdr++; ++ skb_pull(skb, pkt_len_plus_padd); + } +- return 1; ++ ++ return 0; + } + + static struct sk_buff * +-- +2.39.0 + + diff --git a/SOURCES/CVE-2022-4139.patch b/SOURCES/CVE-2022-4139.patch new file mode 100644 index 0000000..c5e49ac --- /dev/null +++ b/SOURCES/CVE-2022-4139.patch @@ -0,0 +1,98 @@ +From 23b83d20ee925f9c6fd81e24e56081f35fec4c7c Mon Sep 17 00:00:00 2001 +From: Yannick Cote +Date: Mon, 12 Dec 2022 18:57:27 -0500 +Subject: [KPATCH CVE-2022-4139] kpatch fixes for CVE-2022-4139 + +Kernels: +5.14.0-162.6.1.el9_1 + + +Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-9/-/merge_requests/13 +Approved-by: Joe Lawrence (@joe.lawrence) +Changes since last build: +[x86_64]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +intel_gt.o: changed function: intel_gt_invalidate_tlbs +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +[ppc64le]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +--------------------------- + +Modifications: none + +commit 77eddcf995483fabb6d7c81bef19dc69c697b16e +Author: Wander Lairson Costa +Date: Thu Dec 1 10:24:37 2022 -0300 + + drm/i915: fix TLB invalidation for Gen12 video and compute engines + + Bugzilla: https://bugzilla.redhat.com/2148152 + CVE: CVE-2022-4139 + Y-Commit: 98336d51bfacb10fd4b73432beac0fe95d73bf7c + + O-Bugzilla: https://bugzilla.redhat.com/2148153 + O-CVE: CVE-2022-4139 + + commit 04aa64375f48a5d430b5550d9271f8428883e550 + Author: Andrzej Hajda + Date: Mon Nov 14 11:38:24 2022 +0100 + + drm/i915: fix TLB invalidation for Gen12 video and compute engines + + In case of Gen12 video and compute engines, TLB_INV registers are masked - + to modify one bit, corresponding bit in upper half of the register must + be enabled, otherwise nothing happens. + + CVE: CVE-2022-4139 + Suggested-by: Chris Wilson + Signed-off-by: Andrzej Hajda + Acked-by: Daniel Vetter + Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") + Cc: stable@vger.kernel.org + Signed-off-by: Linus Torvalds + + Signed-off-by: Wander Lairson Costa + Signed-off-by: Patrick Talbert + +Signed-off-by: Yannick Cote +--- + drivers/gpu/drm/i915/gt/intel_gt.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c +index f4375479e6f0..1cb9971759d2 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt.c ++++ b/drivers/gpu/drm/i915/gt/intel_gt.c +@@ -1021,6 +1021,11 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) + if (!i915_mmio_reg_offset(rb.reg)) + continue; + ++ if (GRAPHICS_VER(i915) == 12 && (engine->class == VIDEO_DECODE_CLASS || ++ engine->class == VIDEO_ENHANCEMENT_CLASS || ++ engine->class == COMPUTE_CLASS)) ++ rb.bit = _MASKED_BIT_ENABLE(rb.bit); ++ + intel_uncore_write_fw(uncore, rb.reg, rb.bit); + } + +-- +2.39.0 + + diff --git a/SOURCES/CVE-2022-43945.patch b/SOURCES/CVE-2022-43945.patch new file mode 100644 index 0000000..064ffa5 --- /dev/null +++ b/SOURCES/CVE-2022-43945.patch @@ -0,0 +1,510 @@ +From 279997974099abbc4a1ac28ed243f62bc039cf65 Mon Sep 17 00:00:00 2001 +From: Yannick Cote +Date: Mon, 12 Dec 2022 19:34:33 -0500 +Subject: [KPATCH CVE-2022-43945] kpatch fixes for CVE-2022-43945 + +Kernels: +5.14.0-162.6.1.el9_1 + + +Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-9/-/merge_requests/14 +Approved-by: Joe Lawrence (@joe.lawrence) +Changes since last build: +[x86_64]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +intel_gt.o: changed function: intel_gt_invalidate_tlbs +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +[ppc64le]: +ax88179_178a.o: changed function: ax88179_rx_fixup +callback_xdr.o: changed function: nfs_callback_dispatch +nfs3proc.o: changed function: nfsd3_init_dirlist_pages +nfs3proc.o: changed function: nfsd3_proc_read +nfsproc.o: changed function: nfsd_proc_read +nfsproc.o: changed function: nfsd_proc_readdir +nfssvc.o: changed function: nfsd_dispatch +pipe.o: changed function: pipe_resize_ring +svc.o: changed function: nlmsvc_dispatch + +--------------------------- + +Modifications: +- Take out modifications to header routines and roll new kpatch versions + of them to be included at all call sites. +- Wrapped new routines: svcxdr_init_decode(), svcxdr_init_encode() + +commit a7e335af244128a81a936cfc8d23509e29fc0b72 +Author: Scott Mayhew +Date: Thu Nov 10 13:41:53 2022 -0500 + + SUNRPC: Fix svcxdr_init_decode's end-of-buffer calculation + + Bugzilla: https://bugzilla.redhat.com/2141769 + CVE: CVE-2022-43945 + Y-Commit: 63e941917cd28dff8b33ce5c8658aac3b7dc5c75 + + O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141770 + O-CVE: CVE-2022-43945 + + commit 90bfc37b5ab91c1a6165e3e5cfc49bf04571b762 + Author: Chuck Lever + Date: Thu Sep 1 15:09:53 2022 -0400 + + SUNRPC: Fix svcxdr_init_decode's end-of-buffer calculation + + Ensure that stream-based argument decoding can't go past the actual + end of the receive buffer. xdr_init_decode's calculation of the + value of xdr->end over-estimates the end of the buffer because the + Linux kernel RPC server code does not remove the size of the RPC + header from rqstp->rq_arg before calling the upper layer's + dispatcher. + + The server-side still uses the svc_getnl() macros to decode the + RPC call header. These macros reduce the length of the head iov + but do not update the total length of the message in the buffer + (buf->len). + + A proper fix for this would be to replace the use of svc_getnl() and + friends in the RPC header decoder, but that would be a large and + invasive change that would be difficult to backport. + + Fixes: 5191955d6fc6 ("SUNRPC: Prepare for xdr_stream-style decoding on the server-side") + Reviewed-by: Jeff Layton + Signed-off-by: Chuck Lever + + Signed-off-by: Scott Mayhew + Signed-off-by: Patrick Talbert + +commit 8d718c29ff4601ff5ca279421f7e2187a38d856f +Author: Scott Mayhew +Date: Thu Nov 10 13:41:52 2022 -0500 + + SUNRPC: Fix svcxdr_init_encode's buflen calculation + + Bugzilla: https://bugzilla.redhat.com/2141769 + CVE: CVE-2022-43945 + Y-Commit: 02ef2175406bbe8753f6ff08d3dae4d927f88c69 + + O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141770 + O-CVE: CVE-2022-43945 + + commit 1242a87da0d8cd2a428e96ca68e7ea899b0f4624 + Author: Chuck Lever + Date: Thu Sep 1 15:09:59 2022 -0400 + + SUNRPC: Fix svcxdr_init_encode's buflen calculation + + Commit 2825a7f90753 ("nfsd4: allow encoding across page boundaries") + added an explicit computation of the remaining length in the rq_res + XDR buffer. + + The computation appears to suffer from an "off-by-one" bug. Because + buflen is too large by one page, XDR encoding can run off the end of + the send buffer by eventually trying to use the struct page address + in rq_page_end, which always contains NULL. + + Fixes: bddfdbcddbe2 ("NFSD: Extract the svcxdr_init_encode() helper") + Reviewed-by: Jeff Layton + Signed-off-by: Chuck Lever + + Signed-off-by: Scott Mayhew + Signed-off-by: Patrick Talbert + +commit b4648565ad97ee05956cabbb56d89f29932e7a02 +Author: Scott Mayhew +Date: Thu Nov 10 13:41:52 2022 -0500 + + NFSD: Protect against send buffer overflow in NFSv2 READDIR + + Bugzilla: https://bugzilla.redhat.com/2141769 + CVE: CVE-2022-43945 + Y-Commit: 13ed52506cc7713e48ae64bd11ba867295aed137 + + O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141770 + O-CVE: CVE-2022-43945 + + commit 00b4492686e0497fdb924a9d4c8f6f99377e176c + Author: Chuck Lever + Date: Thu Sep 1 15:10:05 2022 -0400 + + NFSD: Protect against send buffer overflow in NFSv2 READDIR + + Restore the previous limit on the @count argument to prevent a + buffer overflow attack. + + Fixes: 53b1119a6e50 ("NFSD: Fix READDIR buffer overflow") + Signed-off-by: Chuck Lever + Reviewed-by: Jeff Layton + Signed-off-by: Chuck Lever + + Signed-off-by: Scott Mayhew + Signed-off-by: Patrick Talbert + +commit 08fca21e5fe53bd2e0ef7ddbe9cb302ccedeba45 +Author: Scott Mayhew +Date: Thu Nov 10 13:41:52 2022 -0500 + + NFSD: Protect against send buffer overflow in NFSv3 READDIR + + Bugzilla: https://bugzilla.redhat.com/2141769 + CVE: CVE-2022-43945 + Y-Commit: 2a688c7c62dce0bc5e4377d82d830fe2955503cc + + O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141770 + O-CVE: CVE-2022-43945 + + commit 640f87c190e0d1b2a0fcb2ecf6d2cd53b1c41991 + Author: Chuck Lever + Date: Thu Sep 1 15:10:12 2022 -0400 + + NFSD: Protect against send buffer overflow in NFSv3 READDIR + + Since before the git era, NFSD has conserved the number of pages + held by each nfsd thread by combining the RPC receive and send + buffers into a single array of pages. This works because there are + no cases where an operation needs a large RPC Call message and a + large RPC Reply message at the same time. + + Once an RPC Call has been received, svc_process() updates + svc_rqst::rq_res to describe the part of rq_pages that can be + used for constructing the Reply. This means that the send buffer + (rq_res) shrinks when the received RPC record containing the RPC + Call is large. + + A client can force this shrinkage on TCP by sending a correctly- + formed RPC Call header contained in an RPC record that is + excessively large. The full maximum payload size cannot be + constructed in that case. + + Thanks to Aleksi Illikainen and Kari Hulkko for uncovering this + issue. + + Reported-by: Ben Ronallo + Cc: + Signed-off-by: Chuck Lever + Reviewed-by: Jeff Layton + Signed-off-by: Chuck Lever + + Signed-off-by: Scott Mayhew + Signed-off-by: Patrick Talbert + +commit 5665aff4c12502c39f372548d1be622d99ad2252 +Author: Scott Mayhew +Date: Thu Nov 10 13:41:52 2022 -0500 + + NFSD: Protect against send buffer overflow in NFSv2 READ + + Bugzilla: https://bugzilla.redhat.com/2141769 + CVE: CVE-2022-43945 + Y-Commit: 385d7c5a859c93544e7aad1dfe8e955f2035ab5f + + O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141770 + O-CVE: CVE-2022-43945 + + commit 401bc1f90874280a80b93f23be33a0e7e2d1f912 + Author: Chuck Lever + Date: Thu Sep 1 15:10:18 2022 -0400 + + NFSD: Protect against send buffer overflow in NFSv2 READ + + Since before the git era, NFSD has conserved the number of pages + held by each nfsd thread by combining the RPC receive and send + buffers into a single array of pages. This works because there are + no cases where an operation needs a large RPC Call message and a + large RPC Reply at the same time. + + Once an RPC Call has been received, svc_process() updates + svc_rqst::rq_res to describe the part of rq_pages that can be + used for constructing the Reply. This means that the send buffer + (rq_res) shrinks when the received RPC record containing the RPC + Call is large. + + A client can force this shrinkage on TCP by sending a correctly- + formed RPC Call header contained in an RPC record that is + excessively large. The full maximum payload size cannot be + constructed in that case. + + Cc: + Signed-off-by: Chuck Lever + Reviewed-by: Jeff Layton + Signed-off-by: Chuck Lever + + Signed-off-by: Scott Mayhew + Signed-off-by: Patrick Talbert + +commit f036edb9860c89970440f8d524831b11afd399fb +Author: Scott Mayhew +Date: Thu Nov 10 13:41:52 2022 -0500 + + NFSD: Protect against send buffer overflow in NFSv3 READ + + Bugzilla: https://bugzilla.redhat.com/2141769 + CVE: CVE-2022-43945 + Y-Commit: 45f0034c12711e534531b23c15c04aa060c9ed47 + + O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141770 + O-CVE: CVE-2022-43945 + + commit fa6be9cc6e80ec79892ddf08a8c10cabab9baf38 + Author: Chuck Lever + Date: Thu Sep 1 15:10:24 2022 -0400 + + NFSD: Protect against send buffer overflow in NFSv3 READ + + Since before the git era, NFSD has conserved the number of pages + held by each nfsd thread by combining the RPC receive and send + buffers into a single array of pages. This works because there are + no cases where an operation needs a large RPC Call message and a + large RPC Reply at the same time. + + Once an RPC Call has been received, svc_process() updates + svc_rqst::rq_res to describe the part of rq_pages that can be + used for constructing the Reply. This means that the send buffer + (rq_res) shrinks when the received RPC record containing the RPC + Call is large. + + A client can force this shrinkage on TCP by sending a correctly- + formed RPC Call header contained in an RPC record that is + excessively large. The full maximum payload size cannot be + constructed in that case. + + Cc: + Signed-off-by: Chuck Lever + Reviewed-by: Jeff Layton + Signed-off-by: Chuck Lever + + Signed-off-by: Scott Mayhew + Signed-off-by: Patrick Talbert + +Signed-off-by: Yannick Cote +--- + fs/lockd/svc.c | 6 ++- + fs/nfs/callback_xdr.c | 6 ++- + fs/nfsd/nfs3proc.c | 11 +++--- + fs/nfsd/nfsproc.c | 6 +-- + fs/nfsd/nfssvc.c | 6 ++- + include/linux/kpatch_cve_2022_43945.h | 53 +++++++++++++++++++++++++++ + 6 files changed, 74 insertions(+), 14 deletions(-) + create mode 100644 include/linux/kpatch_cve_2022_43945.h + +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index b220e1b91726..e8b6e09af323 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -768,6 +768,8 @@ static void __exit exit_nlm(void) + module_init(init_nlm); + module_exit(exit_nlm); + ++#include ++ + /** + * nlmsvc_dispatch - Process an NLM Request + * @rqstp: incoming request +@@ -781,7 +783,7 @@ static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp) + { + const struct svc_procedure *procp = rqstp->rq_procinfo; + +- svcxdr_init_decode(rqstp); ++ kpatch_cve_2022_43945_svcxdr_init_decode(rqstp); + if (!procp->pc_decode(rqstp, &rqstp->rq_arg_stream)) + goto out_decode_err; + +@@ -791,7 +793,7 @@ static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp) + if (*statp != rpc_success) + return 1; + +- svcxdr_init_encode(rqstp); ++ kpatch_cve_2022_43945_svcxdr_init_encode(rqstp); + if (!procp->pc_encode(rqstp, &rqstp->rq_res_stream)) + goto out_encode_err; + +diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c +index a67c41ec545f..9438f91b9c2d 100644 +--- a/fs/nfs/callback_xdr.c ++++ b/fs/nfs/callback_xdr.c +@@ -983,13 +983,15 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp) + return rpc_success; + } + ++#include ++ + static int + nfs_callback_dispatch(struct svc_rqst *rqstp, __be32 *statp) + { + const struct svc_procedure *procp = rqstp->rq_procinfo; + +- svcxdr_init_decode(rqstp); +- svcxdr_init_encode(rqstp); ++ kpatch_cve_2022_43945_svcxdr_init_decode(rqstp); ++ kpatch_cve_2022_43945_svcxdr_init_encode(rqstp); + + *statp = procp->pc_func(rqstp); + return 1; +diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c +index 9d2667a8dbd1..e0eb8b7acec8 100644 +--- a/fs/nfsd/nfs3proc.c ++++ b/fs/nfsd/nfs3proc.c +@@ -147,7 +147,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp) + { + struct nfsd3_readargs *argp = rqstp->rq_argp; + struct nfsd3_readres *resp = rqstp->rq_resp; +- u32 max_blocksize = svc_max_payload(rqstp); + unsigned int len; + int v; + +@@ -156,7 +155,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp) + (unsigned long) argp->count, + (unsigned long long) argp->offset); + +- argp->count = min_t(u32, argp->count, max_blocksize); ++ argp->count = min_t(u32, argp->count, svc_max_payload(rqstp)); ++ argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen); + if (argp->offset > (u64)OFFSET_MAX) + argp->offset = (u64)OFFSET_MAX; + if (argp->offset + argp->count > (u64)OFFSET_MAX) +@@ -554,13 +554,14 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp, + { + struct xdr_buf *buf = &resp->dirlist; + struct xdr_stream *xdr = &resp->xdr; +- +- count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp)); ++ unsigned int sendbuf = min_t(unsigned int, rqstp->rq_res.buflen, ++ svc_max_payload(rqstp)); + + memset(buf, 0, sizeof(*buf)); + + /* Reserve room for the NULL ptr & eof flag (-2 words) */ +- buf->buflen = count - XDR_UNIT * 2; ++ buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), sendbuf); ++ buf->buflen -= XDR_UNIT * 2; + buf->pages = rqstp->rq_next_page; + rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; + +diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c +index de282f3273c5..6c15d4ac52e8 100644 +--- a/fs/nfsd/nfsproc.c ++++ b/fs/nfsd/nfsproc.c +@@ -182,6 +182,7 @@ nfsd_proc_read(struct svc_rqst *rqstp) + argp->count, argp->offset); + + argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2); ++ argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen); + + v = 0; + len = argp->count; +@@ -561,12 +562,11 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp, + struct xdr_buf *buf = &resp->dirlist; + struct xdr_stream *xdr = &resp->xdr; + +- count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp)); +- + memset(buf, 0, sizeof(*buf)); + + /* Reserve room for the NULL ptr & eof flag (-2 words) */ +- buf->buflen = count - XDR_UNIT * 2; ++ buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), (u32)PAGE_SIZE); ++ buf->buflen -= XDR_UNIT * 2; + buf->pages = rqstp->rq_next_page; + rqstp->rq_next_page++; + +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index 80431921e5d7..125f490147df 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -990,6 +990,8 @@ nfsd(void *vrqstp) + return 0; + } + ++#include ++ + /** + * nfsd_dispatch - Process an NFS or NFSACL Request + * @rqstp: incoming request +@@ -1011,7 +1013,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) + */ + rqstp->rq_cachetype = proc->pc_cachetype; + +- svcxdr_init_decode(rqstp); ++ kpatch_cve_2022_43945_svcxdr_init_decode(rqstp); + if (!proc->pc_decode(rqstp, &rqstp->rq_arg_stream)) + goto out_decode_err; + +@@ -1028,7 +1030,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) + * Need to grab the location to store the status, as + * NFSv4 does some encoding while processing + */ +- svcxdr_init_encode(rqstp); ++ kpatch_cve_2022_43945_svcxdr_init_encode(rqstp); + + *statp = proc->pc_func(rqstp); + if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags)) +diff --git a/include/linux/kpatch_cve_2022_43945.h b/include/linux/kpatch_cve_2022_43945.h +new file mode 100644 +index 000000000000..d52392485a57 +--- /dev/null ++++ b/include/linux/kpatch_cve_2022_43945.h +@@ -0,0 +1,53 @@ ++#ifndef _KPATCH_CVE_2022_43945_H ++#define _KPATCH_CVE_2022_43945_H ++ ++/* ++ * svcxdr_init_decode - Prepare an xdr_stream for Call decoding ++ * @rqstp: controlling server RPC transaction context ++ * ++ * This function currently assumes the RPC header in rq_arg has ++ * already been decoded. Upon return, xdr->p points to the ++ * location of the upper layer header. ++ */ ++static inline void kpatch_cve_2022_43945_svcxdr_init_decode(struct svc_rqst *rqstp) ++{ ++ struct xdr_stream *xdr = &rqstp->rq_arg_stream; ++ struct xdr_buf *buf = &rqstp->rq_arg; ++ struct kvec *argv = buf->head; ++ ++ /* ++ * svc_getnl() and friends do not keep the xdr_buf's ::len ++ * field up to date. Refresh that field before initializing ++ * the argument decoding stream. ++ */ ++ buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len; ++ ++ xdr_init_decode(xdr, buf, argv->iov_base, NULL); ++ xdr_set_scratch_page(xdr, rqstp->rq_scratch_page); ++} ++ ++/* ++ * svcxdr_init_encode - Prepare an xdr_stream for svc Reply encoding ++ * @rqstp: controlling server RPC transaction context ++ * ++ */ ++static inline void kpatch_cve_2022_43945_svcxdr_init_encode(struct svc_rqst *rqstp) ++{ ++ struct xdr_stream *xdr = &rqstp->rq_res_stream; ++ struct xdr_buf *buf = &rqstp->rq_res; ++ struct kvec *resv = buf->head; ++ ++ xdr_reset_scratch_buffer(xdr); ++ ++ xdr->buf = buf; ++ xdr->iov = resv; ++ xdr->p = resv->iov_base + resv->iov_len; ++ xdr->end = resv->iov_base + PAGE_SIZE - rqstp->rq_auth_slack; ++ buf->len = resv->iov_len; ++ xdr->page_ptr = buf->pages - 1; ++ buf->buflen = PAGE_SIZE * (rqstp->rq_page_end - buf->pages); ++ buf->buflen -= rqstp->rq_auth_slack; ++ xdr->rqst = NULL; ++} ++ ++#endif /* _KPATCH_CVE_2022_43945_H */ +-- +2.39.0 + + diff --git a/SOURCES/v0.9.7-backport-MR-1314-create-diff-object-fix-__UNI.patch b/SOURCES/v0.9.7-backport-MR-1314-create-diff-object-fix-__UNI.patch new file mode 100644 index 0000000..0cef2c1 --- /dev/null +++ b/SOURCES/v0.9.7-backport-MR-1314-create-diff-object-fix-__UNI.patch @@ -0,0 +1,77 @@ +From c351828bf35121628461095eeb25ea2152e98d38 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Mon, 21 Nov 2022 19:32:18 -0800 +Subject: [PATCH] v0.9.7 backport: MR!1314 ("create-diff-object: fix + __UNIQUE_ID() variable correlation") + +commit 901445a54fcecbd6852b79878e67153c5048602e +Author: Josh Poimboeuf +Date: Mon Nov 21 19:32:18 2022 -0800 + + create-diff-object: fix __UNIQUE_ID() variable correlation + + kpatch_mangled_strcmp() only ignores the digits after the period, but in + the case of __UNIQUE_ID(), the symbol names have random digits before + the period due to the use of `__COUNTER__`. Make sure such symbols are + properly correlated. + + Signed-off-by: Josh Poimboeuf + +Signed-off-by: Yannick Cote +--- + kpatch-build/create-diff-object.c | 32 +++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index 360441111c5e..7106b67cfd25 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -396,6 +396,35 @@ static bool has_digit_tail(char *tail) + return false; + } + ++/* ++ * Hack for __UNIQUE_ID(). The following should match: ++ * ++ * __UNIQUE_ID_ddebug1131.186 ++ * __UNIQUE_ID_ddebug1132.187 ++ */ ++static int __kpatch_unique_id_strcmp(char *s1, char *s2) ++{ ++ /* match '__UNIQUE_ID_ddebug' */ ++ while (*s1 == *s2) { ++ if (!*s1) ++ return 0; ++ s1++; ++ s2++; ++ } ++ ++ /* skip digits before '.' or EOL */ ++ while (isdigit(*s1)) ++ s1++; ++ while (isdigit(*s2)) ++ s2++; ++ ++ if ((!*s1 || has_digit_tail(s1)) && ++ (!*s2 || has_digit_tail(s2))) ++ return 0; ++ ++ return 1; ++} ++ + /* + * This is like strcmp, but for gcc-mangled symbols. It skips the comparison + * of any substring which consists of '.' followed by any number of digits. +@@ -409,6 +438,9 @@ static int kpatch_mangled_strcmp(char *s1, char *s2) + if (strstr(s1, ".str1.")) + return strcmp(s1, s2); + ++ if (!strncmp(s1, "__UNIQUE_ID_", 12)) ++ return __kpatch_unique_id_strcmp(s1, s2); ++ + while (*s1 == *s2) { + if (!*s1) + return 0; +-- +2.38.1 + diff --git a/SOURCES/v0.9.7-backport-MR-1315-Static-call-fixes.patch b/SOURCES/v0.9.7-backport-MR-1315-Static-call-fixes.patch new file mode 100644 index 0000000..58f2e3f --- /dev/null +++ b/SOURCES/v0.9.7-backport-MR-1315-Static-call-fixes.patch @@ -0,0 +1,529 @@ +From 358743e6d8748510f4c9a71511d7ceea7c72f7aa Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Mon, 21 Nov 2022 19:23:07 -0800 +Subject: [PATCH] v0.9.7 backport: MR!1315 ("Static call fixes") + +commit 87ad96760a3af0db294d44865dfa1703f57f5595 +Author: Josh Poimboeuf +Date: Mon Nov 21 19:23:07 2022 -0800 + + create-diff-object: fix s390 special_section initializer spacing + + Align the s390 special_section initializers to improve readability and + for consistency with the rest. + + Signed-off-by: Josh Poimboeuf + +commit 56bd8c4d0da1634f8549e7269f77a53e9d936a57 +Author: Josh Poimboeuf +Date: Mon Nov 21 19:27:23 2022 -0800 + + create-diff-object: refactor jump label filtering + + Convert the hard-coded should_keep_jump_label() to a proper callback, + since static calls will need a similar filter. + + Signed-off-by: Josh Poimboeuf + +commit f83218ad12a2d9e20d99d379c78974a576aa558c +Author: Josh Poimboeuf +Date: Mon Nov 21 19:29:53 2022 -0800 + + create-diff-object: detect unsupported static calls + + Similar to jump labels, static calls aren't supported when the static + call key was originally defined in a module rather than in vmlinux. + Detect those cases and either remove them (in the case of tracepoints) + or error out. + + Signed-off-by: Josh Poimboeuf + +commit ab2397c03e31f0f697aa8bf943d70b4e5a7def54 +Author: Josh Poimboeuf +Date: Mon Nov 21 19:41:30 2022 -0800 + + kpatch-macros: add KPATCH_STATIC_CALL() + + Signed-off-by: Josh Poimboeuf + +commit 92c178b6a30a827c48db46ff4238501ec406a28e +Author: Josh Poimboeuf +Date: Tue Nov 22 12:53:09 2022 -0800 + + create-diff-object: use errx() instead of err() + + Otherwise on recent distros it appends the errno to the error message, + like: + + create-diff-object: ERROR: x86.o: kpatch_regenerate_special_section: 2633: Found 1 unsupported static call(s) in the patched code. Use KPATCH_STATIC_CALL() instead.: Success + + which is not what we want in most cases. + + Signed-off-by: Josh Poimboeuf + +Signed-off-by: Yannick Cote +--- + kmod/patch/kpatch-macros.h | 11 + + kpatch-build/create-diff-object.c | 328 ++++++++++++++++++------------ + kpatch-build/log.h | 2 +- + 3 files changed, 211 insertions(+), 130 deletions(-) + +diff --git a/kmod/patch/kpatch-macros.h b/kmod/patch/kpatch-macros.h +index 8e09702ea001..b797838849ca 100644 +--- a/kmod/patch/kpatch-macros.h ++++ b/kmod/patch/kpatch-macros.h +@@ -141,4 +141,15 @@ struct kpatch_post_unpatch_callback { + printk(_fmt, ## __VA_ARGS__); \ + }) + ++/* ++ * KPATCH_STATIC_CALL macro ++ * ++ * Replace usages of static_call() with this macro, when create-diff-object ++ * recommends it due to the original static call key living in a module. ++ * ++ * This converts the static call to a regular indirect call. ++ */ ++#define KPATCH_STATIC_CALL(name) \ ++ ((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func)) ++ + #endif /* __KPATCH_MACROS_H_ */ +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index 7106b67cfd25..ddaa9b44f11e 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -56,7 +56,7 @@ + #define DIFF_FATAL(format, ...) \ + ({ \ + fprintf(stderr, "ERROR: %s: " format "\n", childobj, ##__VA_ARGS__); \ +- err(EXIT_STATUS_DIFF_FATAL, "unreconcilable difference"); \ ++ errx(EXIT_STATUS_DIFF_FATAL, "unreconcilable difference"); \ + }) + + char *childobj; +@@ -71,6 +71,8 @@ enum loglevel loglevel = NORMAL; + + bool KLP_ARCH; + ++int jump_label_errors, static_call_errors; ++ + /******************* + * Data structures + * ****************/ +@@ -78,6 +80,9 @@ struct special_section { + char *name; + enum architecture arch; + int (*group_size)(struct kpatch_elf *kelf, int offset); ++ bool (*group_filter)(struct lookup_table *lookup, ++ struct section *relasec, unsigned int offset, ++ unsigned int size); + }; + + /************* +@@ -2215,6 +2220,169 @@ static int fixup_group_size(struct kpatch_elf *kelf, int offset) + return (int)(rela->addend - offset); + } + ++static bool jump_table_group_filter(struct lookup_table *lookup, ++ struct section *relasec, ++ unsigned int group_offset, ++ unsigned int group_size) ++{ ++ struct rela *code = NULL, *key = NULL, *rela; ++ bool tracepoint = false, dynamic_debug = false; ++ struct lookup_result symbol; ++ int i = 0; ++ ++ /* ++ * Here we hard-code knowledge about the contents of the jump_entry ++ * struct. It has three fields: code, target, and key. Each field has ++ * a relocation associated with it. ++ */ ++ list_for_each_entry(rela, &relasec->relas, list) { ++ if (rela->offset >= group_offset && ++ rela->offset < group_offset + group_size) { ++ if (i == 0) ++ code = rela; ++ else if (i == 2) ++ key = rela; ++ i++; ++ } ++ } ++ ++ if (i != 3 || !key || !code) ++ ERROR("BUG: __jump_table has an unexpected format"); ++ ++ if (!strncmp(key->sym->name, "__tracepoint_", 13)) ++ tracepoint = true; ++ ++ if (is_dynamic_debug_symbol(key->sym)) ++ dynamic_debug = true; ++ ++ if (KLP_ARCH) { ++ /* ++ * On older kernels (with .klp.arch support), jump labels ++ * aren't supported at all. Error out when they occur in a ++ * replacement function, with the exception of tracepoints and ++ * dynamic debug printks. An inert tracepoint or printk is ++ * harmless enough, but a broken jump label can cause ++ * unexpected behavior. ++ */ ++ if (tracepoint || dynamic_debug) ++ return false; ++ ++ /* ++ * This will be upgraded to an error after all jump labels have ++ * been reported. ++ */ ++ log_normal("Found a jump label at %s()+0x%lx, using key %s. Jump labels aren't supported with this kernel. Use static_key_enabled() instead.\n", ++ code->sym->name, code->addend, key->sym->name); ++ jump_label_errors++; ++ return false; ++ } ++ ++ /* ++ * On newer (5.8+) kernels, jump labels are supported in the case where ++ * the corresponding static key lives in vmlinux. That's because such ++ * kernels apply vmlinux-specific .klp.rela sections at the same time ++ * (in the klp module load) as normal relas, before jump label init. ++ * On the other hand, jump labels based on static keys which are ++ * defined in modules aren't supported, because late module patching ++ * can result in the klp relas getting applied *after* the klp module's ++ * jump label init. ++ */ ++ ++ if (lookup_symbol(lookup, key->sym, &symbol) && ++ strcmp(symbol.objname, "vmlinux")) { ++ ++ /* The static key lives in a module -- not supported */ ++ ++ /* Inert tracepoints and dynamic debug printks are harmless */ ++ if (tracepoint || dynamic_debug) ++ return false; ++ ++ /* ++ * This will be upgraded to an error after all jump label ++ * errors have been reported. ++ */ ++ log_normal("Found a jump label at %s()+0x%lx, using key %s, which is defined in a module. Use static_key_enabled() instead.\n", ++ code->sym->name, code->addend, key->sym->name); ++ jump_label_errors++; ++ return false; ++ } ++ ++ /* The static key lives in vmlinux or the patch module itself */ ++ ++ /* ++ * If the jump label key lives in the '__dyndbg' section, make sure ++ * the section gets included, because we don't use klp relocs for ++ * dynamic debug symbols. For an example of such a key, see ++ * DYNAMIC_DEBUG_BRANCH(). ++ */ ++ if (dynamic_debug) ++ kpatch_include_symbol(key->sym); ++ ++ return true; ++} ++ ++static bool static_call_sites_group_filter(struct lookup_table *lookup, ++ struct section *relasec, ++ unsigned int group_offset, ++ unsigned int group_size) ++{ ++ struct rela *code = NULL, *key = NULL, *rela; ++ bool tracepoint = false; ++ struct lookup_result symbol; ++ int i = 0; ++ ++ /* ++ * Here we hard-code knowledge about the contents of the jump_entry ++ * struct. It has three fields: code, target, and key. Each field has ++ * a relocation associated with it. ++ */ ++ list_for_each_entry(rela, &relasec->relas, list) { ++ if (rela->offset >= group_offset && ++ rela->offset < group_offset + group_size) { ++ if (i == 0) ++ code = rela; ++ else if (i == 1) ++ key = rela; ++ i++; ++ } ++ } ++ ++ if (i != 2 || !key || !code) ++ ERROR("BUG: .static_call_sites has an unexpected format"); ++ ++ if (!strncmp(key->sym->name, "__SCK__tp_func_", 15)) ++ tracepoint = true; ++ ++ /* ++ * Static calls are only supported in the case where the corresponding ++ * static call key lives in vmlinux (see explanation in ++ * jump_table_group_filter). ++ */ ++ ++ if (lookup_symbol(lookup, key->sym, &symbol) && ++ strcmp(symbol.objname, "vmlinux")) { ++ ++ /* The key lives in a module -- not supported */ ++ ++ /* Inert tracepoints are harmless */ ++ if (tracepoint) ++ return false; ++ ++ /* ++ * This will be upgraded to an error after all static call ++ * errors have been reported. ++ */ ++ log_normal("Found a static call at %s()+0x%lx, using key %s, which is defined in a module. Use KPATCH_STATIC_CALL() instead.\n", ++ code->sym->name, code->addend, key->sym->name); ++ static_call_errors++; ++ return false; ++ } ++ ++ /* The key lives in vmlinux or the patch module itself */ ++ return true; ++} ++ ++ + static struct special_section special_sections[] = { + { + .name = "__bug_table", +@@ -2235,6 +2403,7 @@ static struct special_section special_sections[] = { + .name = "__jump_table", + .arch = X86_64 | PPC64 | S390, + .group_size = jump_table_group_size, ++ .group_filter = jump_table_group_filter, + }, + { + .name = ".printk_index", +@@ -2260,6 +2429,7 @@ static struct special_section special_sections[] = { + .name = ".static_call_sites", + .arch = X86_64, + .group_size = static_call_sites_group_size, ++ .group_filter = static_call_sites_group_filter, + }, + { + .name = ".retpoline_sites", +@@ -2297,138 +2467,36 @@ static struct special_section special_sections[] = { + .group_size = fixup_barrier_nospec_group_size, + }, + { +- .name = ".s390_return_mem", +- .arch = S390, +- .group_size = s390_expolines_group_size, ++ .name = ".s390_return_mem", ++ .arch = S390, ++ .group_size = s390_expolines_group_size, + }, + { +- .name = ".s390_return_reg", +- .arch = S390, +- .group_size = s390_expolines_group_size, ++ .name = ".s390_return_reg", ++ .arch = S390, ++ .group_size = s390_expolines_group_size, + }, + { +- .name = ".s390_indirect_call", +- .arch = S390, +- .group_size = s390_expolines_group_size, ++ .name = ".s390_indirect_call", ++ .arch = S390, ++ .group_size = s390_expolines_group_size, + }, + { +- .name = ".s390_indirect_branches", +- .arch = S390, +- .group_size = s390_expolines_group_size, ++ .name = ".s390_indirect_branches", ++ .arch = S390, ++ .group_size = s390_expolines_group_size, + }, + { +- .name = ".s390_indirect_jump", +- .arch = S390, +- .group_size = s390_expolines_group_size, ++ .name = ".s390_indirect_jump", ++ .arch = S390, ++ .group_size = s390_expolines_group_size, + }, + {}, + }; + +-static bool should_keep_jump_label(struct lookup_table *lookup, +- struct section *relasec, +- unsigned int group_offset, +- unsigned int group_size, +- int *jump_labels_found) +-{ +- struct rela *code = NULL, *key = NULL, *rela; +- bool tracepoint = false, dynamic_debug = false; +- struct lookup_result symbol; +- int i = 0; +- +- /* +- * Here we hard-code knowledge about the contents of the jump_entry +- * struct. It has three fields: code, target, and key. Each field has +- * a relocation associated with it. +- */ +- list_for_each_entry(rela, &relasec->relas, list) { +- if (rela->offset >= group_offset && +- rela->offset < group_offset + group_size) { +- if (i == 0) +- code = rela; +- else if (i == 2) +- key = rela; +- i++; +- } +- } +- +- if (i != 3 || !key || !code) +- ERROR("BUG: __jump_table has an unexpected format"); +- +- if (!strncmp(key->sym->name, "__tracepoint_", 13)) +- tracepoint = true; +- +- if (is_dynamic_debug_symbol(key->sym)) +- dynamic_debug = true; +- +- if (KLP_ARCH) { +- /* +- * On older kernels (with .klp.arch support), jump labels +- * aren't supported at all. Error out when they occur in a +- * replacement function, with the exception of tracepoints and +- * dynamic debug printks. An inert tracepoint or printk is +- * harmless enough, but a broken jump label can cause +- * unexpected behavior. +- */ +- if (tracepoint || dynamic_debug) +- return false; +- +- /* +- * This will be upgraded to an error after all jump labels have +- * been reported. +- */ +- log_normal("Found a jump label at %s()+0x%lx, using key %s. Jump labels aren't supported with this kernel. Use static_key_enabled() instead.\n", +- code->sym->name, code->addend, key->sym->name); +- (*jump_labels_found)++; +- return false; +- } +- +- /* +- * On newer (5.8+) kernels, jump labels are supported in the case where +- * the corresponding static key lives in vmlinux. That's because such +- * kernels apply vmlinux-specific .klp.rela sections at the same time +- * (in the klp module load) as normal relas, before jump label init. +- * On the other hand, jump labels based on static keys which are +- * defined in modules aren't supported, because late module patching +- * can result in the klp relas getting applied *after* the klp module's +- * jump label init. +- */ +- +- if (lookup_symbol(lookup, key->sym, &symbol) && +- strcmp(symbol.objname, "vmlinux")) { +- +- /* The static key lives in a module -- not supported */ +- +- /* Inert tracepoints and dynamic debug printks are harmless */ +- if (tracepoint || dynamic_debug) +- return false; +- +- /* +- * This will be upgraded to an error after all jump labels have +- * been reported. +- */ +- log_normal("Found a jump label at %s()+0x%lx, using key %s, which is defined in a module. Use static_key_enabled() instead.\n", +- code->sym->name, code->addend, key->sym->name); +- (*jump_labels_found)++; +- return false; +- } +- +- /* The static key lives in vmlinux or the patch module itself */ +- +- /* +- * If the jump label key lives in the '__dyndbg' section, make sure +- * the section gets included, because we don't use klp relocs for +- * dynamic debug symbols. For an example of such a key, see +- * DYNAMIC_DEBUG_BRANCH(). +- */ +- if (dynamic_debug) +- kpatch_include_symbol(key->sym); +- +- return true; +-} +- + static bool should_keep_rela_group(struct lookup_table *lookup, + struct section *relasec, unsigned int offset, +- unsigned int size, int *jump_labels_found) ++ unsigned int size) + { + struct rela *rela; + bool found = false; +@@ -2448,10 +2516,6 @@ static bool should_keep_rela_group(struct lookup_table *lookup, + if (!found) + return false; + +- if (!strcmp(relasec->name, ".rela__jump_table")) +- return should_keep_jump_label(lookup, relasec, offset, size, +- jump_labels_found); +- + return true; + } + +@@ -2488,7 +2552,6 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf, + struct rela *rela, *safe; + char *src, *dest; + unsigned int group_size, src_offset, dest_offset; +- int jump_labels_found = 0; + + LIST_HEAD(newrelas); + +@@ -2523,8 +2586,11 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf, + if (src_offset + group_size > relasec->base->sh.sh_size) + group_size = (unsigned int)(relasec->base->sh.sh_size - src_offset); + +- if (!should_keep_rela_group(lookup, relasec, src_offset, group_size, +- &jump_labels_found)) ++ if (!should_keep_rela_group(lookup, relasec, src_offset, group_size)) ++ continue; ++ ++ if (special->group_filter && ++ !special->group_filter(lookup, relasec, src_offset, group_size)) + continue; + + /* +@@ -2557,9 +2623,13 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf, + dest_offset += group_size; + } + +- if (jump_labels_found) +- ERROR("Found %d jump label(s) in the patched code. Jump labels aren't currently supported. Use static_key_enabled() instead.", +- jump_labels_found); ++ if (jump_label_errors) ++ ERROR("Found %d unsupported jump label(s) in the patched code. Use static_key_enabled() instead.", ++ jump_label_errors); ++ ++ if (static_call_errors) ++ ERROR("Found %d unsupported static call(s) in the patched code. Use KPATCH_STATIC_CALL() instead.", ++ static_call_errors); + + if (!dest_offset) { + /* no changed or global functions referenced */ +diff --git a/kpatch-build/log.h b/kpatch-build/log.h +index eefa0fce7b08..dbdc212713e1 100644 +--- a/kpatch-build/log.h ++++ b/kpatch-build/log.h +@@ -9,7 +9,7 @@ extern enum loglevel loglevel; + extern char *childobj; + + #define ERROR(format, ...) \ +- err(EXIT_STATUS_ERROR, "ERROR: %s: %s: %d: " format, childobj, __FUNCTION__, __LINE__, ##__VA_ARGS__) ++ errx(EXIT_STATUS_ERROR, "ERROR: %s: %s: %d: " format, childobj, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__) + #define log_normal(format, ...) log(NORMAL, "%s: " format, childobj, ##__VA_ARGS__) +-- +2.38.1 + diff --git a/SPECS/kpatch-patch.spec b/SPECS/kpatch-patch.spec index 6c9c529..c880651 100644 --- a/SPECS/kpatch-patch.spec +++ b/SPECS/kpatch-patch.spec @@ -1,17 +1,27 @@ # Set to 1 if building an empty subscription-only package. -%define empty_package 1 +%define empty_package 0 ####################################################### # Only need to update these variables and the changelog %define kernel_ver 5.14.0-162.6.1.el9_1 %define kpatch_ver 0.9.7 -%define rpm_ver 0 -%define rpm_rel 0 +%define rpm_ver 1 +%define rpm_rel 1 %if !%{empty_package} # Patch sources below. DO NOT REMOVE THIS LINE. -Source100: XXX.patch -#Source101: YYY.patch +# +# https://bugzilla.redhat.com/2141637 +Source100: CVE-2022-2959.patch +# +# https://bugzilla.redhat.com/2142785 +Source101: CVE-2022-2964.patch +# +# https://bugzilla.redhat.com/2147591 +Source102: CVE-2022-4139.patch +# +# https://bugzilla.redhat.com/2143187 +Source103: CVE-2022-43945.patch # End of patch sources. DO NOT REMOVE THIS LINE. %endif @@ -104,6 +114,8 @@ Source0: https://github.com/dynup/kpatch/archive/v%{kpatch_ver}.tar.gz Source10: kernel-%{kernel_ver}.src.rpm # kpatch-build patches +Patch1: v0.9.7-backport-MR-1314-create-diff-object-fix-__UNI.patch +Patch2: v0.9.7-backport-MR-1315-Static-call-fixes.patch %global _dupsign_opts --keyname=rhelkpatch1 @@ -187,5 +199,11 @@ It is only a method to subscribe to the kpatch stream for kernel-%{kernel_ver}. %endif %changelog +* Wed Jan 04 2023 Yannick Cote [1-1.el9_1] +- kernel: nfsd buffer overflow by RPC message over TCP with garbage data [2143187] {CVE-2022-43945} +- kernel: i915: Incorrect GPU TLB flush can lead to random memory access [2147591] {CVE-2022-4139} +- kernel: memory corruption in AX88179_178A based USB ethernet device. [2142785] {CVE-2022-2964} +- kernel: watch queue race condition can lead to privilege escalation [2141637] {CVE-2022-2959} + * Mon Oct 24 2022 Yannick Cote [0-0.el9] - An empty patch to subscribe to kpatch stream for kernel-5.14.0-162.6.1.el9_1 [2137424]