|
Message-ID: <ee226490-51c6-f8e9-821a-6061202c01b1@gmail.com> Date: Wed, 7 Jun 2023 11:32:31 +0800 From: Hangyu Hua <hbh25y@...il.com> To: oss-security@...ts.openwall.com Subject: Linux kernel: off-by-one in fl_set_geneve_opt 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. Thanks, Hangyu
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.