diff --git a/pocs/linux/kernelctf/CVE-2023-3390_lts_cos_mitigation/docs/exploit.md b/pocs/linux/kernelctf/CVE-2023-3390_lts_cos_mitigation/docs/exploit.md index 454f9016..924191fd 100644 --- a/pocs/linux/kernelctf/CVE-2023-3390_lts_cos_mitigation/docs/exploit.md +++ b/pocs/linux/kernelctf/CVE-2023-3390_lts_cos_mitigation/docs/exploit.md @@ -193,27 +193,32 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) After that, `nf_tables_destroy_set` function, which is eventually reached from `nf_tables_rule_destroy` [1], checks that the given set is an anonymous set and is not bind to anywhere [2]. If so, `nft_set_destroy` function frees this set [3]. -- [net/netfilter/nf_tables_api.c:nft_set_lookup()](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/net/netfilter/nf_tables_api.c?h=linux-6.1.y&id=d2869ace6eeb8ea8a6e70e6904524c5a6456d3fb#n3893) +- [net/netfilter/nf_tables_api.c:nft_set_lookup_byid()](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/net/netfilter/nf_tables_api.c?h=linux-6.1.y&id=d2869ace6eeb8ea8a6e70e6904524c5a6456d3fb#n3923) ```c -static struct nft_set *nft_set_lookup(const struct nft_table *table, - const struct nlattr *nla, u8 genmask) +static struct nft_set *nft_set_lookup_byid(const struct net *net, + const struct nft_table *table, + const struct nlattr *nla, u8 genmask) { - struct nft_set *set; - - if (nla == NULL) - return ERR_PTR(-EINVAL); - - list_for_each_entry_rcu(set, &table->sets, list) { - if (!nla_strcmp(nla, set->name) && - nft_active_genmask(set, genmask)) // [1] - return set; + struct nftables_pernet *nft_net = nft_pernet(net); + u32 id = ntohl(nla_get_be32(nla)); + struct nft_trans *trans; + + list_for_each_entry(trans, &nft_net->commit_list, list) { + if (trans->msg_type == NFT_MSG_NEWSET) { + struct nft_set *set = nft_trans_set(trans); + + if (id == nft_trans_set_id(trans) && + set->table == table && + nft_active_genmask(set, genmask)) // [1] + return set; + } } return ERR_PTR(-ENOENT); } ``` -Unfortunately, this freed set object is still accessible in the following commands of the same transaction. This is because this object was not properly deactivated (i.e., `nft_activate_genmask` will return true). From this, we can see why the patch works; It doesn't unbind the set object but only deactivates it, making it non-accessible. +Unfortunately, this freed set object is still accessible in the following commands of the same transaction. This is because this object was still in transaction list and not properly deactivated (i.e., `nft_activate_genmask` will return true). From this, we can see why the patch works; It doesn't unbind the set object but only deactivates it, making it non-accessible. ![vuln_2](./img/vuln_2.png)