[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <ac6f090.eaff.18f7baadb40.Coremail.duoming@zju.edu.cn>
Date: Wed, 15 May 2024 17:52:25 +0800 (GMT+08:00)
From: duoming@....edu.cn
To: "Lars Kellogg-Stedman" <lars@...bit.com>
Cc: linux-hams@...r.kernel.org, netdev@...r.kernel.org,
linux-kernel@...r.kernel.org, pabeni@...hat.com, kuba@...nel.org,
edumazet@...gle.com, davem@...emloft.net, jreuter@...na.de,
dan.carpenter@...aro.org
Subject: Re: [PATCH net] ax25: Fix refcount leak issues of ax25_dev
On Wed, 1 May 2024 21:29:16 -0400 Lars Kellogg-Stedman wrote:
> Assume we have the following two interfaces configured on a system:
>
> $ cat /etc/ax25/axports
> udp0 test0-0 9600 255 2 axudp0
> udp1 test0-1 9600 255 2 axudp1
>
> And we have ax25d listening on both interfaces:
>
> [udp0]
> default * * * * * * - root /usr/sbin/axwrapper axwrapper -- /bin/sh sh /etc/ax25/example-output.sh
> [udp1]
> default * * * * * * - root /usr/sbin/axwrapper axwrapper -- /bin/sh sh /etc/ax25/example-output.sh
>
> Using the 'ax-devs' and 'ax-sockets' gdb commands shown at the end of
> this message, we start with:
>
> (gdb) ax-devs
> ax1 ax_refcnt:2 dev_refcnt:9 dev_untracked:1 dev_notrack:1
> ax0 ax_refcnt:2 dev_refcnt:9 dev_untracked:1 dev_notrack:1
> (gdb) ax-sockets
> 0xffff8881002b6800 if:ax1 state:0 refcnt:2 dev_tracker:0xffff888100ded200
> 0xffff888101ac4e00 if:ax0 state:0 refcnt:2 dev_tracker:0xffff888100dec4c0
>
> We initiate a connection from ax0 to ax1:
>
> call -r udp0 test0-1
>
> When we first enter ax25_rcv, we have:
>
> (gdb) ax-devs
> ax1 ax_refcnt:2 dev_refcnt:9 dev_untracked:1 dev_notrack:1
> ax0 ax_refcnt:3 dev_refcnt:10 dev_untracked:1 dev_notrack:1
> (gdb) ax-sockets
> 0xffff888101ac8000 if:ax0 state:1 refcnt:2 dev_tracker:0xffff888100dedb80
> 0xffff8881002b6800 if:ax1 state:0 refcnt:2 dev_tracker:0xffff888100ded200
> 0xffff888101ac4e00 if:ax0 state:0 refcnt:2 dev_tracker:0xffff888100dec4c0
>
> After we reach line 413 (in net/ax25/ax25_in.c) and add a new control
> block:
>
> ax25_cb_add(ax25)
>
> We have:
>
> (gdb) ax-devs
> ax1 ax_refcnt:2 dev_refcnt:9 dev_untracked:1 dev_notrack:1
> ax0 ax_refcnt:3 dev_refcnt:10 dev_untracked:1 dev_notrack:1
> (gdb) ax-sockets
> 0xffff88810245ac00 if:ax1 state:3 refcnt:2 dev_tracker:0x0 <fixed_percpu_data>
> 0xffff88810245ba00 if:ax0 state:1 refcnt:2 dev_tracker:0xffff88810136c800
> 0xffff888100c79e00 if:ax1 state:0 refcnt:2 dev_tracker:0xffff88810136c6e0
> 0xffff8881018e9800 if:ax0 state:0 refcnt:2 dev_tracker:0xffff88810170c860
>
> Note that (a) ax25->dev_tracker is NULL, and (b) we have incremeted the
> refcount on ax0 (the source interface), but not on ax1 (the destination
> interface). When we call ax25_release for this control block, we get to:
>
> netdev_put(ax25_dev->dev, &ax25->dev_tracker);
> ax25_dev_put(ax25_dev);
>
> With:
>
> (gdb) ax-devs
> ax1 ax_refcnt:2 dev_refcnt:9 dev_untracked:1 dev_notrack:1
> ax0 ax_refcnt:3 dev_refcnt:10 dev_untracked:1 dev_notrack:1
>
> After the calls to netdev_put() and ax25_dev_put(), we have:
>
> (gdb) ax-devs
> ax1 ax_refcnt:1 dev_refcnt:8 dev_untracked:-1073741824 dev_notrack:1
> ax0 ax_refcnt:2 dev_refcnt:9 dev_untracked:1 dev_notrack:1
>
> You can see that (a) ax25_dev->dev->refcnt_tracker->untracked is now
> invalid, and ax25_dev->dev->dev_refcnt is in trouble: it decrements by
> one for each closed connection, even though it was never incremented
> when we accepted the connection. The underflow in
> ...refcnt_tracker->untracked yields the traceback with:
>
> refcount_t: decrement hit 0; leaking memory.
>
> Additional connections will eventually trigger more problems; we will
> ultimately underflow ax25_dev->dev->dev_refcnt, but we may also run into
> memory corruption because of the invalid tracker data, resulting in:
>
> BUG: unable to handle page fault for address: 00000010000003b0
Do you know how to trigger this bug? Could you share the POC?
Best regards,
Duoming Zhou
Powered by blists - more mailing lists