Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.rhelver
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RHEL_MINOR = 10
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 553.87.1
RHEL_RELEASE = 553.89.1

#
# ZSTREAM
Expand Down
203 changes: 203 additions & 0 deletions ciq/ciq_backports/kernel-4.18.0-553.89.1.el8_10/3b8abb32.failed
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
mm: kmem: fix a NULL pointer dereference in obj_stock_flush_required()

jira KERNEL-325
cve CVE-2023-53401
Rebuild_History Non-Buildable kernel-4.18.0-553.89.1.el8_10
commit-author Roman Gushchin <roman.gushchin@linux.dev>
commit 3b8abb3239530c423c0b97e42af7f7e856e1ee96
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
Will be included in final tarball splat. Ref for failed cherry-pick at:
ciq/ciq_backports/kernel-4.18.0-553.89.1.el8_10/3b8abb32.failed

KCSAN found an issue in obj_stock_flush_required():
stock->cached_objcg can be reset between the check and dereference:

==================================================================
BUG: KCSAN: data-race in drain_all_stock / drain_obj_stock

write to 0xffff888237c2a2f8 of 8 bytes by task 19625 on cpu 0:
drain_obj_stock+0x408/0x4e0 mm/memcontrol.c:3306
refill_obj_stock+0x9c/0x1e0 mm/memcontrol.c:3340
obj_cgroup_uncharge+0xe/0x10 mm/memcontrol.c:3408
memcg_slab_free_hook mm/slab.h:587 [inline]
__cache_free mm/slab.c:3373 [inline]
__do_kmem_cache_free mm/slab.c:3577 [inline]
kmem_cache_free+0x105/0x280 mm/slab.c:3602
__d_free fs/dcache.c:298 [inline]
dentry_free fs/dcache.c:375 [inline]
__dentry_kill+0x422/0x4a0 fs/dcache.c:621
dentry_kill+0x8d/0x1e0
dput+0x118/0x1f0 fs/dcache.c:913
__fput+0x3bf/0x570 fs/file_table.c:329
____fput+0x15/0x20 fs/file_table.c:349
task_work_run+0x123/0x160 kernel/task_work.c:179
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
exit_to_user_mode_loop+0xcf/0xe0 kernel/entry/common.c:171
exit_to_user_mode_prepare+0x6a/0xa0 kernel/entry/common.c:203
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x26/0x140 kernel/entry/common.c:296
do_syscall_64+0x4d/0xc0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd

read to 0xffff888237c2a2f8 of 8 bytes by task 19632 on cpu 1:
obj_stock_flush_required mm/memcontrol.c:3319 [inline]
drain_all_stock+0x174/0x2a0 mm/memcontrol.c:2361
try_charge_memcg+0x6d0/0xd10 mm/memcontrol.c:2703
try_charge mm/memcontrol.c:2837 [inline]
mem_cgroup_charge_skmem+0x51/0x140 mm/memcontrol.c:7290
sock_reserve_memory+0xb1/0x390 net/core/sock.c:1025
sk_setsockopt+0x800/0x1e70 net/core/sock.c:1525
udp_lib_setsockopt+0x99/0x6c0 net/ipv4/udp.c:2692
udp_setsockopt+0x73/0xa0 net/ipv4/udp.c:2817
sock_common_setsockopt+0x61/0x70 net/core/sock.c:3668
__sys_setsockopt+0x1c3/0x230 net/socket.c:2271
__do_sys_setsockopt net/socket.c:2282 [inline]
__se_sys_setsockopt net/socket.c:2279 [inline]
__x64_sys_setsockopt+0x66/0x80 net/socket.c:2279
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd

value changed: 0xffff8881382d52c0 -> 0xffff888138893740

Reported by Kernel Concurrency Sanitizer on:
CPU: 1 PID: 19632 Comm: syz-executor.0 Not tainted 6.3.0-rc2-syzkaller-00387-g534293368afa #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/02/2023

Fix it by using READ_ONCE()/WRITE_ONCE() for all accesses to
stock->cached_objcg.

Link: https://lkml.kernel.org/r/20230502160839.361544-1-roman.gushchin@linux.dev
Fixes: bf4f059954dc ("mm: memcg/slab: obj_cgroup API")
Signed-off-by: Roman Gushchin <roman.gushchin@linux.dev>
Reported-by: syzbot+774c29891415ab0fd29d@syzkaller.appspotmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Link: https://lore.kernel.org/linux-mm/CACT4Y+ZfucZhM60YPphWiCLJr6+SGFhT+jjm8k1P-a_8Kkxsjg@mail.gmail.com/T/#t
Reviewed-by: Yosry Ahmed <yosryahmed@google.com>
Acked-by: Shakeel Butt <shakeelb@google.com>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 3b8abb3239530c423c0b97e42af7f7e856e1ee96)
Signed-off-by: Jonathan Maple <jmaple@ciq.com>

# Conflicts:
# mm/memcontrol.c
diff --cc mm/memcontrol.c
index 6e2a077af4c1,c823c35c2ed4..000000000000
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@@ -3272,8 -3208,8 +3272,13 @@@ void mod_objcg_state(struct obj_cgroup
* accumulating over a page of vmstat data or when pgdat or idx
* changes.
*/
++<<<<<<< HEAD
+ if (stock->cached_objcg != objcg) {
+ drain_obj_stock(stock);
++=======
+ if (READ_ONCE(stock->cached_objcg) != objcg) {
+ old = drain_obj_stock(stock);
++>>>>>>> 3b8abb323953 (mm: kmem: fix a NULL pointer dereference in obj_stock_flush_required())
obj_cgroup_get(objcg);
stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
? atomic_xchg(&objcg->nr_charged_bytes, 0) : 0;
@@@ -3322,11 -3260,14 +3327,18 @@@

static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)
{
- struct memcg_stock_pcp *stock;
unsigned long flags;
+ struct obj_stock *stock = get_obj_stock(&flags);
bool ret = false;

++<<<<<<< HEAD
+ if (objcg == stock->cached_objcg && stock->nr_bytes >= nr_bytes) {
++=======
+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
+
+ stock = this_cpu_ptr(&memcg_stock);
+ if (objcg == READ_ONCE(stock->cached_objcg) && stock->nr_bytes >= nr_bytes) {
++>>>>>>> 3b8abb323953 (mm: kmem: fix a NULL pointer dereference in obj_stock_flush_required())
stock->nr_bytes -= nr_bytes;
ret = true;
}
@@@ -3336,12 -3277,12 +3348,12 @@@
return ret;
}

-static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
+static void drain_obj_stock(struct obj_stock *stock)
{
- struct obj_cgroup *old = stock->cached_objcg;
+ struct obj_cgroup *old = READ_ONCE(stock->cached_objcg);

if (!old)
- return NULL;
+ return;

if (stock->nr_bytes) {
unsigned int nr_pages = stock->nr_bytes >> PAGE_SHIFT;
@@@ -3383,22 -3332,22 +3395,37 @@@
stock->cached_pgdat = NULL;
}

++<<<<<<< HEAD
+ obj_cgroup_put(old);
+ stock->cached_objcg = NULL;
++=======
+ WRITE_ONCE(stock->cached_objcg, NULL);
+ /*
+ * The `old' objects needs to be released by the caller via
+ * obj_cgroup_put() outside of memcg_stock_pcp::stock_lock.
+ */
+ return old;
++>>>>>>> 3b8abb323953 (mm: kmem: fix a NULL pointer dereference in obj_stock_flush_required())
}

static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
struct mem_cgroup *root_memcg)
{
+ struct obj_cgroup *objcg = READ_ONCE(stock->cached_objcg);
struct mem_cgroup *memcg;

++<<<<<<< HEAD
+ if (in_task() && stock->task_obj.cached_objcg) {
+ memcg = obj_cgroup_memcg(stock->task_obj.cached_objcg);
+ if (memcg && mem_cgroup_is_descendant(memcg, root_memcg))
+ return true;
+ }
+ if (stock->irq_obj.cached_objcg) {
+ memcg = obj_cgroup_memcg(stock->irq_obj.cached_objcg);
++=======
+ if (objcg) {
+ memcg = obj_cgroup_memcg(objcg);
++>>>>>>> 3b8abb323953 (mm: kmem: fix a NULL pointer dereference in obj_stock_flush_required())
if (memcg && mem_cgroup_is_descendant(memcg, root_memcg))
return true;
}
@@@ -3409,14 -3358,18 +3436,22 @@@
static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
bool allow_uncharge)
{
- struct memcg_stock_pcp *stock;
- struct obj_cgroup *old = NULL;
unsigned long flags;
+ struct obj_stock *stock = get_obj_stock(&flags);
unsigned int nr_pages = 0;

++<<<<<<< HEAD
+ if (stock->cached_objcg != objcg) { /* reset if necessary */
+ drain_obj_stock(stock);
++=======
+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
+
+ stock = this_cpu_ptr(&memcg_stock);
+ if (READ_ONCE(stock->cached_objcg) != objcg) { /* reset if necessary */
+ old = drain_obj_stock(stock);
++>>>>>>> 3b8abb323953 (mm: kmem: fix a NULL pointer dereference in obj_stock_flush_required())
obj_cgroup_get(objcg);
- stock->cached_objcg = objcg;
+ WRITE_ONCE(stock->cached_objcg, objcg);
stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
? atomic_xchg(&objcg->nr_charged_bytes, 0) : 0;
allow_uncharge = true; /* Allow uncharge when objcg changes */
* Unmerged path mm/memcontrol.c
90 changes: 90 additions & 0 deletions ciq/ciq_backports/kernel-4.18.0-553.89.1.el8_10/5d122db2.failed
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
RDMA/rxe: Fix incomplete state save in rxe_requester

jira KERNEL-325
cve CVE-2023-53539
Rebuild_History Non-Buildable kernel-4.18.0-553.89.1.el8_10
commit-author Bob Pearson <rpearsonhpe@gmail.com>
commit 5d122db2ff80cd2aed4dcd630befb56b51ddf947
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
Will be included in final tarball splat. Ref for failed cherry-pick at:
ciq/ciq_backports/kernel-4.18.0-553.89.1.el8_10/5d122db2.failed

If a send packet is dropped by the IP layer in rxe_requester()
the call to rxe_xmit_packet() can fail with err == -EAGAIN.
To recover, the state of the wqe is restored to the state before
the packet was sent so it can be resent. However, the routines
that save and restore the state miss a significnt part of the
variable state in the wqe, the dma struct which is used to process
through the sge table. And, the state is not saved before the packet
is built which modifies the dma struct.

Under heavy stress testing with many QPs on a fast node sending
large messages to a slow node dropped packets are observed and
the resent packets are corrupted because the dma struct was not
restored. This patch fixes this behavior and allows the test cases
to succeed.

Fixes: 3050b9985024 ("IB/rxe: Fix race condition between requester and completer")
Link: https://lore.kernel.org/r/20230721200748.4604-1-rpearsonhpe@gmail.com
Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
(cherry picked from commit 5d122db2ff80cd2aed4dcd630befb56b51ddf947)
Signed-off-by: Jonathan Maple <jmaple@ciq.com>

# Conflicts:
# drivers/infiniband/sw/rxe/rxe_req.c
diff --cc drivers/infiniband/sw/rxe/rxe_req.c
index f63771207970,d8c41fd626a9..000000000000
--- a/drivers/infiniband/sw/rxe/rxe_req.c
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@@ -746,9 -799,12 +748,12 @@@ int rxe_requester(void *arg
pkt.mask = rxe_opcode[opcode].mask;
pkt.wqe = wqe;

+ /* save wqe state before we build and send packet */
+ save_state(wqe, qp, &rollback_wqe, &rollback_psn);
+
av = rxe_get_av(&pkt, &ah);
if (unlikely(!av)) {
- rxe_dbg_qp(qp, "Failed no address vector\n");
+ pr_err("qp#%d Failed no address vector\n", qp_num(qp));
wqe->status = IB_WC_LOC_QP_OP_ERR;
goto err;
}
@@@ -790,17 -840,23 +789,33 @@@

err = rxe_xmit_packet(qp, &pkt, skb);
if (err) {
++<<<<<<< HEAD
+ qp->need_req_skb = 1;
+
+ rollback_state(wqe, qp, &rollback_wqe, rollback_psn);
+
+ if (err == -EAGAIN) {
+ rxe_run_task(&qp->req.task, 1);
+ goto exit;
++=======
+ if (err != -EAGAIN) {
+ wqe->status = IB_WC_LOC_QP_OP_ERR;
+ goto err;
++>>>>>>> 5d122db2ff80 (RDMA/rxe: Fix incomplete state save in rxe_requester)
}

- wqe->status = IB_WC_LOC_QP_OP_ERR;
- goto err;
+ /* the packet was dropped so reset wqe to the state
+ * before we sent it so we can try to resend
+ */
+ rollback_state(wqe, qp, &rollback_wqe, rollback_psn);
+
+ /* force a delay until the dropped packet is freed and
+ * the send queue is drained below the low water mark
+ */
+ qp->need_req_skb = 1;
+
+ rxe_sched_task(&qp->req.task);
+ goto exit;
}

update_state(qp, &pkt);
* Unmerged path drivers/infiniband/sw/rxe/rxe_req.c
Loading