Skip to content

Commit

Permalink
audit: fix a net reference leak in audit_send_reply()
Browse files Browse the repository at this point in the history
commit a48b284 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>
  • Loading branch information
Paul Moore authored and Greg Kroah-Hartman committed Apr 7, 2021
1 parent 03691e3 commit 61ec5d8
Showing 1 changed file with 28 additions and 18 deletions.
46 changes: 28 additions & 18 deletions kernel/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,18 @@ struct sk_buff *audit_make_reply(__u32 portid, int seq, int type, int done,
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;
Expand All @@ -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;
}
/**
Expand All @@ -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);
}

/*
Expand Down

0 comments on commit 61ec5d8

Please sign in to comment.