From: Greg Kroah-Hartman gregkh@linuxfoundation.org
stable inclusion form stable-v5.10.85 commit 7193ad3e50e596ac2192531c58ba83b9e6d2444b bugzilla: 185937 https://gitee.com/openeuler/kernel/issues/I4DDEL CVE: CVE-2021-39685
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
Sometimes USB hosts can ask for buffers that are too large from endpoint 0, which should not be allowed. If this happens for OUT requests, stall the endpoint, but for IN requests, trim the request size to the endpoint buffer size.
Co-developed-by: Szymon Heidrich szymon.heidrich@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Chen Jun chenjun102@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/gadget/composite.c | 12 ++++++++++++ drivers/usb/gadget/legacy/dbgp.c | 13 +++++++++++++ drivers/usb/gadget/legacy/inode.c | 16 +++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index a8704e6498ab..426132988512 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1648,6 +1648,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) struct usb_function *f = NULL; u8 endp;
+ if (w_length > USB_COMP_EP0_BUFSIZ) { + if (ctrl->bRequestType == USB_DIR_OUT) { + goto done; + } else { + /* Cast away the const, we are going to overwrite on purpose. */ + __le16 *temp = (__le16 *)&ctrl->wLength; + + *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); + w_length = USB_COMP_EP0_BUFSIZ; + } + } + /* partial re-init of the response message; the function or the * gadget might need to intercept e.g. a control-OUT completion * when we delegate to it. diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index e1d566c9918a..e567afcb2794 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget, void *data = NULL; u16 len = 0;
+ if (length > DBGP_REQ_LEN) { + if (ctrl->bRequestType == USB_DIR_OUT) { + return err; + } else { + /* Cast away the const, we are going to overwrite on purpose. */ + __le16 *temp = (__le16 *)&ctrl->wLength; + + *temp = cpu_to_le16(DBGP_REQ_LEN); + length = DBGP_REQ_LEN; + } + } + + if (request == USB_REQ_GET_DESCRIPTOR) { switch (value>>8) { case USB_DT_DEVICE: diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 71e7d10dd76b..04b9c4f5f129 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -110,6 +110,8 @@ enum ep0_state { /* enough for the whole queue: most events invalidate others */ #define N_EVENT 5
+#define RBUF_SIZE 256 + struct dev_data { spinlock_t lock; refcount_t count; @@ -144,7 +146,7 @@ struct dev_data { struct dentry *dentry;
/* except this scratch i/o buffer for ep0 */ - u8 rbuf [256]; + u8 rbuf[RBUF_SIZE]; };
static inline void get_dev (struct dev_data *data) @@ -1333,6 +1335,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength);
+ if (w_length > RBUF_SIZE) { + if (ctrl->bRequestType == USB_DIR_OUT) { + return value; + } else { + /* Cast away the const, we are going to overwrite on purpose. */ + __le16 *temp = (__le16 *)&ctrl->wLength; + + *temp = cpu_to_le16(RBUF_SIZE); + w_length = RBUF_SIZE; + } + } + spin_lock (&dev->lock); dev->setup_abort = 0; if (dev->state == STATE_DEV_UNCONNECTED) {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
mainline inclusion form mainline-v5.16-rc6 commit f08adf5add9a071160c68bb2a61d697f39ab0758 bugzilla: 185937 https://gitee.com/openeuler/kernel/issues/I4DDEL CVE: CVE-2021-39685
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Szymon rightly pointed out that the previous check for the endpoint direction in bRequestType was not looking at only the bit involved, but rather the whole value. Normally this is ok, but for some request types, bits other than bit 8 could be set and the check for the endpoint length could not stall correctly.
Fix that up by only checking the single bit.
Fixes: 153a2d7e3350 ("USB: gadget: detect too-big endpoint 0 requests") Cc: Felipe Balbi balbi@kernel.org Reported-by: Szymon Heidrich szymon.heidrich@gmail.com Link: https://lore.kernel.org/r/20211214184621.385828-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Chen Jun chenjun102@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/gadget/composite.c | 6 +++--- drivers/usb/gadget/legacy/dbgp.c | 6 +++--- drivers/usb/gadget/legacy/inode.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 426132988512..8bec0cbf844e 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1649,14 +1649,14 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) u8 endp;
if (w_length > USB_COMP_EP0_BUFSIZ) { - if (ctrl->bRequestType == USB_DIR_OUT) { - goto done; - } else { + if (ctrl->bRequestType & USB_DIR_IN) { /* Cast away the const, we are going to overwrite on purpose. */ __le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); w_length = USB_COMP_EP0_BUFSIZ; + } else { + goto done; } }
diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index e567afcb2794..ffe58d44b2cb 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -346,14 +346,14 @@ static int dbgp_setup(struct usb_gadget *gadget, u16 len = 0;
if (length > DBGP_REQ_LEN) { - if (ctrl->bRequestType == USB_DIR_OUT) { - return err; - } else { + if (ctrl->bRequestType & USB_DIR_IN) { /* Cast away the const, we are going to overwrite on purpose. */ __le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(DBGP_REQ_LEN); length = DBGP_REQ_LEN; + } else { + return err; } }
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 04b9c4f5f129..217d2b66fa51 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1336,14 +1336,14 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) u16 w_length = le16_to_cpu(ctrl->wLength);
if (w_length > RBUF_SIZE) { - if (ctrl->bRequestType == USB_DIR_OUT) { - return value; - } else { + if (ctrl->bRequestType & USB_DIR_IN) { /* Cast away the const, we are going to overwrite on purpose. */ __le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(RBUF_SIZE); w_length = RBUF_SIZE; + } else { + return value; } }
From: Chen Jun chenjun102@huawei.com
hulk inclusion bugzilla: 185877 https://gitee.com/openeuler/kernel/issues/I4DDEL
--------------------------------
This reverts commit 3573d9d69944e012d995753eab9415de244b7bc9.
the commit 568d94c5c9f0 ("ARM: BCM53016: Specify switch ports for Meraki MR32") Introduce some warning:
property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) arch/arm/boot/dts/bcm53016-meraki-mr32.dtb: Warning (pci_device_bus_num): Failed prerequisite 'reg_format' arch/arm/boot/dts/bcm53016-meraki-mr32.dtb: Warning (i2c_bus_reg): Failed prerequisite 'reg_format' arch/arm/boot/dts/bcm53016-meraki-mr32.dtb: Warning (spi_bus_reg): Failed prerequisite 'reg_format' arch/arm/boot/dts/bcm53016-meraki-mr32.dts:203.10-206.5: Warning (avoid_default_addr_size): /srab@18007000/ports/port@0: Relying on default #address-cells value arch/arm/boot/dts/bcm53016-meraki-mr32.dts:203.10-206.5: Warning (avoid_default_addr_size): /srab@18007000/ports/port@0: Relying on default #size-cells value arch/arm/boot/dts/bcm53016-meraki-mr32.dts:208.10-217.5: Warning (avoid_default_addr_size): /srab@18007000/ports/port@5: Relying on default #address-cells value arch/arm/boot/dts/bcm53016-meraki-mr32.dts:208.10-217.5: Warning (avoid_default_addr_size): /srab@18007000/ports/port@5: Relying on default #size-cells value
bcm53016-meraki-mr32.dtb will not be used, so revert it.
Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 22 ---------------------- 1 file changed, 22 deletions(-)
diff --git a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts index 577a4dc604d9..612d61852bfb 100644 --- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts +++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts @@ -195,25 +195,3 @@ }; }; }; - -&srab { - status = "okay"; - - ports { - port@0 { - reg = <0>; - label = "poe"; - }; - - port@5 { - reg = <5>; - label = "cpu"; - ethernet = <&gmac0>; - - fixed-link { - speed = <1000>; - duplex-full; - }; - }; - }; -};
From: Hangyu Hua hbh25y@gmail.com
mainline inclusion from mainline-v5.16-rc6 commit bcd0f93353326954817a4f9fa55ec57fb38acbb0 category: bugfix bugzilla: 185940 https://gitee.com/openeuler/kernel/issues/I4DDEL CVE: CVE-2021-45095
Reference: https://patchwork.kernel.org/project/netdevbpf/patch/20211209082839.33985-1-...
-------------------------------------------------------------------
sock_hold(sk) is invoked in pep_sock_accept(), but __sock_put(sk) is not invoked in subsequent failure branches(pep_accept_conn() != 0).
Signed-off-by: Hangyu Hua hbh25y@gmail.com Link: https://lore.kernel.org/r/20211209082839.33985-1-hbh25y@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Huang Guobin huangguobin4@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- net/phonet/pep.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/phonet/pep.c b/net/phonet/pep.c index a1525916885a..b4f90afb0638 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -868,6 +868,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp,
err = pep_accept_conn(newsk, skb); if (err) { + __sock_put(sk); sock_put(newsk); newsk = NULL; goto drop;
From: Mike Rapoport rppt@linux.ibm.com
mainline inclusion from mainline-v5.14-rc1 commit 023accf5cdc1e504a9b04187ec23ff156fe53d90 category: bugfix bugzilla: 172285 https://gitee.com/openeuler/kernel/issues/I4DDEL
-----------------------------------------------
There maybe an overflow in memblock_overlaps_region() if it is called with base and size such that
base + size > PHYS_ADDR_MAX
Make sure that memblock_overlaps_region() caps the size to prevent such overflow and remove now duplicated call to memblock_cap_size() from memblock_is_region_reserved().
Signed-off-by: Mike Rapoport rppt@linux.ibm.com Tested-by: Tony Lindgren tony@atomide.com Signed-off-by: Chen Huang chenhuang5@huawei.com Reviewed-by: Chen Wandun chenwandun@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/memblock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/memblock.c b/mm/memblock.c index d85893ab2f22..7b25c54ab5c8 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -182,6 +182,8 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type, { unsigned long i;
+ memblock_cap_size(base, &size); + for (i = 0; i < type->cnt; i++) if (memblock_addrs_overlap(base, size, type->regions[i].base, type->regions[i].size)) @@ -1804,7 +1806,6 @@ bool __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t siz */ bool __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size) { - memblock_cap_size(base, &size); return memblock_overlaps_region(&memblock.reserved, base, size); }
From: Mike Kravetz mike.kravetz@oracle.com
mainline inclusion from mainline-v5.14-rc1 commit 7118fc2906e2925d7edb5ed9c8a57f2a5f23b849 category: bugfix bugzilla:171843
-----------------------------------------------
In [1], Jann Horn points out a possible race between prep_compound_gigantic_page and __page_cache_add_speculative. The root cause of the possible race is prep_compound_gigantic_page uncondittionally setting the ref count of pages to zero. It does this because prep_compound_gigantic_page is handed a 'group' of pages from an allocator and needs to convert that group of pages to a compound page. The ref count of each page in this 'group' is one as set by the allocator. However, the ref count of compound page tail pages must be zero.
The potential race comes about when ref counted pages are returned from the allocator. When this happens, other mm code could also take a reference on the page. __page_cache_add_speculative is one such example. Therefore, prep_compound_gigantic_page can not just set the ref count of pages to zero as it does today. Doing so would lose the reference taken by any other code. This would lead to BUGs in code checking ref counts and could possibly even lead to memory corruption.
There are two possible ways to address this issue.
1) Make all allocators of gigantic groups of pages be able to return a properly constructed compound page.
2) Make prep_compound_gigantic_page be more careful when constructing a compound page.
This patch takes approach 2.
In prep_compound_gigantic_page, use cmpxchg to only set ref count to zero if it is one. If the cmpxchg fails, call synchronize_rcu() in the hope that the extra ref count will be driopped during a rcu grace period. This is not a performance critical code path and the wait should be accceptable. If the ref count is still inflated after the grace period, then undo any modifications made and return an error.
Currently prep_compound_gigantic_page is type void and does not return errors. Modify the two callers to check for and handle error returns. On error, the caller must free the 'group' of pages as they can not be used to form a gigantic page. After freeing pages, the runtime caller (alloc_fresh_huge_page) will retry the allocation once. Boot time allocations can not be retried.
The routine prep_compound_page also unconditionally sets the ref count of compound page tail pages to zero. However, in this case the buddy allocator is constructing a compound page from freshly allocated pages. The ref count on those freshly allocated pages is already zero, so the set_page_count(p, 0) is unnecessary and could lead to confusion. Just remove it.
[1] https://lore.kernel.org/linux-mm/CAG48ez23q0Jy9cuVnwAe7t_fdhMk2S7N5Hdi-GLcCe...
Link: https://lkml.kernel.org/r/20210622021423.154662-3-mike.kravetz@oracle.com Fixes: 58a84aa92723 ("thp: set compound tail page _count to zero") Signed-off-by: Mike Kravetz mike.kravetz@oracle.com Reported-by: Jann Horn jannh@google.com Cc: Youquan Song youquan.song@intel.com Cc: Andrea Arcangeli aarcange@redhat.com Cc: Jan Kara jack@suse.cz Cc: John Hubbard jhubbard@nvidia.com Cc: "Kirill A . Shutemov" kirill@shutemov.name Cc: Matthew Wilcox willy@infradead.org Cc: Michal Hocko mhocko@kernel.org Cc: Muchun Song songmuchun@bytedance.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Chen Huang chenhuang5@huawei.com Reviewed-by: Chen Wandun chenwandun@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/hugetlb.c | 72 +++++++++++++++++++++++++++++++++++++++++++------ mm/page_alloc.c | 1 - 2 files changed, 64 insertions(+), 9 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index e553e959bda8..c9b6f063fde1 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1632,9 +1632,9 @@ static void prep_new_huge_page(struct hstate *h, struct page *page, int nid) spin_unlock_irq(&hugetlb_lock); }
-static void prep_compound_gigantic_page(struct page *page, unsigned int order) +static bool prep_compound_gigantic_page(struct page *page, unsigned int order) { - int i; + int i, j; int nr_pages = 1 << order; struct page *p = page + 1;
@@ -1656,11 +1656,48 @@ static void prep_compound_gigantic_page(struct page *page, unsigned int order) * after get_user_pages(). */ __ClearPageReserved(p); + /* + * Subtle and very unlikely + * + * Gigantic 'page allocators' such as memblock or cma will + * return a set of pages with each page ref counted. We need + * to turn this set of pages into a compound page with tail + * page ref counts set to zero. Code such as speculative page + * cache adding could take a ref on a 'to be' tail page. + * We need to respect any increased ref count, and only set + * the ref count to zero if count is currently 1. If count + * is not 1, we call synchronize_rcu in the hope that a rcu + * grace period will cause ref count to drop and then retry. + * If count is still inflated on retry we return an error and + * must discard the pages. + */ + if (!page_ref_freeze(p, 1)) { + pr_info("HugeTLB unexpected inflated ref count on freshly allocated page\n"); + synchronize_rcu(); + if (!page_ref_freeze(p, 1)) + goto out_error; + } set_page_count(p, 0); set_compound_head(p, page); } atomic_set(compound_mapcount_ptr(page), -1); atomic_set(compound_pincount_ptr(page), 0); + return true; + +out_error: + /* undo tail page modifications made above */ + p = page + 1; + for (j = 1; j < i; j++, p = mem_map_next(p, page, j)) { + clear_compound_head(p); + set_page_refcounted(p); + } + /* need to clear PG_reserved on remaining tail pages */ + for (; j < nr_pages; j++, p = mem_map_next(p, page, j)) + __ClearPageReserved(p); + set_compound_order(page, 0); + page[1].compound_nr = 0; + __ClearPageHead(page); + return false; }
/* @@ -1780,7 +1817,9 @@ static struct page *alloc_fresh_huge_page(struct hstate *h, nodemask_t *node_alloc_noretry) { struct page *page; + bool retry = false;
+retry: if (hstate_is_gigantic(h)) page = alloc_gigantic_page(h, gfp_mask, nid, nmask); else @@ -1789,8 +1828,21 @@ static struct page *alloc_fresh_huge_page(struct hstate *h, if (!page) return NULL;
- if (hstate_is_gigantic(h)) - prep_compound_gigantic_page(page, huge_page_order(h)); + if (hstate_is_gigantic(h)) { + if (!prep_compound_gigantic_page(page, huge_page_order(h))) { + /* + * Rare failure to convert pages to compound page. + * Free pages and try again - ONCE! + */ + free_gigantic_page(page, huge_page_order(h)); + if (!retry) { + retry = true; + goto retry; + } + pr_warn("HugeTLB page can not be used due to unexpected inflated ref count\n"); + return NULL; + } + } prep_new_huge_page(h, page, page_to_nid(page));
return page; @@ -2586,10 +2638,14 @@ static void __init gather_bootmem_prealloc(void)
VM_BUG_ON(!hstate_is_gigantic(h)); WARN_ON(page_count(page) != 1); - prep_compound_gigantic_page(page, huge_page_order(h)); - WARN_ON(PageReserved(page)); - prep_new_huge_page(h, page, page_to_nid(page)); - put_page(page); /* free it into the hugepage allocator */ + if (prep_compound_gigantic_page(page, huge_page_order(h))) { + WARN_ON(PageReserved(page)); + prep_new_huge_page(h, page, page_to_nid(page)); + put_page(page); /* add to the hugepage allocator */ + } else { + free_gigantic_page(page, huge_page_order(h)); + pr_warn("HugeTLB page can not be used due to unexpected inflated ref count\n"); + }
/* * We need to restore the 'stolen' pages to totalram_pages diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 22f6824b1714..988051bf6795 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -703,7 +703,6 @@ void prep_compound_page(struct page *page, unsigned int order) __SetPageHead(page); for (i = 1; i < nr_pages; i++) { struct page *p = page + i; - set_page_count(p, 0); p->mapping = TAIL_MAPPING; set_compound_head(p, page); }
From: Liu Shixin liushixin2@huawei.com
mainline inclusion from mainline-v5.16-rc7 commit 2a57d83c78f889bf3f54eede908d0643c40d5418 category: bugfix bugzilla: 185855 https://gitee.com/openeuler/kernel/issues/I4DDEL
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Hulk Robot reported a panic in put_page_testzero() when testing madvise() with MADV_SOFT_OFFLINE. The BUG() is triggered when retrying get_any_page(). This is because we keep MF_COUNT_INCREASED flag in second try but the refcnt is not increased.
page dumped because: VM_BUG_ON_PAGE(page_ref_count(page) == 0) ------------[ cut here ]------------ kernel BUG at include/linux/mm.h:737! invalid opcode: 0000 [#1] PREEMPT SMP CPU: 5 PID: 2135 Comm: sshd Tainted: G B 5.16.0-rc6-dirty #373 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 RIP: release_pages+0x53f/0x840 Call Trace: free_pages_and_swap_cache+0x64/0x80 tlb_flush_mmu+0x6f/0x220 unmap_page_range+0xe6c/0x12c0 unmap_single_vma+0x90/0x170 unmap_vmas+0xc4/0x180 exit_mmap+0xde/0x3a0 mmput+0xa3/0x250 do_exit+0x564/0x1470 do_group_exit+0x3b/0x100 __do_sys_exit_group+0x13/0x20 __x64_sys_exit_group+0x16/0x20 do_syscall_64+0x34/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae Modules linked in: ---[ end trace e99579b570fe0649 ]--- RIP: 0010:release_pages+0x53f/0x840
Link: https://lkml.kernel.org/r/20211221074908.3910286-1-liushixin2@huawei.com Fixes: b94e02822deb ("mm,hwpoison: try to narrow window race for free pages") Signed-off-by: Liu Shixin liushixin2@huawei.com Reported-by: Hulk Robot hulkci@huawei.com Reviewed-by: Oscar Salvador osalvador@suse.de Acked-by: Naoya Horiguchi naoya.horiguchi@nec.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Conflicts: mm/memory-failure.c Signed-off-by: Liu Shixin liushixin2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/memory-failure.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index c222d5a35338..b7cd29a26c1b 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1960,6 +1960,7 @@ int soft_offline_page(unsigned long pfn, int flags) else if (ret == 0) if (soft_offline_free_page(page) && try_again) { try_again = false; + flags &= ~MF_COUNT_INCREASED; goto retry; }
From: Haimin Zhang tcs.kernel@gmail.com
mainline inclusion from mainline-v5.16-rc6 commit 481221775d53d6215a6e5e9ce1cce6d2b4ab9a46 category: bugfix bugzilla: 185973 https://gitee.com/openeuler/kernel/issues/I4DDEL CVE: CVE-2021-4135
Reference: https://lore.kernel.org/all/20211215111530.72103-1-tcs.kernel@gmail.com/ Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Zero-initialize memory for new map's value in function nsim_bpf_map_alloc since it may cause a potential kernel information leak issue, as follows: 1. nsim_bpf_map_alloc calls nsim_map_alloc_elem to allocate elements for a new map. 2. nsim_map_alloc_elem uses kmalloc to allocate map's value, but doesn't zero it. 3. A user application can use IOCTL BPF_MAP_LOOKUP_ELEM to get specific element's information in the map. 4. The kernel function map_lookup_elem will call bpf_map_copy_value to get the information allocated at step-2, then use copy_to_user to copy to the user buffer. This can only leak information for an array map.
Fixes: 395cacb5f1a0 ("netdevsim: bpf: support fake map offload") Suggested-by: Jakub Kicinski kuba@kernel.org Acked-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Haimin Zhang tcs.kernel@gmail.com Link: https://lore.kernel.org/r/20211215111530.72103-1-tcs.kernel@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: He Fengqing hefengqing@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/netdevsim/bpf.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c index 90aafb56f140..a43820212932 100644 --- a/drivers/net/netdevsim/bpf.c +++ b/drivers/net/netdevsim/bpf.c @@ -514,6 +514,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap) goto err_free; key = nmap->entry[i].key; *key = i; + memset(nmap->entry[i].value, 0, offmap->map.value_size); } }
From: Xiaoming Ni nixiaoming@huawei.com
stable inclusion from stable-v5.10.88 commit 151ffac3ac277ad7c2a5f201b566b56d97ed3a99 bugzilla: 185938 https://gitee.com/openeuler/kernel/issues/I4DDEL
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 3dc709e518b47386e6af937eaec37bb36539edfd ]
When CONFIG_FSL_PMC is set to n, no value is assigned to cpu_up_prepare in the mpc85xx_pm_ops structure. As a result, oops is triggered in smp_85xx_start_cpu().
smp: Bringing up secondary CPUs ... kernel tried to execute user page (0) - exploit attempt? (uid: 0) BUG: Unable to handle kernel instruction fetch (NULL pointer?) Faulting instruction address: 0x00000000 Oops: Kernel access of bad area, sig: 11 [#1] ... NIP [00000000] 0x0 LR [c0021d2c] smp_85xx_kick_cpu+0xe8/0x568 Call Trace: [c1051da8] [c0021cb8] smp_85xx_kick_cpu+0x74/0x568 (unreliable) [c1051de8] [c0011460] __cpu_up+0xc0/0x228 [c1051e18] [c0031bbc] bringup_cpu+0x30/0x224 [c1051e48] [c0031f3c] cpu_up.constprop.0+0x180/0x33c [c1051e88] [c00322e8] bringup_nonboot_cpus+0x88/0xc8 [c1051eb8] [c07e67bc] smp_init+0x30/0x78 [c1051ed8] [c07d9e28] kernel_init_freeable+0x118/0x2a8 [c1051f18] [c00032d8] kernel_init+0x14/0x124 [c1051f38] [c0010278] ret_from_kernel_thread+0x14/0x1c
Fixes: c45361abb918 ("powerpc/85xx: fix timebase sync issue when CONFIG_HOTPLUG_CPU=n") Reported-by: Martin Kennedy hurricos@gmail.com Signed-off-by: Xiaoming Ni nixiaoming@huawei.com Tested-by: Martin Kennedy hurricos@gmail.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20211126041153.16926-1-nixiaoming@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Chen Jun chenjun102@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/powerpc/platforms/85xx/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 83f4a6389a28..d7081e9af65c 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -220,7 +220,7 @@ static int smp_85xx_start_cpu(int cpu) local_irq_save(flags); hard_irq_disable();
- if (qoriq_pm_ops) + if (qoriq_pm_ops && qoriq_pm_ops->cpu_up_prepare) qoriq_pm_ops->cpu_up_prepare(cpu);
/* if cpu is not spinning, reset it */ @@ -292,7 +292,7 @@ static int smp_85xx_kick_cpu(int nr) booting_thread_hwid = cpu_thread_in_core(nr); primary = cpu_first_thread_sibling(nr);
- if (qoriq_pm_ops) + if (qoriq_pm_ops && qoriq_pm_ops->cpu_up_prepare) qoriq_pm_ops->cpu_up_prepare(nr);
/*
From: Baokun Li libaokun1@huawei.com
hulk inclusion category: bugfix bugzilla: 185988 https://gitee.com/openeuler/kernel/issues/I4DDEL
--------------------------------
When we mount a jffs2 image, assume that the first few blocks of the image are normal and contain at least one xattr-related inode, but the next block is abnormal. As a result, an error is returned in jffs2_scan_eraseblock(). jffs2_clear_xattr_subsystem() is then called in jffs2_build_filesystem() and then again in jffs2_do_fill_super().
Finally we can observe the following report: ================================================================== BUG: KASAN: use-after-free in jffs2_clear_xattr_subsystem+0x95/0x6ac Read of size 8 at addr ffff8881243384e0 by task mount/719
Call Trace: dump_stack+0x115/0x16b jffs2_clear_xattr_subsystem+0x95/0x6ac jffs2_do_fill_super+0x84f/0xc30 jffs2_fill_super+0x2ea/0x4c0 mtd_get_sb+0x254/0x400 mtd_get_sb_by_nr+0x4f/0xd0 get_tree_mtd+0x498/0x840 jffs2_get_tree+0x25/0x30 vfs_get_tree+0x8d/0x2e0 path_mount+0x50f/0x1e50 do_mount+0x107/0x130 __se_sys_mount+0x1c5/0x2f0 __x64_sys_mount+0xc7/0x160 do_syscall_64+0x45/0x70 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Allocated by task 719: kasan_save_stack+0x23/0x60 __kasan_kmalloc.constprop.0+0x10b/0x120 kasan_slab_alloc+0x12/0x20 kmem_cache_alloc+0x1c0/0x870 jffs2_alloc_xattr_ref+0x2f/0xa0 jffs2_scan_medium.cold+0x3713/0x4794 jffs2_do_mount_fs.cold+0xa7/0x2253 jffs2_do_fill_super+0x383/0xc30 jffs2_fill_super+0x2ea/0x4c0 [...]
Freed by task 719: kmem_cache_free+0xcc/0x7b0 jffs2_free_xattr_ref+0x78/0x98 jffs2_clear_xattr_subsystem+0xa1/0x6ac jffs2_do_mount_fs.cold+0x5e6/0x2253 jffs2_do_fill_super+0x383/0xc30 jffs2_fill_super+0x2ea/0x4c0 [...]
The buggy address belongs to the object at ffff8881243384b8 which belongs to the cache jffs2_xattr_ref of size 48 The buggy address is located 40 bytes inside of 48-byte region [ffff8881243384b8, ffff8881243384e8) [...] ==================================================================
The triggering of the BUG is shown in the following stack: ----------------------------------------------------------- jffs2_fill_super jffs2_do_fill_super jffs2_do_mount_fs jffs2_build_filesystem jffs2_scan_medium jffs2_scan_eraseblock <--- ERROR jffs2_clear_xattr_subsystem <--- free jffs2_clear_xattr_subsystem <--- free again -----------------------------------------------------------
An error is returned in jffs2_do_mount_fs(). If the error is returned by jffs2_sum_init(), the jffs2_clear_xattr_subsystem() does not need to be executed. If the error is returned by jffs2_build_filesystem(), the jffs2_clear_xattr_subsystem() also does not need to be executed again. So move jffs2_clear_xattr_subsystem() from 'out_inohash' to 'out_root' to fix this UAF problem.
Fixes: aa98d7cf59b5 ("[JFFS2][XATTR] XATTR support on JFFS2 (version. 5)") Reported-by: Chengsong Ke kechengsong@huawei.com Signed-off-by: Baokun Li libaokun1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/jffs2/fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 29c9c3809fd1..6ac76ed9dbd4 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -600,8 +600,8 @@ int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc) jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); kvfree(c->blocks); - out_inohash: jffs2_clear_xattr_subsystem(c); + out_inohash: kfree(c->inocache_list); out_wbuf: jffs2_flash_cleanup(c);
From: Baokun Li libaokun1@huawei.com
hulk inclusion category: bugfix bugzilla: 185988 https://gitee.com/openeuler/kernel/issues/I4DDEL
--------------------------------
If jffs2_build_filesystem() in jffs2_do_mount_fs() returns an error, we can observe the following kmemleak report:
-------------------------------------------- unreferenced object 0xffff88811b25a640 (size 64): comm "mount", pid 691, jiffies 4294957728 (age 71.952s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffffa493be24>] kmem_cache_alloc_trace+0x584/0x880 [<ffffffffa5423a06>] jffs2_sum_init+0x86/0x130 [<ffffffffa5400e58>] jffs2_do_mount_fs+0x798/0xac0 [<ffffffffa540acf3>] jffs2_do_fill_super+0x383/0xc30 [<ffffffffa540c00a>] jffs2_fill_super+0x2ea/0x4c0 [...] unreferenced object 0xffff88812c760000 (size 65536): comm "mount", pid 691, jiffies 4294957728 (age 71.952s) hex dump (first 32 bytes): bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb ................ bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb ................ backtrace: [<ffffffffa493a449>] __kmalloc+0x6b9/0x910 [<ffffffffa5423a57>] jffs2_sum_init+0xd7/0x130 [<ffffffffa5400e58>] jffs2_do_mount_fs+0x798/0xac0 [<ffffffffa540acf3>] jffs2_do_fill_super+0x383/0xc30 [<ffffffffa540c00a>] jffs2_fill_super+0x2ea/0x4c0 [...] --------------------------------------------
This is because the resources allocated in jffs2_sum_init() are not released. Call jffs2_sum_exit() to release these resources to solve the problem.
Fixes: e631ddba5887 ("[JFFS2] Add erase block summary support (mount time improvement)") Signed-off-by: Baokun Li libaokun1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/jffs2/build.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index b288c8ae1236..837cd55fd4c5 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -415,13 +415,15 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); ret = -EIO; - goto out_free; + goto out_sum_exit; }
jffs2_calc_trigger_levels(c);
return 0;
+ out_sum_exit: + jffs2_sum_exit(c); out_free: kvfree(c->blocks);
From: Baokun Li libaokun1@huawei.com
hulk inclusion category: bugfix bugzilla: 185988 https://gitee.com/openeuler/kernel/issues/I4DDEL
--------------------------------
If an error is returned in jffs2_scan_eraseblock() and some memory has been added to the jffs2_summary *s, we can observe the following kmemleak report:
-------------------------------------------- unreferenced object 0xffff88812b889c40 (size 64): comm "mount", pid 692, jiffies 4294838325 (age 34.288s) hex dump (first 32 bytes): 40 48 b5 14 81 88 ff ff 01 e0 31 00 00 00 50 00 @H........1...P. 00 00 01 00 00 00 01 00 00 00 02 00 00 00 09 08 ................ backtrace: [<ffffffffae93a3a3>] __kmalloc+0x613/0x910 [<ffffffffaf423b9c>] jffs2_sum_add_dirent_mem+0x5c/0xa0 [<ffffffffb0f3afa8>] jffs2_scan_medium.cold+0x36e5/0x4794 [<ffffffffb0f3dbe1>] jffs2_do_mount_fs.cold+0xa7/0x2267 [<ffffffffaf40acf3>] jffs2_do_fill_super+0x383/0xc30 [<ffffffffaf40c00a>] jffs2_fill_super+0x2ea/0x4c0 [<ffffffffb0315d64>] mtd_get_sb+0x254/0x400 [<ffffffffb0315f5f>] mtd_get_sb_by_nr+0x4f/0xd0 [<ffffffffb0316478>] get_tree_mtd+0x498/0x840 [<ffffffffaf40bd15>] jffs2_get_tree+0x25/0x30 [<ffffffffae9f358d>] vfs_get_tree+0x8d/0x2e0 [<ffffffffaea7a98f>] path_mount+0x50f/0x1e50 [<ffffffffaea7c3d7>] do_mount+0x107/0x130 [<ffffffffaea7c5c5>] __se_sys_mount+0x1c5/0x2f0 [<ffffffffaea7c917>] __x64_sys_mount+0xc7/0x160 [<ffffffffb10142f5>] do_syscall_64+0x45/0x70 unreferenced object 0xffff888114b54840 (size 32): comm "mount", pid 692, jiffies 4294838325 (age 34.288s) hex dump (first 32 bytes): c0 75 b5 14 81 88 ff ff 02 e0 02 00 00 00 02 00 .u.............. 00 00 84 00 00 00 44 00 00 00 6b 6b 6b 6b 6b a5 ......D...kkkkk. backtrace: [<ffffffffae93be24>] kmem_cache_alloc_trace+0x584/0x880 [<ffffffffaf423b04>] jffs2_sum_add_inode_mem+0x54/0x90 [<ffffffffb0f3bd44>] jffs2_scan_medium.cold+0x4481/0x4794 [...] unreferenced object 0xffff888114b57280 (size 32): comm "mount", pid 692, jiffies 4294838393 (age 34.357s) hex dump (first 32 bytes): 10 d5 6c 11 81 88 ff ff 08 e0 05 00 00 00 01 00 ..l............. 00 00 38 02 00 00 28 00 00 00 6b 6b 6b 6b 6b a5 ..8...(...kkkkk. backtrace: [<ffffffffae93be24>] kmem_cache_alloc_trace+0x584/0x880 [<ffffffffaf423c34>] jffs2_sum_add_xattr_mem+0x54/0x90 [<ffffffffb0f3a24f>] jffs2_scan_medium.cold+0x298c/0x4794 [...] unreferenced object 0xffff8881116cd510 (size 16): comm "mount", pid 692, jiffies 4294838395 (age 34.355s) hex dump (first 16 bytes): 00 00 00 00 00 00 00 00 09 e0 60 02 00 00 6b a5 ..........`...k. backtrace: [<ffffffffae93be24>] kmem_cache_alloc_trace+0x584/0x880 [<ffffffffaf423cc4>] jffs2_sum_add_xref_mem+0x54/0x90 [<ffffffffb0f3b2e3>] jffs2_scan_medium.cold+0x3a20/0x4794 [...] --------------------------------------------
Therefore, when processing errors, it is necessary to determine whether s->sum_list_head is NULL. If not, call jffs2_sum_reset_collected(s) to release the memory added in s.
Fixes: e631ddba5887 ("[JFFS2] Add erase block summary support (mount time improvement)") Co-developed-with: Zhihao Cheng chengzhihao1@huawei.com Signed-off-by: Baokun Li libaokun1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/jffs2/scan.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index b676056826be..49b0637fb36e 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -281,6 +281,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) else mtd_unpoint(c->mtd, 0, c->mtd->size); #endif + if (s->sum_list_head) + jffs2_sum_reset_collected(s); kfree(s); return ret; }
From: Kefeng Wang wangkefeng.wang@huawei.com
hulk inclusion category: bugfix bugzilla: 186017 https://gitee.com/openeuler/kernel/issues/I4DDEL
--------------------------------
When run ethtool eth0, the BUG occurred,
usercopy: Kernel memory exposure attempt detected from SLUB object not in SLUB page?! (offset 0, size 1048)! kernel BUG at mm/usercopy.c:99 ... usercopy_abort+0x64/0xa0 (unreliable) __check_heap_object+0x168/0x190 __check_object_size+0x1a0/0x200 dev_ethtool+0x2494/0x2b20 dev_ioctl+0x5d0/0x770 sock_do_ioctl+0xf0/0x1d0 sock_ioctl+0x3ec/0x5a0 __se_sys_ioctl+0xf0/0x160 system_call_exception+0xfc/0x1f0 system_call_common+0xf8/0x200
The code shows below,
data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN)); copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
The data is alloced by vmalloc(), virt_addr_valid(ptr) will return true on PowerPC64, which leads to the panic.
As commit 4dd7554a6456 ("powerpc/64: Add VIRTUAL_BUG_ON checks for __va and __pa addresses") does, make sure the virt addr above PAGE_OFFSET in the virt_addr_valid().
Signed-off-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yuanzheng Song songyuanzheng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/powerpc/include/asm/page.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index 254687258f42..300d4c105a3a 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -132,7 +132,10 @@ static inline bool pfn_valid(unsigned long pfn) #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr)) +#define virt_addr_valid(vaddr) ({ \ + unsigned long _addr = (unsigned long)vaddr; \ + (unsigned long)(_addr) >= PAGE_OFFSET && pfn_valid(virt_to_pfn(_addr)); \ +})
/* * On Book-E parts we need __va to parse the device tree and we can't
From: Kefeng Wang wangkefeng.wang@huawei.com
hulk inclusion category: bugfix bugzilla: 186017 https://gitee.com/openeuler/kernel/issues/I4DDEL
--------------------------------
virt_addr_valid() could be insufficient to validate the virt addr on some architecture, which could lead to potential BUG which has been found on arm64/powerpc64.
Let's add WARN_ON to check if the virt addr is passed virt_addr_valid() but is a vmalloc/module address.
Signed-off-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yuanzheng Song songyuanzheng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- mm/usercopy.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/mm/usercopy.c b/mm/usercopy.c index b3de3c4eefba..ce83e0b137dd 100644 --- a/mm/usercopy.c +++ b/mm/usercopy.c @@ -228,6 +228,8 @@ static inline void check_heap_object(const void *ptr, unsigned long n, if (!virt_addr_valid(ptr)) return;
+ WARN_ON_ONCE(is_vmalloc_or_module_addr(ptr)); + /* * When CONFIG_HIGHMEM=y, kmap_to_page() will give either the * highmem page or fallback to virt_to_page(). The following
From: Desmond Cheong Zhi Xi desmondcheongzx@gmail.com
mainline inclusion from mainline-v5.15-rc1 commit f671a691e299f58835d4660d642582bf0e8f6fda category: bugfix bugzilla: 185969 https://gitee.com/openeuler/kernel/issues/I4DDEL
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h...
--------------------------------
Syzbot reports a potential deadlock in do_fcntl:
======================================================== WARNING: possible irq lock inversion dependency detected 5.12.0-syzkaller #0 Not tainted -------------------------------------------------------- syz-executor132/8391 just changed the state of lock: ffff888015967bf8 (&f->f_owner.lock){.+..}-{2:2}, at: f_getown_ex fs/fcntl.c:211 [inline] ffff888015967bf8 (&f->f_owner.lock){.+..}-{2:2}, at: do_fcntl+0x8b4/0x1200 fs/fcntl.c:395 but this lock was taken by another, HARDIRQ-safe lock in the past: (&dev->event_lock){-...}-{2:2}
and interrupts could create inverse lock ordering between them.
other info that might help us debug this: Chain exists of: &dev->event_lock --> &new->fa_lock --> &f->f_owner.lock
Possible interrupt unsafe locking scenario:
CPU0 CPU1 ---- ---- lock(&f->f_owner.lock); local_irq_disable(); lock(&dev->event_lock); lock(&new->fa_lock); <Interrupt> lock(&dev->event_lock);
*** DEADLOCK ***
This happens because there is a lock hierarchy of &dev->event_lock --> &new->fa_lock --> &f->f_owner.lock from the following call chain:
input_inject_event(): spin_lock_irqsave(&dev->event_lock,...); input_handle_event(): input_pass_values(): input_to_handler(): evdev_events(): evdev_pass_values(): spin_lock(&client->buffer_lock); __pass_event(): kill_fasync(): kill_fasync_rcu(): read_lock(&fa->fa_lock); send_sigio(): read_lock_irqsave(&fown->lock,...);
However, since &dev->event_lock is HARDIRQ-safe, interrupts have to be disabled while grabbing &f->f_owner.lock, otherwise we invert the lock hierarchy.
Hence, we replace calls to read_lock/read_unlock on &f->f_owner.lock, with read_lock_irq/read_unlock_irq.
Reported-and-tested-by: syzbot+e6d5398a02c516ce5e70@syzkaller.appspotmail.com Signed-off-by: Desmond Cheong Zhi Xi desmondcheongzx@gmail.com Signed-off-by: Jeff Layton jlayton@kernel.org
Conflict: fs/fcntl.c Signed-off-by: Zhang Wensheng zhangwensheng5@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- fs/fcntl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/fcntl.c b/fs/fcntl.c index 3eebcbead8bf..3e05c8d4661b 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -149,11 +149,11 @@ void f_delown(struct file *filp) pid_t f_getown(struct file *filp) { pid_t pid; - read_lock(&filp->f_owner.lock); + read_lock_irq(&filp->f_owner.lock); pid = pid_vnr(filp->f_owner.pid); if (filp->f_owner.pid_type == PIDTYPE_PGID) pid = -pid; - read_unlock(&filp->f_owner.lock); + read_unlock_irq(&filp->f_owner.lock); return pid; }
@@ -203,7 +203,7 @@ static int f_getown_ex(struct file *filp, unsigned long arg) struct f_owner_ex owner; int ret = 0;
- read_lock(&filp->f_owner.lock); + read_lock_irq(&filp->f_owner.lock); owner.pid = pid_vnr(filp->f_owner.pid); switch (filp->f_owner.pid_type) { case PIDTYPE_PID: @@ -223,7 +223,7 @@ static int f_getown_ex(struct file *filp, unsigned long arg) ret = -EINVAL; break; } - read_unlock(&filp->f_owner.lock); + read_unlock_irq(&filp->f_owner.lock);
if (!ret) { ret = copy_to_user(owner_p, &owner, sizeof(owner)); @@ -241,10 +241,10 @@ static int f_getowner_uids(struct file *filp, unsigned long arg) uid_t src[2]; int err;
- read_lock(&filp->f_owner.lock); + read_lock_irq(&filp->f_owner.lock); src[0] = from_kuid(user_ns, filp->f_owner.uid); src[1] = from_kuid(user_ns, filp->f_owner.euid); - read_unlock(&filp->f_owner.lock); + read_unlock_irq(&filp->f_owner.lock);
err = put_user(src[0], &dst[0]); err |= put_user(src[1], &dst[1]);
From: Xu Kuohai xukuohai@huawei.com
hulk inclusion category: bugfix bugzilla: 185909 https://gitee.com/openeuler/kernel/issues/I4DDEL
--------------------------------
The unwind directives can't handle nested function entries, so only the outermost function __loop_udelay is annotated, and the inner nested entries share the same unwind info with __loop_udelay.
Signed-off-by: Xu Kuohai xukuohai@huawei.com Reviewed-by: Yang Jihong yangjihong1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm/lib/delay-loop.S | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm/lib/delay-loop.S b/arch/arm/lib/delay-loop.S index 3ccade0f8130..f0a076f9abc5 100644 --- a/arch/arm/lib/delay-loop.S +++ b/arch/arm/lib/delay-loop.S @@ -7,6 +7,7 @@ #include <linux/linkage.h> #include <asm/assembler.h> #include <asm/delay.h> +#include <asm/unwind.h>
.text
@@ -21,6 +22,7 @@ */
ENTRY(__loop_udelay) +UNWIND(.fnstart) ldr r2, .LC1 mul r0, r2, r0 @ r0 = delay_us * UDELAY_MULT ENTRY(__loop_const_udelay) @ 0 <= r0 <= 0xfffffaf0 @@ -54,6 +56,7 @@ ENTRY(__loop_delay) #endif bhi __loop_delay ret lr -ENDPROC(__loop_udelay) -ENDPROC(__loop_const_udelay) ENDPROC(__loop_delay) +ENDPROC(__loop_const_udelay) +UNWIND(.fnend) +ENDPROC(__loop_udelay)