|
Message-ID: <ZI1CALKOZczi4lKI@eldamar.lan> Date: Sat, 17 Jun 2023 07:17:52 +0200 From: Salvatore Bonaccorso <carnil@...ian.org> To: oss-security@...ts.openwall.com Subject: Re: Linux kernel: off-by-one in fl_set_geneve_opt Hi, On Wed, Jun 07, 2023 at 11:32:31AM +0800, Hangyu Hua wrote: > Hi guys, > > I find a off-by-one bug in linux kernel's Flower > classifier(NET_CLS_FLOWER). It can cause denial-of-service and privilege > escalation. > > # Details: > > static int fl_set_geneve_opt(const struct nlattr *nla, struct fl_flow_key > *key, > int depth, int option_len, > struct netlink_ext_ack *extack) > { > struct nlattr *tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX + 1]; > struct nlattr *class = NULL, *type = NULL, *data = NULL; > struct geneve_opt *opt; > int err, data_len = 0; > > if (option_len > sizeof(struct geneve_opt)) > data_len = option_len - sizeof(struct geneve_opt); > > opt = (struct geneve_opt *)&key->enc_opts.data[key->enc_opts.len]; <--- [1] > memset(opt, 0xff, option_len); > opt->length = data_len / 4; > opt->r1 = 0; > opt->r2 = 0; > opt->r3 = 0; > > ... > if (tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA]) { > int new_len = key->enc_opts.len; > > data = tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA]; > data_len = nla_len(data); > if (data_len < 4) { > NL_SET_ERR_MSG(extack, "Tunnel key geneve option data is less than 4 > bytes long"); > return -ERANGE; > } > if (data_len % 4) { > NL_SET_ERR_MSG(extack, "Tunnel key geneve option data is not a > multiple of 4 bytes long"); > return -ERANGE; > } > > new_len += sizeof(struct geneve_opt) + data_len; > BUILD_BUG_ON(FLOW_DIS_TUN_OPTS_MAX != IP_TUNNEL_OPTS_MAX); > if (new_len > FLOW_DIS_TUN_OPTS_MAX) { <--- [2] > NL_SET_ERR_MSG(extack, "Tunnel options exceeds max size"); > return -ERANGE; > } > opt->length = data_len / 4; > memcpy(opt->opt_data, nla_data(data), data_len); <--- [3] > } > ... > } > > We can see that opt use key->enc_opts.len to get its pointer from > key->enc_opts.data[] in [1]. Then length will be set to "data_len / > 4". The bug is that if we send two TCA_FLOWER_KEY_ENC_OPTS_GENEVE > packets and their total size is 252 bytes(key->enc_opts.len = 252) > then key->enc_opts.len = opt->length = data_len / 4 when the third > TCA_FLOWER_KEY_ENC_OPTS_GENEVE packet enters fl_set_geneve_opt. This > can bypass the check in [2] and cause out of bound write in > [3](opt->opt_data = key->enc_opts.data[257]). > > # Patch > > I already contacted the linux security team and made a patch: > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/sched?id=4d56304e5827c8cc8cc18c75343d283af7c4825c > > # CVE > > Pending > > # EXP > > In order to avoid confusion i will publish it after I get CVE. CVE-2023-35788 has been assigned for this issue: https://www.cve.org/CVERecord?id=CVE-2023-35788 Regards, Salvatore
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.