diff options
author | Paul Moore <paul@paul-moore.com> | 2020-04-20 10:09:29 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-04-07 12:05:41 +0200 |
commit | 61ec5d8de5786a55c4889d746bc94651fc399ef0 (patch) | |
tree | c1562ca218b65be6d68841f10d682b6a16042604 | |
parent | 03691e3b50dc97ddd7f39a98a376ac7651c65605 (diff) | |
download | linux-stable-61ec5d8de5786a55c4889d746bc94651fc399ef0.tar.gz linux-stable-61ec5d8de5786a55c4889d746bc94651fc399ef0.tar.bz2 linux-stable-61ec5d8de5786a55c4889d746bc94651fc399ef0.zip |
audit: fix a net reference leak in audit_send_reply()
commit a48b284b403a4a073d8beb72d2bb33e54df67fb6 upstream.
If audit_send_reply() fails when trying to create a new thread to
send the reply it also fails to cleanup properly, leaking a reference
to a net structure. This patch fixes the error path and makes a
handful of other cleanups that came up while fixing the code.
Reported-by: teroincn@gmail.com
Reviewed-by: Richard Guy Briggs <rgb@redhat.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Cc: <stable@vger.kernel.org> # 4.9.x
Signed-off-by: Wen Yang <wenyang@linux.alibaba.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | kernel/audit.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index af1e00f52bd0..55ccd8421df7 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -580,6 +580,18 @@ out_kfree_skb: return NULL; } +static void audit_free_reply(struct audit_reply *reply) +{ + if (!reply) + return; + + if (reply->skb) + kfree_skb(reply->skb); + if (reply->net) + put_net(reply->net); + kfree(reply); +} + static int audit_send_reply_thread(void *arg) { struct audit_reply *reply = (struct audit_reply *)arg; @@ -592,8 +604,8 @@ static int audit_send_reply_thread(void *arg) /* Ignore failure. It'll only happen if the sender goes away, because our timeout is set to infinite. */ netlink_unicast(aunet->nlsk , reply->skb, reply->portid, 0); - put_net(net); - kfree(reply); + reply->skb = NULL; + audit_free_reply(reply); return 0; } /** @@ -606,36 +618,34 @@ static int audit_send_reply_thread(void *arg) * @payload: payload data * @size: payload size * - * Allocates an skb, builds the netlink message, and sends it to the port id. - * No failure notifications. + * Allocates a skb, builds the netlink message, and sends it to the port id. */ static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done, int multi, const void *payload, int size) { u32 portid = NETLINK_CB(request_skb).portid; - struct net *net = sock_net(NETLINK_CB(request_skb).sk); - struct sk_buff *skb; struct task_struct *tsk; - struct audit_reply *reply = kmalloc(sizeof(struct audit_reply), - GFP_KERNEL); + struct audit_reply *reply; + reply = kzalloc(sizeof(*reply), GFP_KERNEL); if (!reply) return; - skb = audit_make_reply(portid, seq, type, done, multi, payload, size); - if (!skb) - goto out; + reply->skb = audit_make_reply(portid, seq, type, done, multi, payload, size); + if (!reply->skb) + goto err; - reply->net = get_net(net); + reply->net = get_net(sock_net(NETLINK_CB(request_skb).sk)); reply->portid = portid; - reply->skb = skb; tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); - if (!IS_ERR(tsk)) - return; - kfree_skb(skb); -out: - kfree(reply); + if (IS_ERR(tsk)) + goto err; + + return; + +err: + audit_free_reply(reply); } /* |