[LTP] [PATCH 3/3] Add test for CVE 2023-1829
Martin Doucha
mdoucha@suse.cz
Fri Aug 4 11:23:14 CEST 2023
Hi,
I've noticed some kernel messages complaining that there's leftover data
at the end of the filter setup rtnetlink query. I need to investigate a
bit more and I'll send v2 for this patch. The other two patches can be
merged as is.
On 27. 07. 23 17:00, Martin Doucha wrote:
> Signed-off-by: Martin Doucha <mdoucha@suse.cz>
> ---
> runtest/cve | 1 +
> testcases/cve/.gitignore | 1 +
> testcases/cve/tcindex01.c | 156 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 158 insertions(+)
> create mode 100644 testcases/cve/tcindex01.c
>
> diff --git a/runtest/cve b/runtest/cve
> index 7d1e84f89..f9b36a182 100644
> --- a/runtest/cve
> +++ b/runtest/cve
> @@ -84,6 +84,7 @@ cve-2021-38604 mq_notify03
> cve-2022-0847 dirtypipe
> cve-2022-2590 dirtyc0w_shmem
> cve-2022-23222 bpf_prog07
> +cve-2023-1829 tcindex01
> # Tests below may cause kernel memory leak
> cve-2020-25704 perf_event_open03
> cve-2022-0185 fsconfig03
> diff --git a/testcases/cve/.gitignore b/testcases/cve/.gitignore
> index 90e8b191c..389354eaf 100644
> --- a/testcases/cve/.gitignore
> +++ b/testcases/cve/.gitignore
> @@ -12,3 +12,4 @@ cve-2017-16939
> cve-2017-17053
> cve-2022-4378
> icmp_rate_limit01
> +tcindex01.c
> diff --git a/testcases/cve/tcindex01.c b/testcases/cve/tcindex01.c
> new file mode 100644
> index 000000000..89569d1f7
> --- /dev/null
> +++ b/testcases/cve/tcindex01.c
> @@ -0,0 +1,156 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2023 SUSE LLC <mdoucha@suse.cz>
> + */
> +
> +/*\
> + * CVE-2023-1829
> + *
> + * Test for use-after-free after removing tcindex traffic filter with certain
> + * parameters.
> + *
> + * Tcindex filter removed in:
> + *
> + * commit 8c710f75256bb3cf05ac7b1672c82b92c43f3d28
> + * Author: Jamal Hadi Salim <jhs@mojatatu.com>
> + * Date: Tue Feb 14 08:49:14 2023 -0500
> + *
> + * net/sched: Retire tcindex classifier
> + */
> +
> +#include <linux/netlink.h>
> +#include <linux/pkt_sched.h>
> +#include <linux/pkt_cls.h>
> +#include <linux/tc_act/tc_gact.h>
> +#include "tst_test.h"
> +#include "tst_rtnetlink.h"
> +#include "tst_netdevice.h"
> +#include "lapi/sched.h"
> +#include "lapi/if_ether.h"
> +#include "lapi/rtnetlink.h"
> +
> +#define DEVNAME "ltp_dummy1"
> +
> +static const uint32_t qd_handle = TC_H_MAKE(1 << 16, 0);
> +static const uint32_t clsid = TC_H_MAKE(1 << 16, 1);
> +static const uint32_t shift = 10;
> +static const uint16_t mask = 0xffff;
> +
> +/* rtnetlink payloads */
> +static const struct tc_htb_glob qd_opt = {
> + .rate2quantum = 10,
> + .version = 3,
> + .defcls = 30
> +};
> +static const struct tc_gact f_gact_param = {
> + .action = TC_ACT_SHOT
> +};
> +static struct tc_htb_opt cls_opt = {};
> +
> +/* htb qdisc and class options */
> +static const struct tst_rtnl_attr_list qd_config[] = {
> + {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
> + {TCA_HTB_INIT, &qd_opt, sizeof(qd_opt), NULL},
> + {0, NULL, -1, NULL}
> + }},
> + {0, NULL, -1, NULL}
> +};
> +static const struct tst_rtnl_attr_list cls_config[] = {
> + {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
> + {TCA_HTB_PARMS, &cls_opt, sizeof(cls_opt), NULL},
> + {0, NULL, -1, NULL}
> + }},
> + {0, NULL, -1, NULL}
> +};
> +
> +/* tcindex filter options */
> +static const struct tst_rtnl_attr_list f_actopts[] = {
> + {TCA_GACT_PARMS, &f_gact_param, sizeof(f_gact_param), NULL},
> + {0, NULL, -1, NULL}
> +};
> +static const struct tst_rtnl_attr_list f_action[] = {
> + {1, NULL, 0, (const struct tst_rtnl_attr_list[]){
> + {TCA_ACT_KIND, "gact", 5, NULL},
> + {TCA_ACT_OPTIONS | NLA_F_NESTED, NULL, 0, f_actopts},
> + {0, NULL, -1, NULL}
> + }},
> + {0, NULL, -1, NULL}
> +};
> +static const struct tst_rtnl_attr_list f_config[] = {
> + {TCA_OPTIONS, NULL, 0, (const struct tst_rtnl_attr_list[]){
> + {TCA_TCINDEX_MASK, &mask, sizeof(mask), NULL},
> + {TCA_TCINDEX_SHIFT, &shift, sizeof(shift), NULL},
> + {TCA_TCINDEX_CLASSID, &clsid, sizeof(clsid), NULL},
> + {TCA_TCINDEX_ACT, &clsid, sizeof(clsid), f_action},
> + {0, NULL, -1, NULL}
> + }},
> + {0, NULL, -1, NULL}
> +};
> +
> +static void setup(void)
> +{
> + tst_setup_netns();
> + NETDEV_ADD_DEVICE(DEVNAME, "dummy");
> +
> + cls_opt.rate.rate = cls_opt.ceil.rate = 256000;
> + cls_opt.buffer = 1000000 * 1600 / cls_opt.rate.rate;
> + cls_opt.cbuffer = 1000000 * 1600 / cls_opt.ceil.rate;
> +}
> +
> +static void run(void)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < 100; i++) {
> + NETDEV_ADD_QDISC(DEVNAME, AF_UNSPEC, TC_H_ROOT, qd_handle,
> + "htb", qd_config);
> + NETDEV_ADD_TRAFFIC_CLASS(DEVNAME, qd_handle, clsid, "htb",
> + cls_config);
> + NETDEV_ADD_TRAFFIC_FILTER(DEVNAME, qd_handle, 10, ETH_P_IP, 1,
> + "tcindex", f_config);
> + NETDEV_REMOVE_TRAFFIC_FILTER(DEVNAME, qd_handle, 10, ETH_P_IP,
> + 1, "tcindex");
> +
> + /* Wait at least one jiffy for use-after-free */
> + usleep(10000);
> +
> + NETDEV_REMOVE_QDISC(DEVNAME, AF_UNSPEC, TC_H_ROOT, qd_handle,
> + "htb");
> + }
> +
> + if (tst_taint_check()) {
> + tst_res(TFAIL, "Kernel is vulnerable");
> + return;
> + }
> +
> + tst_res(TPASS, "Nothing bad happened (yet)");
> +}
> +
> +static void cleanup(void)
> +{
> + NETDEV_REMOVE_DEVICE(DEVNAME);
> +}
> +
> +static struct tst_test test = {
> + .test_all = run,
> + .setup = setup,
> + .cleanup = cleanup,
> + .taint_check = TST_TAINT_W | TST_TAINT_D,
> + .needs_kconfigs = (const char *[]) {
> + "CONFIG_VETH",
> + "CONFIG_USER_NS=y",
> + "CONFIG_NET_NS=y",
> + "CONFIG_NET_SCH_HTB",
> + "CONFIG_NET_CLS_TCINDEX",
> + NULL
> + },
> + .save_restore = (const struct tst_path_val[]) {
> + {"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
> + {}
> + },
> + .tags = (const struct tst_tag[]) {
> + {"linux-git", "8c710f75256b"},
> + {"CVE", "2023-1829"},
> + {}
> + }
> +};
--
Martin Doucha mdoucha@suse.cz
SW Quality Engineer
SUSE LINUX, s.r.o.
CORSO IIa
Krizikova 148/34
186 00 Prague 8
Czech Republic
More information about the ltp
mailing list