diff --git a/SOURCES/CVE-2022-3564.patch b/SOURCES/CVE-2022-3564.patch new file mode 100644 index 0000000..f9c4512 --- /dev/null +++ b/SOURCES/CVE-2022-3564.patch @@ -0,0 +1,248 @@ +From 63f63d3ce535ca59a9da05ba3004187033495b7d Mon Sep 17 00:00:00 2001 +From: Ryan Sullivan +Date: Mon, 23 Jan 2023 11:41:37 -0500 +Subject: [KPATCH CVE-2022-3564] kpatch fixes for CVE-2022-3564 + +Kernels: +3.10.0-1160.71.1.el7 +3.10.0-1160.76.1.el7 +3.10.0-1160.80.1.el7 +3.10.0-1160.81.1.el7 + + +Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-7/-/merge_requests/49 +Approved-by: Yannick Cote (@ycote1) +Approved-by: Joe Lawrence (@joe.lawrence) +Changes since last build: +[x86_64]: +l2cap_core.o: changed function: l2cap_data_channel +l2cap_core.o: changed function: l2cap_rx_state_recv +nf_tables_api.o: changed function: __nf_tables_abort +nf_tables_api.o: changed function: nf_tables_delsetelem +nf_tables_api.o: changed function: nf_tables_newset +nf_tables_api.o: changed function: nft_delrule +nf_tables_api.o: changed function: nft_set_destroy +nf_tables_api.o: changed function: nft_validate_register_store +nf_tables_api.o: new function: nf_tables_activate_set +nf_tables_api.o: new function: nf_tables_deactivate_set +nf_tables_api.o: new function: nft_rule_expr_deactivate +nft_dynset.o: new function: klp_is_nft_dynset +nft_dynset.o: new function: nft_dynset_activate +nft_dynset.o: new function: nft_dynset_deactivate +nft_lookup.o: new function: klp_is_nft_lookup +nft_lookup.o: new function: nft_lookup_activate +nft_lookup.o: new function: nft_lookup_deactivate + +[ppc64le]: +l2cap_core.o: changed function: l2cap_data_channel +l2cap_core.o: changed function: l2cap_rx_state_recv +nf_tables_api.o: changed function: __nf_tables_abort +nf_tables_api.o: changed function: nf_tables_bind_check_setelem +nf_tables_api.o: changed function: nf_tables_bind_set +nf_tables_api.o: changed function: nf_tables_commit +nf_tables_api.o: changed function: nf_tables_delrule +nf_tables_api.o: changed function: nf_tables_delsetelem +nf_tables_api.o: changed function: nf_tables_newset +nf_tables_api.o: changed function: nf_tables_unbind_set +nf_tables_api.o: changed function: nft_add_set_elem +nf_tables_api.o: changed function: nft_delrule_by_chain +nf_tables_api.o: changed function: nft_unregister_afinfo +nf_tables_api.o: changed function: nft_validate_register_store +nf_tables_api.o: new function: nf_tables_activate_set +nf_tables_api.o: new function: nf_tables_deactivate_set +nft_dynset.o: new function: klp_is_nft_dynset +nft_dynset.o: new function: nft_dynset_activate +nft_dynset.o: new function: nft_dynset_deactivate +nft_lookup.o: new function: klp_is_nft_lookup +nft_lookup.o: new function: nft_lookup_activate +nft_lookup.o: new function: nft_lookup_deactivate + +--------------------------- + +Modifications: none + +commit ce15ab7416bca0378f144b0aa9183abb532bfb7d +Author: Wander Lairson Costa +Date: Mon Jan 9 14:37:35 2023 -0300 + + Bluetooth: L2CAP: Fix use-after-free caused by l2cap_reassemble_sdu + + Bugzilla: https://bugzilla.redhat.com/2152941 + CVE: CVE-2022-3564 + + commit 3aff8aaca4e36dc8b17eaa011684881a80238966 + Author: Maxim Mikityanskiy + Date: Wed Oct 5 00:27:18 2022 +0300 + + Bluetooth: L2CAP: Fix use-after-free caused by l2cap_reassemble_sdu + + Fix the race condition between the following two flows that run in + parallel: + + 1. l2cap_reassemble_sdu -> chan->ops->recv (l2cap_sock_recv_cb) -> + __sock_queue_rcv_skb. + + 2. bt_sock_recvmsg -> skb_recv_datagram, skb_free_datagram. + + An SKB can be queued by the first flow and immediately dequeued and + freed by the second flow, therefore the callers of l2cap_reassemble_sdu + can't use the SKB after that function returns. However, some places + continue accessing struct l2cap_ctrl that resides in the SKB's CB for a + short time after l2cap_reassemble_sdu returns, leading to a + use-after-free condition (the stack trace is below, line numbers for + kernel 5.19.8). + + Fix it by keeping a local copy of struct l2cap_ctrl. + + BUG: KASAN: use-after-free in l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth + Read of size 1 at addr ffff88812025f2f0 by task kworker/u17:3/43169 + + Workqueue: hci0 hci_rx_work [bluetooth] + Call Trace: + + dump_stack_lvl (lib/dump_stack.c:107 (discriminator 4)) + print_report.cold (mm/kasan/report.c:314 mm/kasan/report.c:429) + ? l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth + kasan_report (mm/kasan/report.c:162 mm/kasan/report.c:493) + ? l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth + l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth + l2cap_rx (net/bluetooth/l2cap_core.c:7236 net/bluetooth/l2cap_core.c:7271) bluetooth + ret_from_fork (arch/x86/entry/entry_64.S:306) + + + Allocated by task 43169: + kasan_save_stack (mm/kasan/common.c:39) + __kasan_slab_alloc (mm/kasan/common.c:45 mm/kasan/common.c:436 mm/kasan/common.c:469) + kmem_cache_alloc_node (mm/slab.h:750 mm/slub.c:3243 mm/slub.c:3293) + __alloc_skb (net/core/skbuff.c:414) + l2cap_recv_frag (./include/net/bluetooth/bluetooth.h:425 net/bluetooth/l2cap_core.c:8329) bluetooth + l2cap_recv_acldata (net/bluetooth/l2cap_core.c:8442) bluetooth + hci_rx_work (net/bluetooth/hci_core.c:3642 net/bluetooth/hci_core.c:3832) bluetooth + process_one_work (kernel/workqueue.c:2289) + worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2437) + kthread (kernel/kthread.c:376) + ret_from_fork (arch/x86/entry/entry_64.S:306) + + Freed by task 27920: + kasan_save_stack (mm/kasan/common.c:39) + kasan_set_track (mm/kasan/common.c:45) + kasan_set_free_info (mm/kasan/generic.c:372) + ____kasan_slab_free (mm/kasan/common.c:368 mm/kasan/common.c:328) + slab_free_freelist_hook (mm/slub.c:1780) + kmem_cache_free (mm/slub.c:3536 mm/slub.c:3553) + skb_free_datagram (./include/net/sock.h:1578 ./include/net/sock.h:1639 net/core/datagram.c:323) + bt_sock_recvmsg (net/bluetooth/af_bluetooth.c:295) bluetooth + l2cap_sock_recvmsg (net/bluetooth/l2cap_sock.c:1212) bluetooth + sock_read_iter (net/socket.c:1087) + new_sync_read (./include/linux/fs.h:2052 fs/read_write.c:401) + vfs_read (fs/read_write.c:482) + ksys_read (fs/read_write.c:620) + do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) + + Link: https://lore.kernel.org/linux-bluetooth/CAKErNvoqga1WcmoR3-0875esY6TVWFQDandbVZncSiuGPBQXLA@mail.gmail.com/T/#u + Fixes: d2a7ac5d5d3a ("Bluetooth: Add the ERTM receive state machine") + Fixes: 4b51dae96731 ("Bluetooth: Add streaming mode receive and incoming packet classifier") + Signed-off-by: Maxim Mikityanskiy + Signed-off-by: Luiz Augusto von Dentz + + Signed-off-by: Wander Lairson Costa + +Signed-off-by: Ryan Sullivan +--- + net/bluetooth/l2cap_core.c | 48 ++++++++++++++++++++++++++++++++------ + 1 file changed, 41 insertions(+), 7 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 6e94fd907d89..4338810b0d58 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6197,6 +6197,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, + struct l2cap_ctrl *control, + struct sk_buff *skb, u8 event) + { ++ struct l2cap_ctrl local_control; + int err = 0; + bool skb_in_use = false; + +@@ -6221,15 +6222,32 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, + chan->buffer_seq = chan->expected_tx_seq; + skb_in_use = true; + ++ /* l2cap_reassemble_sdu may free skb, hence invalidate ++ * control, so make a copy in advance to use it after ++ * l2cap_reassemble_sdu returns and to avoid the race ++ * condition, for example: ++ * ++ * The current thread calls: ++ * l2cap_reassemble_sdu ++ * chan->ops->recv == l2cap_sock_recv_cb ++ * __sock_queue_rcv_skb ++ * Another thread calls: ++ * bt_sock_recvmsg ++ * skb_recv_datagram ++ * skb_free_datagram ++ * Then the current thread tries to access control, but ++ * it was freed by skb_free_datagram. ++ */ ++ local_control = *control; + err = l2cap_reassemble_sdu(chan, skb, control); + if (err) + break; + +- if (control->final) { ++ if (local_control.final) { + if (!test_and_clear_bit(CONN_REJ_ACT, + &chan->conn_state)) { +- control->final = 0; +- l2cap_retransmit_all(chan, control); ++ local_control.final = 0; ++ l2cap_retransmit_all(chan, &local_control); + l2cap_ertm_send(chan); + } + } +@@ -6609,11 +6627,27 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, + static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, + struct sk_buff *skb) + { ++ /* l2cap_reassemble_sdu may free skb, hence invalidate control, so store ++ * the txseq field in advance to use it after l2cap_reassemble_sdu ++ * returns and to avoid the race condition, for example: ++ * ++ * The current thread calls: ++ * l2cap_reassemble_sdu ++ * chan->ops->recv == l2cap_sock_recv_cb ++ * __sock_queue_rcv_skb ++ * Another thread calls: ++ * bt_sock_recvmsg ++ * skb_recv_datagram ++ * skb_free_datagram ++ * Then the current thread tries to access control, but it was freed by ++ * skb_free_datagram. ++ */ ++ u16 txseq = control->txseq; ++ + BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb, + chan->rx_state); + +- if (l2cap_classify_txseq(chan, control->txseq) == +- L2CAP_TXSEQ_EXPECTED) { ++ if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) { + l2cap_pass_to_tx(chan, control); + + BT_DBG("buffer_seq %d->%d", chan->buffer_seq, +@@ -6636,8 +6670,8 @@ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, + } + } + +- chan->last_acked_seq = control->txseq; +- chan->expected_tx_seq = __next_seq(chan, control->txseq); ++ chan->last_acked_seq = txseq; ++ chan->expected_tx_seq = __next_seq(chan, txseq); + + return 0; + } +-- +2.40.1 + + diff --git a/SOURCES/CVE-2023-32233.patch b/SOURCES/CVE-2023-32233.patch new file mode 100644 index 0000000..dbc84ca --- /dev/null +++ b/SOURCES/CVE-2023-32233.patch @@ -0,0 +1,442 @@ +From 7972a497548bcdfc7f3b6f24a1fd5e4b0e008fff Mon Sep 17 00:00:00 2001 +From: Ryan Sullivan +Date: Thu, 15 Jun 2023 10:43:28 -0400 +Subject: [KPATCH CVE-2023-32233] kpatch fixes for CVE-2023-32233 + +Kernels: +3.10.0-1160.81.1.el7 +3.10.0-1160.83.1.el7 +3.10.0-1160.88.1.el7 +3.10.0-1160.90.1.el7 +3.10.0-1160.92.1.el7 + + +Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-7/-/merge_requests/54 +Approved-by: Yannick Cote (@ycote1) +Approved-by: Joe Lawrence (@joe.lawrence) +Changes since last build: +[x86_64]: +l2cap_core.o: changed function: l2cap_data_channel +l2cap_core.o: changed function: l2cap_rx_state_recv +nf_tables_api.o: changed function: __nf_tables_abort +nf_tables_api.o: changed function: nf_tables_delsetelem +nf_tables_api.o: changed function: nf_tables_newset +nf_tables_api.o: changed function: nft_delrule +nf_tables_api.o: changed function: nft_set_destroy +nf_tables_api.o: changed function: nft_validate_register_store +nf_tables_api.o: new function: nf_tables_activate_set +nf_tables_api.o: new function: nf_tables_deactivate_set +nf_tables_api.o: new function: nft_rule_expr_deactivate +nft_dynset.o: new function: klp_is_nft_dynset +nft_dynset.o: new function: nft_dynset_activate +nft_dynset.o: new function: nft_dynset_deactivate +nft_lookup.o: new function: klp_is_nft_lookup +nft_lookup.o: new function: nft_lookup_activate +nft_lookup.o: new function: nft_lookup_deactivate + +[ppc64le]: +l2cap_core.o: changed function: l2cap_data_channel +l2cap_core.o: changed function: l2cap_rx_state_recv +nf_tables_api.o: changed function: __nf_tables_abort +nf_tables_api.o: changed function: nf_tables_bind_check_setelem +nf_tables_api.o: changed function: nf_tables_bind_set +nf_tables_api.o: changed function: nf_tables_commit +nf_tables_api.o: changed function: nf_tables_delrule +nf_tables_api.o: changed function: nf_tables_delsetelem +nf_tables_api.o: changed function: nf_tables_newset +nf_tables_api.o: changed function: nf_tables_unbind_set +nf_tables_api.o: changed function: nft_add_set_elem +nf_tables_api.o: changed function: nft_delrule_by_chain +nf_tables_api.o: changed function: nft_unregister_afinfo +nf_tables_api.o: changed function: nft_validate_register_store +nf_tables_api.o: new function: nf_tables_activate_set +nf_tables_api.o: new function: nf_tables_deactivate_set +nft_dynset.o: new function: klp_is_nft_dynset +nft_dynset.o: new function: nft_dynset_activate +nft_dynset.o: new function: nft_dynset_deactivate +nft_lookup.o: new function: klp_is_nft_lookup +nft_lookup.o: new function: nft_lookup_activate +nft_lookup.o: new function: nft_lookup_deactivate + +--------------------------- + +Modifications: +- Removes prototype definitions of nf_tables_activate_set() and +nf_tables_deactivate_set() from nf_tables.h and moves them into the +affected files above when they are called + +- Adds optimization attribute "-fno-optimize-sibling-calls" to the +nf_tables_deactivate_set() + +- Removes definitions/edits of the policy and removed fields from the +nft_set struct instead using a shadow variable +(ID = KLP_CVE_2023_32233), created in nf_tables_newset() and +destroyed in nft_set_destroy() + +- Removes .activate and .deactivate from nft_(dynset/lookup)_ops and +instead changes nft_rule_expr_(activate/deactivate) to directly call +activate and deactivate functions from within them + +commit ffb7eb4b21c69f2b5e084c85b37eb033544e3fc9 +Author: Florian Westphal +Date: Tue May 16 13:34:35 2023 +0200 + + netfilter: nf_tables: deactivate anonymous set from preparation phase + + Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2196159 + Upstream Status: commit c1592a89942e9 + CVE: CVE-2023-32233 + Conflicts: everywhere + Tested: nftables v0.8 shell/py tests + + A rule like + + ip saddr { 1.2.3.4, 5.6.7.8 } accept + + consists of multiple expressions and a set (the part in { }). + + This set only has a auto-assigned name "__set%d" hidden from + userspace view, but its still internally referenceable this way. + + Such "anonymous" sets are owned by the rule that use it. + Rule deletion auto-removes the set as well. + + Unfortunately userspace can craft a transaction that first + deletes the rule and then attempts an operation on the anon + set, such as deleting it or deleting an element from the set. + + Upstream patch uses existing delete/activate callbacks to disable + the set in the new generation (the "preview" of the future ruleset). + This makes such attempt at (re)using the set fail because the set + won't be visible anymore. + + In RHEL7 we cannot mark the set as inactive in next generation + because neither sets nor set elements have such a generation bit mask. + + This backport adds minimal bits from + 408070d6ee3490 "netfilter: nf_tables: add nft_set_is_anonymous() helper" + bb7b40aecbf778 "netfilter: nf_tables: bogus EBUSY in chain deletions" + cd5125d8f51882 "netfilter: nf_tables: split set destruction in deactivate and destroy phase" + + for the necessary infrastructure to mark anon sets as + "to be removed" from transaction preparation phase. + + Introduce an explicit "removed" bit flag that is set once the nft_lookup + or dynset expression referencing an anonymous set gets scheduled for + removal in the transaction phase. + + This can then be detected in a subsequent DELSETEM attempt and + an error can be returned. + + commit c1592a89942e9678f7d9c8030efa777c0d57edab + Author: Pablo Neira Ayuso + Date: Tue May 2 10:25:24 2023 +0200 + + netfilter: nf_tables: deactivate anonymous set from preparation phase + + Toggle deleted anonymous sets as inactive in the next generation, so + users cannot perform any update on it. Clear the generation bitmask + in case the transaction is aborted. + + The following KASAN splat shows a set element deletion for a bound + anonymous set that has been already removed in the same transaction. + + [ 64.921510] ================================================================== + [ 64.923123] BUG: KASAN: wild-memory-access in nf_tables_commit+0xa24/0x1490 [nf_tables] + [ 64.924745] Write of size 8 at addr dead000000000122 by task test/890 + [ 64.927903] CPU: 3 PID: 890 Comm: test Not tainted 6.3.0+ #253 + [ 64.931120] Call Trace: + [ 64.932699] + [ 64.934292] dump_stack_lvl+0x33/0x50 + [ 64.935908] ? nf_tables_commit+0xa24/0x1490 [nf_tables] + [ 64.937551] kasan_report+0xda/0x120 + [ 64.939186] ? nf_tables_commit+0xa24/0x1490 [nf_tables] + [ 64.940814] nf_tables_commit+0xa24/0x1490 [nf_tables] + [ 64.942452] ? __kasan_slab_alloc+0x2d/0x60 + [ 64.944070] ? nf_tables_setelem_notify+0x190/0x190 [nf_tables] + [ 64.945710] ? kasan_set_track+0x21/0x30 + [ 64.947323] nfnetlink_rcv_batch+0x709/0xd90 [nfnetlink] + [ 64.948898] ? nfnetlink_rcv_msg+0x480/0x480 [nfnetlink] + + Signed-off-by: Pablo Neira Ayuso + + Signed-off-by: Florian Westphal + +Signed-off-by: Ryan Sullivan +--- + net/netfilter/nf_tables_api.c | 97 ++++++++++++++++++++++++++++++++++- + net/netfilter/nft_dynset.c | 26 ++++++++++ + net/netfilter/nft_lookup.c | 26 ++++++++++ + 3 files changed, 147 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 44738b987690..feff3b92a617 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -20,6 +20,9 @@ + #include + #include + #include ++#include ++ ++#define KLP_CVE_2023_32233 0x2022101200000111 + + static LIST_HEAD(nf_tables_expressions); + +@@ -260,6 +263,50 @@ static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) + rule->genmask &= ~nft_genmask_next(net); + } + ++extern void nft_dynset_deactivate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr); ++extern void nft_dynset_activate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr); ++extern int klp_is_nft_dynset(const struct nft_expr *expr); ++ ++extern void nft_lookup_deactivate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr); ++extern void nft_lookup_activate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr); ++extern int klp_is_nft_lookup(const struct nft_expr *expr); ++ ++static void nft_rule_expr_activate(const struct nft_ctx *ctx, ++ struct nft_rule *rule) ++{ ++ struct nft_expr *expr; ++ ++ expr = nft_expr_first(rule); ++ while (expr != nft_expr_last(rule) && expr->ops) { ++ if (klp_is_nft_dynset(expr)) ++ nft_dynset_activate(ctx, expr); ++ else if (klp_is_nft_lookup(expr)) ++ nft_lookup_activate(ctx, expr); ++ ++ expr = nft_expr_next(expr); ++ } ++} ++ ++static void nft_rule_expr_deactivate(const struct nft_ctx *ctx, ++ struct nft_rule *rule) ++{ ++ struct nft_expr *expr; ++ ++ expr = nft_expr_first(rule); ++ while (expr != nft_expr_last(rule) && expr->ops) { ++ if (klp_is_nft_dynset(expr)) ++ nft_dynset_deactivate(ctx, expr); ++ else if (klp_is_nft_lookup(expr)) ++ nft_lookup_deactivate(ctx, expr); ++ ++ expr = nft_expr_next(expr); ++ } ++} ++ + static int + nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule) + { +@@ -301,6 +348,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule) + nft_trans_destroy(trans); + return err; + } ++ nft_rule_expr_deactivate(ctx, rule); + + return 0; + } +@@ -2736,6 +2784,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, + unsigned char *udata; + u16 udlen; + int err; ++ u16 *klp_removed; + + if (nla[NFTA_SET_TABLE] == NULL || + nla[NFTA_SET_NAME] == NULL || +@@ -2861,10 +2910,16 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, + if (set == NULL) + goto err1; + ++ klp_removed = klp_shadow_alloc(set, KLP_CVE_2023_32233, ++ sizeof(*klp_removed), GFP_KERNEL, ++ NULL, NULL); ++ if(!klp_removed) ++ goto err2; ++ + nla_strlcpy(name, nla[NFTA_SET_NAME], sizeof(set->name)); + err = nf_tables_set_alloc_name(&ctx, set, name); + if (err < 0) +- goto err2; ++ goto klp_err; + + udata = NULL; + if (udlen) { +@@ -2889,7 +2944,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, + + err = ops->init(set, &desc, nla); + if (err < 0) +- goto err2; ++ goto klp_err; + + err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set); + if (err < 0) +@@ -2901,6 +2956,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, + + err3: + ops->destroy(set); ++klp_err: ++ klp_shadow_free(set, KLP_CVE_2023_32233, NULL); + err2: + kfree(set); + err1: +@@ -2910,6 +2967,7 @@ err1: + + static void nft_set_destroy(struct nft_set *set) + { ++ klp_shadow_free(set, KLP_CVE_2023_32233, NULL); + set->ops->destroy(set); + module_put(set->ops->owner); + kfree(set); +@@ -3013,6 +3071,34 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, + nf_tables_set_destroy(ctx, set); + } + ++static inline bool nft_set_is_anonymous(const struct nft_set *set) ++{ ++ return set->flags & NFT_SET_ANONYMOUS; ++} ++ ++void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set) ++{ ++ u16 *klp_removed; ++ ++ if (nft_set_is_anonymous(set)) { ++ klp_removed = klp_shadow_get(set, KLP_CVE_2023_32233); ++ if(klp_removed) ++ *klp_removed = 0; ++ } ++} ++ ++__attribute__((optimize("-fno-optimize-sibling-calls"))) ++void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set, ++ struct nft_set_binding *binding) ++{ ++ u16 *klp_removed; ++ klp_removed = klp_shadow_get(set, KLP_CVE_2023_32233); ++ if (nft_set_is_anonymous(set)) { ++ if(klp_removed) ++ *klp_removed = 1; ++ } ++} ++ + const struct nft_set_ext_type nft_set_ext_types[] = { + [NFT_SET_EXT_KEY] = { + .align = __alignof__(u32), +@@ -3705,6 +3791,7 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, + struct nft_set *set; + struct nft_ctx ctx; + int rem, err = 0; ++ u16 *klp_removed; + + err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla); + if (err < 0) +@@ -3716,6 +3803,10 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, + if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT) + return -EBUSY; + ++ klp_removed = klp_shadow_get(set, KLP_CVE_2023_32233); ++ if (klp_removed && *klp_removed) ++ return -ENOENT; ++ + if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) { + struct nft_set_dump_args args = { + .iter = { +@@ -4152,11 +4243,13 @@ static int __nf_tables_abort(struct net *net) + break; + case NFT_MSG_NEWRULE: + trans->ctx.chain->use--; ++ nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans)); + list_del_rcu(&nft_trans_rule(trans)->list); + break; + case NFT_MSG_DELRULE: + trans->ctx.chain->use++; + nft_rule_clear(trans->ctx.net, nft_trans_rule(trans)); ++ nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans)); + nft_trans_destroy(trans); + break; + case NFT_MSG_NEWSET: +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index 0cf187230050..4d6d3af26a5b 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -204,6 +204,32 @@ err1: + return err; + } + ++void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set, ++ struct nft_set_binding *binding); ++ ++void nft_dynset_deactivate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr) ++{ ++ struct nft_dynset *priv = nft_expr_priv(expr); ++ ++ nf_tables_deactivate_set(ctx, priv->set, &priv->binding); ++} ++ ++void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set); ++ ++void nft_dynset_activate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr) ++{ ++ struct nft_dynset *priv = nft_expr_priv(expr); ++ ++ nf_tables_activate_set(ctx, priv->set); ++} ++ ++int klp_is_nft_dynset(const struct nft_expr *expr) ++{ ++ return expr->ops->type == &nft_dynset_type; ++} ++ + static void nft_dynset_destroy(const struct nft_ctx *ctx, + const struct nft_expr *expr) + { +diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c +index c9ce7d60cd73..ab98a5cb7128 100644 +--- a/net/netfilter/nft_lookup.c ++++ b/net/netfilter/nft_lookup.c +@@ -125,6 +125,32 @@ static int nft_lookup_init(const struct nft_ctx *ctx, + return 0; + } + ++void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set, ++ struct nft_set_binding *binding); ++ ++void nft_lookup_deactivate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr) ++{ ++ struct nft_lookup *priv = nft_expr_priv(expr); ++ ++ nf_tables_deactivate_set(ctx, priv->set, &priv->binding); ++} ++ ++void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set); ++ ++void nft_lookup_activate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr) ++{ ++ struct nft_lookup *priv = nft_expr_priv(expr); ++ ++ nf_tables_activate_set(ctx, priv->set); ++} ++ ++int klp_is_nft_lookup(const struct nft_expr *expr) ++{ ++ return expr->ops->type == &nft_lookup_type; ++} ++ + static void nft_lookup_destroy(const struct nft_ctx *ctx, + const struct nft_expr *expr) + { +-- +2.40.1 + + diff --git a/SPECS/kpatch-patch.spec b/SPECS/kpatch-patch.spec index 2bb6cd0..e7cc537 100644 --- a/SPECS/kpatch-patch.spec +++ b/SPECS/kpatch-patch.spec @@ -6,13 +6,19 @@ %define kernel_ver 3.10.0-1160.83.1.el7 %define kpatch_ver 0.9.2 %define rpm_ver 1 -%define rpm_rel 1 +%define rpm_rel 2 %if !%{empty_package} # Patch sources below. DO NOT REMOVE THIS LINE. # # https://bugzilla.redhat.com/2152592 Source100: CVE-2022-4378.patch +# +# https://bugzilla.redhat.com/2153001 +Source101: CVE-2022-3564.patch +# +# https://bugzilla.redhat.com/2196588 +Source102: CVE-2023-32233.patch # End of patch sources. DO NOT REMOVE THIS LINE. %endif @@ -147,6 +153,10 @@ It is only a method to subscribe to the kpatch stream for kernel-%{kernel_ver}. %endif %changelog +* Wed Jul 05 2023 Yannick Cote [1-2.el7] +- kernel: netfilter: use-after-free in nf_tables when processing batch requests can lead to privilege escalation [2196588] {CVE-2023-32233} +- kernel: use-after-free caused by l2cap_reassemble_sdu() in net/bluetooth/l2cap_core.c [2153001] {CVE-2022-3564} + * Tue Feb 21 2023 Yannick Cote [1-1.el7] - kernel: stack overflow in do_proc_dointvec and proc_skip_spaces [2152592] {CVE-2022-4378}