]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.14/ipc-prevent-lockup-on-alloc_msg-and-free_msg.patch
a4503b38d5581276d9cc4bd6a60e51776f850568
[thirdparty/kernel/stable-queue.git] / queue-4.14 / ipc-prevent-lockup-on-alloc_msg-and-free_msg.patch
1 From 610e05b94be0dc59b8d30eb6991386c099fb5588 Mon Sep 17 00:00:00 2001
2 From: Li Rongqing <lirongqing@baidu.com>
3 Date: Tue, 14 May 2019 15:46:20 -0700
4 Subject: ipc: prevent lockup on alloc_msg and free_msg
5
6 [ Upstream commit d6a2946a88f524a47cc9b79279667137899db807 ]
7
8 msgctl10 of ltp triggers the following lockup When CONFIG_KASAN is
9 enabled on large memory SMP systems, the pages initialization can take a
10 long time, if msgctl10 requests a huge block memory, and it will block
11 rcu scheduler, so release cpu actively.
12
13 After adding schedule() in free_msg, free_msg can not be called when
14 holding spinlock, so adding msg to a tmp list, and free it out of
15 spinlock
16
17 rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
18 rcu: Tasks blocked on level-1 rcu_node (CPUs 16-31): P32505
19 rcu: Tasks blocked on level-1 rcu_node (CPUs 48-63): P34978
20 rcu: (detected by 11, t=35024 jiffies, g=44237529, q=16542267)
21 msgctl10 R running task 21608 32505 2794 0x00000082
22 Call Trace:
23 preempt_schedule_irq+0x4c/0xb0
24 retint_kernel+0x1b/0x2d
25 RIP: 0010:__is_insn_slot_addr+0xfb/0x250
26 Code: 82 1d 00 48 8b 9b 90 00 00 00 4c 89 f7 49 c1 ee 03 e8 59 83 1d 00 48 b8 00 00 00 00 00 fc ff df 4c 39 eb 48 89 9d 58 ff ff ff <41> c6 04 06 f8 74 66 4c 8d 75 98 4c 89 f1 48 c1 e9 03 48 01 c8 48
27 RSP: 0018:ffff88bce041f758 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff13
28 RAX: dffffc0000000000 RBX: ffffffff8471bc50 RCX: ffffffff828a2a57
29 RDX: dffffc0000000000 RSI: dffffc0000000000 RDI: ffff88bce041f780
30 RBP: ffff88bce041f828 R08: ffffed15f3f4c5b3 R09: ffffed15f3f4c5b3
31 R10: 0000000000000001 R11: ffffed15f3f4c5b2 R12: 000000318aee9b73
32 R13: ffffffff8471bc50 R14: 1ffff1179c083ef0 R15: 1ffff1179c083eec
33 kernel_text_address+0xc1/0x100
34 __kernel_text_address+0xe/0x30
35 unwind_get_return_address+0x2f/0x50
36 __save_stack_trace+0x92/0x100
37 create_object+0x380/0x650
38 __kmalloc+0x14c/0x2b0
39 load_msg+0x38/0x1a0
40 do_msgsnd+0x19e/0xcf0
41 do_syscall_64+0x117/0x400
42 entry_SYSCALL_64_after_hwframe+0x49/0xbe
43
44 rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
45 rcu: Tasks blocked on level-1 rcu_node (CPUs 0-15): P32170
46 rcu: (detected by 14, t=35016 jiffies, g=44237525, q=12423063)
47 msgctl10 R running task 21608 32170 32155 0x00000082
48 Call Trace:
49 preempt_schedule_irq+0x4c/0xb0
50 retint_kernel+0x1b/0x2d
51 RIP: 0010:lock_acquire+0x4d/0x340
52 Code: 48 81 ec c0 00 00 00 45 89 c6 4d 89 cf 48 8d 6c 24 20 48 89 3c 24 48 8d bb e4 0c 00 00 89 74 24 0c 48 c7 44 24 20 b3 8a b5 41 <48> c1 ed 03 48 c7 44 24 28 b4 25 18 84 48 c7 44 24 30 d0 54 7a 82
53 RSP: 0018:ffff88af83417738 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff13
54 RAX: dffffc0000000000 RBX: ffff88bd335f3080 RCX: 0000000000000002
55 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88bd335f3d64
56 RBP: ffff88af83417758 R08: 0000000000000000 R09: 0000000000000000
57 R10: 0000000000000001 R11: ffffed13f3f745b2 R12: 0000000000000000
58 R13: 0000000000000002 R14: 0000000000000000 R15: 0000000000000000
59 is_bpf_text_address+0x32/0xe0
60 kernel_text_address+0xec/0x100
61 __kernel_text_address+0xe/0x30
62 unwind_get_return_address+0x2f/0x50
63 __save_stack_trace+0x92/0x100
64 save_stack+0x32/0xb0
65 __kasan_slab_free+0x130/0x180
66 kfree+0xfa/0x2d0
67 free_msg+0x24/0x50
68 do_msgrcv+0x508/0xe60
69 do_syscall_64+0x117/0x400
70 entry_SYSCALL_64_after_hwframe+0x49/0xbe
71
72 Davidlohr said:
73 "So after releasing the lock, the msg rbtree/list is empty and new
74 calls will not see those in the newly populated tmp_msg list, and
75 therefore they cannot access the delayed msg freeing pointers, which
76 is good. Also the fact that the node_cache is now freed before the
77 actual messages seems to be harmless as this is wanted for
78 msg_insert() avoiding GFP_ATOMIC allocations, and after releasing the
79 info->lock the thing is freed anyway so it should not change things"
80
81 Link: http://lkml.kernel.org/r/1552029161-4957-1-git-send-email-lirongqing@baidu.com
82 Signed-off-by: Li RongQing <lirongqing@baidu.com>
83 Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
84 Reviewed-by: Davidlohr Bueso <dbueso@suse.de>
85 Cc: Manfred Spraul <manfred@colorfullife.com>
86 Cc: Arnd Bergmann <arnd@arndb.de>
87 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
88 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
89 Signed-off-by: Sasha Levin <sashal@kernel.org>
90 ---
91 ipc/mqueue.c | 10 ++++++++--
92 ipc/msgutil.c | 6 ++++++
93 2 files changed, 14 insertions(+), 2 deletions(-)
94
95 diff --git a/ipc/mqueue.c b/ipc/mqueue.c
96 index d24025626310..5c0ae912f2f2 100644
97 --- a/ipc/mqueue.c
98 +++ b/ipc/mqueue.c
99 @@ -374,7 +374,8 @@ static void mqueue_evict_inode(struct inode *inode)
100 struct user_struct *user;
101 unsigned long mq_bytes, mq_treesize;
102 struct ipc_namespace *ipc_ns;
103 - struct msg_msg *msg;
104 + struct msg_msg *msg, *nmsg;
105 + LIST_HEAD(tmp_msg);
106
107 clear_inode(inode);
108
109 @@ -385,10 +386,15 @@ static void mqueue_evict_inode(struct inode *inode)
110 info = MQUEUE_I(inode);
111 spin_lock(&info->lock);
112 while ((msg = msg_get(info)) != NULL)
113 - free_msg(msg);
114 + list_add_tail(&msg->m_list, &tmp_msg);
115 kfree(info->node_cache);
116 spin_unlock(&info->lock);
117
118 + list_for_each_entry_safe(msg, nmsg, &tmp_msg, m_list) {
119 + list_del(&msg->m_list);
120 + free_msg(msg);
121 + }
122 +
123 /* Total amount of bytes accounted for the mqueue */
124 mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) +
125 min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *
126 diff --git a/ipc/msgutil.c b/ipc/msgutil.c
127 index 84598025a6ad..e65593742e2b 100644
128 --- a/ipc/msgutil.c
129 +++ b/ipc/msgutil.c
130 @@ -18,6 +18,7 @@
131 #include <linux/utsname.h>
132 #include <linux/proc_ns.h>
133 #include <linux/uaccess.h>
134 +#include <linux/sched.h>
135
136 #include "util.h"
137
138 @@ -64,6 +65,9 @@ static struct msg_msg *alloc_msg(size_t len)
139 pseg = &msg->next;
140 while (len > 0) {
141 struct msg_msgseg *seg;
142 +
143 + cond_resched();
144 +
145 alen = min(len, DATALEN_SEG);
146 seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT);
147 if (seg == NULL)
148 @@ -176,6 +180,8 @@ void free_msg(struct msg_msg *msg)
149 kfree(msg);
150 while (seg != NULL) {
151 struct msg_msgseg *tmp = seg->next;
152 +
153 + cond_resched();
154 kfree(seg);
155 seg = tmp;
156 }
157 --
158 2.20.1
159