From: Sasha Levin Date: Tue, 3 Mar 2020 21:02:39 +0000 (-0500) Subject: fixes for 4.9 X-Git-Tag: v4.19.108~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e37057fabe11c7eccc8e79661627671a37496fcf;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 4.9 Signed-off-by: Sasha Levin --- diff --git a/queue-4.9/audit-always-check-the-netlink-payload-length-in-aud.patch b/queue-4.9/audit-always-check-the-netlink-payload-length-in-aud.patch new file mode 100644 index 00000000000..5daeb27fb81 --- /dev/null +++ b/queue-4.9/audit-always-check-the-netlink-payload-length-in-aud.patch @@ -0,0 +1,153 @@ +From e826433583ef3d8e0bea44b96e83547329614791 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2020 16:38:57 -0500 +Subject: audit: always check the netlink payload length in audit_receive_msg() + +From: Paul Moore + +[ Upstream commit 756125289285f6e55a03861bf4b6257aa3d19a93 ] + +This patch ensures that we always check the netlink payload length +in audit_receive_msg() before we take any action on the payload +itself. + +Cc: stable@vger.kernel.org +Reported-by: syzbot+399c44bf1f43b8747403@syzkaller.appspotmail.com +Reported-by: syzbot+e4b12d8d202701f08b6d@syzkaller.appspotmail.com +Signed-off-by: Paul Moore +Signed-off-by: Sasha Levin +--- + kernel/audit.c | 40 +++++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +diff --git a/kernel/audit.c b/kernel/audit.c +index 3461a3d874fed..53dcaa3b67bcf 100644 +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -751,13 +751,11 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature + audit_log_end(ab); + } + +-static int audit_set_feature(struct sk_buff *skb) ++static int audit_set_feature(struct audit_features *uaf) + { +- struct audit_features *uaf; + int i; + + BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > ARRAY_SIZE(audit_feature_names)); +- uaf = nlmsg_data(nlmsg_hdr(skb)); + + /* if there is ever a version 2 we should handle that here */ + +@@ -823,6 +821,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + { + u32 seq; + void *data; ++ int data_len; + int err; + struct audit_buffer *ab; + u16 msg_type = nlh->nlmsg_type; +@@ -846,6 +845,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + } + seq = nlh->nlmsg_seq; + data = nlmsg_data(nlh); ++ data_len = nlmsg_len(nlh); + + switch (msg_type) { + case AUDIT_GET: { +@@ -867,7 +867,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + struct audit_status s; + memset(&s, 0, sizeof(s)); + /* guard against past and future API changes */ +- memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); ++ memcpy(&s, data, min_t(size_t, sizeof(s), data_len)); + if (s.mask & AUDIT_STATUS_ENABLED) { + err = audit_set_enabled(s.enabled); + if (err < 0) +@@ -930,7 +930,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + return err; + break; + case AUDIT_SET_FEATURE: +- err = audit_set_feature(skb); ++ if (data_len < sizeof(struct audit_features)) ++ return -EINVAL; ++ err = audit_set_feature(data); + if (err) + return err; + break; +@@ -942,6 +944,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + + err = audit_filter(msg_type, AUDIT_FILTER_USER); + if (err == 1) { /* match or error */ ++ char *str = data; ++ + err = 0; + if (msg_type == AUDIT_USER_TTY) { + err = tty_audit_push(); +@@ -950,19 +954,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + } + mutex_unlock(&audit_cmd_mutex); + audit_log_common_recv_msg(&ab, msg_type); +- if (msg_type != AUDIT_USER_TTY) ++ if (msg_type != AUDIT_USER_TTY) { ++ /* ensure NULL termination */ ++ str[data_len - 1] = '\0'; + audit_log_format(ab, " msg='%.*s'", + AUDIT_MESSAGE_TEXT_MAX, +- (char *)data); +- else { +- int size; +- ++ str); ++ } else { + audit_log_format(ab, " data="); +- size = nlmsg_len(nlh); +- if (size > 0 && +- ((unsigned char *)data)[size - 1] == '\0') +- size--; +- audit_log_n_untrustedstring(ab, data, size); ++ if (data_len > 0 && str[data_len - 1] == '\0') ++ data_len--; ++ audit_log_n_untrustedstring(ab, str, data_len); + } + audit_set_portid(ab, NETLINK_CB(skb).portid); + audit_log_end(ab); +@@ -971,7 +973,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + break; + case AUDIT_ADD_RULE: + case AUDIT_DEL_RULE: +- if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) ++ if (data_len < sizeof(struct audit_rule_data)) + return -EINVAL; + if (audit_enabled == AUDIT_LOCKED) { + audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); +@@ -980,7 +982,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + return -EPERM; + } + err = audit_rule_change(msg_type, NETLINK_CB(skb).portid, +- seq, data, nlmsg_len(nlh)); ++ seq, data, data_len); + break; + case AUDIT_LIST_RULES: + err = audit_list_rules_send(skb, seq); +@@ -994,7 +996,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + case AUDIT_MAKE_EQUIV: { + void *bufp = data; + u32 sizes[2]; +- size_t msglen = nlmsg_len(nlh); ++ size_t msglen = data_len; + char *old, *new; + + err = -EINVAL; +@@ -1070,7 +1072,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + + memset(&s, 0, sizeof(s)); + /* guard against past and future API changes */ +- memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); ++ memcpy(&s, data, min_t(size_t, sizeof(s), data_len)); + /* check if new data is valid */ + if ((s.enabled != 0 && s.enabled != 1) || + (s.log_passwd != 0 && s.log_passwd != 1)) +-- +2.20.1 + diff --git a/queue-4.9/series b/queue-4.9/series index 887ae4d9ccf..79403e20b10 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -47,3 +47,4 @@ tuntap-correctly-set-sockwq_async_nospace.patch drivers-net-xgene-fix-the-order-of-the-arguments-of-alloc_etherdev_mqs.patch perf-hists-browser-restore-esc-as-zoom-out-of-dso-thread-etc.patch mm-huge_memory.c-use-head-to-check-huge-zero-page.patch +audit-always-check-the-netlink-payload-length-in-aud.patch