diff --git a/.gitignore b/.gitignore index e69de29..19a7bb3 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/kernel-3.10.0-1160.88.1.el7.src.rpm +SOURCES/v0.9.2.tar.gz diff --git a/.kpatch-patch-3_10_0-1160_88_1.metadata b/.kpatch-patch-3_10_0-1160_88_1.metadata index e69de29..d686250 100644 --- a/.kpatch-patch-3_10_0-1160_88_1.metadata +++ b/.kpatch-patch-3_10_0-1160_88_1.metadata @@ -0,0 +1,2 @@ +461e3e5abdf0ea335327da02c52d88a65af1a2e5 SOURCES/kernel-3.10.0-1160.88.1.el7.src.rpm +c0878679129add77d6fff57093640892ad941155 SOURCES/v0.9.2.tar.gz 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/SOURCES/v0.9.2-backport-MR-1200-Make-sure-section-symbols-ex.patch b/SOURCES/v0.9.2-backport-MR-1200-Make-sure-section-symbols-ex.patch new file mode 100644 index 0000000..2aec990 --- /dev/null +++ b/SOURCES/v0.9.2-backport-MR-1200-Make-sure-section-symbols-ex.patch @@ -0,0 +1,83 @@ +From c1a07a5329c0b7db0ec54eea093e5d2d77735c06 Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Fri, 9 Dec 2022 15:37:49 -0500 +Subject: [PATCH] v0.9.2 backport: MR!1200 ("Make sure section symbols exist") +Content-type: text/plain + +commit 5622e3cc3d393fd77866b9838d16cd064de6fba5 +Author: Artem Savkov +Date: Fri Jun 18 10:59:26 2021 +0200 + + Make sure section symbols exist + + Binutils recently became much more aggressive about removing unused + section symbols. Since we can not rely on those being available anymore + add additional checks before using them. + + Fixes: #1193 + + Signed-off-by: Artem Savkov + +Fixes: KLP-216 ("Backport kpatch-build section symbol check") +Signed-off-by: Joe Lawrence +--- + kpatch-build/create-diff-object.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index c9afe33bbdae..94879b5fce6a 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -1241,7 +1241,8 @@ static void kpatch_correlate_static_local_variables(struct kpatch_elf *base, + if (bundled && sym->sec->twin) { + UNCORRELATE_ELEMENT(sym->sec); + +- UNCORRELATE_ELEMENT(sym->sec->secsym); ++ if (sym->sec->secsym) ++ UNCORRELATE_ELEMENT(sym->sec->secsym); + + if (sym->sec->rela) + UNCORRELATE_ELEMENT(sym->sec->rela); +@@ -1744,7 +1745,7 @@ static int kpatch_include_callback_elements(struct kpatch_elf *kelf) + sym = rela->sym; + log_normal("found callback: %s\n",sym->name); + kpatch_include_symbol(sym); +- } else { ++ } else if (sec->secsym) { + sec->secsym->include = 1; + } + } +@@ -1772,7 +1773,8 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf) + sec->include = 1; + if (!is_rela_section(sec)) { + /* .kpatch.force */ +- sec->secsym->include = 1; ++ if (sec->secsym) ++ sec->secsym->include = 1; + continue; + } + /* .rela.kpatch.force */ +@@ -2381,7 +2383,8 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf, + sec->include = 1; + sec->base->include = 1; + /* include secsym so .kpatch.arch relas can point to section symbols */ +- sec->base->secsym->include = 1; ++ if (sec->base->secsym) ++ sec->base->secsym->include = 1; + + /* + * Update text section data buf and size. +@@ -2564,7 +2567,9 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) + * from the section data comparison, but this is a simpler way. + */ + strsec->include = 1; +- strsec->secsym->include = 1; ++ if (strsec->secsym) ++ strsec->secsym->include = 1; ++ + name = strsec->data->d_buf + rela->addend; + ignoresec = find_section_by_name(&kelf->sections, name); + if (!ignoresec) +-- +2.38.1 + diff --git a/SOURCES/v0.9.2-backport-MR-1281-create-diff-object-add-suppo.patch b/SOURCES/v0.9.2-backport-MR-1281-create-diff-object-add-suppo.patch new file mode 100644 index 0000000..38ef70c --- /dev/null +++ b/SOURCES/v0.9.2-backport-MR-1281-create-diff-object-add-suppo.patch @@ -0,0 +1,54 @@ +From d98f100dc979f87296ec88b63a0d506aaf4cd2bd Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Thu, 8 Dec 2022 12:31:17 -0500 +Subject: [PATCH] v0.9.2 backport: MR!1281 ("create-diff-object: add support + for .return_sites section (x86)") +Content-type: text/plain + +commit 33368a88cdf875b0edd02b0dfd3356a7e93b24db +Author: Jonathan Dobson +Date: Sat Jul 16 15:46:54 2022 -0600 + + create-diff-object: add support for .return_sites section (x86) + + Conflicts: + kpatch-build/create-diff-object.c + - Manually apply patch to avoid diff context, v0.9.2 structure + special_section structure doesn't have .arch + +Signed-off-by: Joe Lawrence +--- + kpatch-build/create-diff-object.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index cee8adf333dc..c9afe33bbdae 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -1991,6 +1991,11 @@ static int altinstructions_group_size(struct kpatch_elf *kelf, int offset) + return size; + } + ++static int return_sites_group_size(struct kpatch_elf *kelf, int offset) ++{ ++ return 4; ++} ++ + static int smp_locks_group_size(struct kpatch_elf *kelf, int offset) + { + return 4; +@@ -2103,6 +2108,11 @@ static struct special_section special_sections[] = { + .name = ".altinstructions", + .group_size = altinstructions_group_size, + }, ++ { ++ .name = ".return_sites", ++ .group_size = return_sites_group_size, ++ }, ++ + #endif + #ifdef __powerpc64__ + { +-- +2.38.1 + diff --git a/SPECS/kpatch-patch.spec b/SPECS/kpatch-patch.spec index f25d7a8..05bd394 100644 --- a/SPECS/kpatch-patch.spec +++ b/SPECS/kpatch-patch.spec @@ -1,17 +1,21 @@ # 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 3.10.0-1160.88.1.el7 %define kpatch_ver 0.9.2 -%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/2153001 +Source100: CVE-2022-3564.patch +# +# https://bugzilla.redhat.com/2196588 +Source101: CVE-2023-32233.patch # End of patch sources. DO NOT REMOVE THIS LINE. %endif @@ -146,5 +150,9 @@ It is only a method to subscribe to the kpatch stream for kernel-%{kernel_ver}. %endif %changelog +* Wed Jul 05 2023 Yannick Cote [1-1.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} + * Mon Feb 20 2023 Yannick Cote [0-0.el7] - An empty patch to subscribe to kpatch stream for kernel-3.10.0-1160.88.1.el7 [2171884]