All of lore.kernel.org
 help / color / mirror / Atom feed
* Use-after-free access in j1939_session_deactivate
@ 2021-07-12 22:40 Xiaochen Zou
  2021-07-13  4:43 ` Greg KH
  2021-07-13  7:10 ` Oleksij Rempel
  0 siblings, 2 replies; 7+ messages in thread
From: Xiaochen Zou @ 2021-07-12 22:40 UTC (permalink / raw)
  To: kernel, linux-can, netdev, stable

Hi,
It looks like there are multiple use-after-free accesses in
j1939_session_deactivate()

static bool j1939_session_deactivate(struct j1939_session *session)
{
bool active;

j1939_session_list_lock(session->priv);
active = j1939_session_deactivate_locked(session); //session can be freed inside
j1939_session_list_unlock(session->priv); // It causes UAF read and write

return active;
}

session can be freed by
j1939_session_deactivate_locked->j1939_session_put->__j1939_session_release->j1939_session_destroy->kfree.
Therefore it makes the unlock function perform UAF access.


Best,
Xiaochen Zou
Department of Computer Science & Engineering
University of California, Riverside

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use-after-free access in j1939_session_deactivate
  2021-07-12 22:40 Use-after-free access in j1939_session_deactivate Xiaochen Zou
@ 2021-07-13  4:43 ` Greg KH
  2021-07-13  7:30   ` Xiaochen Zou
  2021-07-13  7:10 ` Oleksij Rempel
  1 sibling, 1 reply; 7+ messages in thread
From: Greg KH @ 2021-07-13  4:43 UTC (permalink / raw)
  To: Xiaochen Zou; +Cc: kernel, linux-can, netdev, stable

On Mon, Jul 12, 2021 at 03:40:46PM -0700, Xiaochen Zou wrote:
> Hi,
> It looks like there are multiple use-after-free accesses in
> j1939_session_deactivate()
> 
> static bool j1939_session_deactivate(struct j1939_session *session)
> {
> bool active;
> 
> j1939_session_list_lock(session->priv);
> active = j1939_session_deactivate_locked(session); //session can be freed inside
> j1939_session_list_unlock(session->priv); // It causes UAF read and write
> 
> return active;
> }
> 
> session can be freed by
> j1939_session_deactivate_locked->j1939_session_put->__j1939_session_release->j1939_session_destroy->kfree.
> Therefore it makes the unlock function perform UAF access.

Great, can you make up a patch to fix this issue so you can get credit
for finding and solving it?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use-after-free access in j1939_session_deactivate
  2021-07-12 22:40 Use-after-free access in j1939_session_deactivate Xiaochen Zou
  2021-07-13  4:43 ` Greg KH
@ 2021-07-13  7:10 ` Oleksij Rempel
  1 sibling, 0 replies; 7+ messages in thread
From: Oleksij Rempel @ 2021-07-13  7:10 UTC (permalink / raw)
  To: Xiaochen Zou; +Cc: kernel, linux-can, netdev, stable

Hi,

On Mon, Jul 12, 2021 at 03:40:46PM -0700, Xiaochen Zou wrote:
> Hi,
> It looks like there are multiple use-after-free accesses in
> j1939_session_deactivate()
> 
> static bool j1939_session_deactivate(struct j1939_session *session)
> {
> bool active;
> 
> j1939_session_list_lock(session->priv);
> active = j1939_session_deactivate_locked(session); //session can be freed inside
> j1939_session_list_unlock(session->priv); // It causes UAF read and write
> 
> return active;
> }
> 
> session can be freed by
> j1939_session_deactivate_locked->j1939_session_put->__j1939_session_release->j1939_session_destroy->kfree.
> Therefore it makes the unlock function perform UAF access.

Potentially I would agree, but this function takes "session" as
property. Any function which provided session pointer should
care about own ref counting. If described scenarios really happens, then
there is problem on other place. Was you able to reproduce it?

Regards,
Oleksij
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use-after-free access in j1939_session_deactivate
  2021-07-13  4:43 ` Greg KH
@ 2021-07-13  7:30   ` Xiaochen Zou
  2021-07-13  7:35     ` Marc Kleine-Budde
  0 siblings, 1 reply; 7+ messages in thread
From: Xiaochen Zou @ 2021-07-13  7:30 UTC (permalink / raw)
  To: Greg KH; +Cc: kernel, linux-can, netdev, stable

j1939_session_destroy() will free both session and session->priv. It
leads to multiple use-after-free read and write in
j1939_session_deactivate() when session was freed in
j1939_session_deactivate_locked(). The free chain is
j1939_session_deactivate_locked()->
j1939_session_put()->__j1939_session_release()->j1939_session_destroy().
To fix this bug, I moved j1939_session_put() behind
j1939_session_deactivate_locked() and guarded it with a check of
active since the session would be freed only if active is true.

diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index e5f1a56994c6..b6448f29a4bd 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -1018,7 +1018,6 @@ static bool
j1939_session_deactivate_locked(struct j1939_session *session)

        list_del_init(&session->active_session_list_entry);
        session->state = J1939_SESSION_DONE;
-       j1939_session_put(session);
    }

    return active;
@@ -1031,6 +1030,9 @@ static bool j1939_session_deactivate(struct
j1939_session *session)
    j1939_session_list_lock(session->priv);
    active = j1939_session_deactivate_locked(session);
    j1939_session_list_unlock(session->priv);
+   if (active) {
+       j1939_session_put(session);
+   }

    return active;
 }
@@ -2021,6 +2023,7 @@ void j1939_simple_recv(struct j1939_priv *priv,
struct sk_buff *skb)
 int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk)
 {
    struct j1939_session *session, *saved;
+   bool active;

    netdev_dbg(priv->ndev, "%s, sk: %p\n", __func__, sk);
    j1939_session_list_lock(priv);
@@ -2030,7 +2033,10 @@ int j1939_cancel_active_session(struct
j1939_priv *priv, struct sock *sk)
        if (!sk || sk == session->sk) {
            j1939_session_timers_cancel(session);
            session->err = ESHUTDOWN;
-           j1939_session_deactivate_locked(session);
+           active = j1939_session_deactivate_locked(session);
+           if (active) {
+               j1939_session_put(session);
+           }
        }
    }
    j1939_session_list_unlock(priv);

On Mon, Jul 12, 2021 at 9:44 PM Greg KH <greg@kroah.com> wrote:
>
> On Mon, Jul 12, 2021 at 03:40:46PM -0700, Xiaochen Zou wrote:
> > Hi,
> > It looks like there are multiple use-after-free accesses in
> > j1939_session_deactivate()
> >
> > static bool j1939_session_deactivate(struct j1939_session *session)
> > {
> > bool active;
> >
> > j1939_session_list_lock(session->priv);
> > active = j1939_session_deactivate_locked(session); //session can be freed inside
> > j1939_session_list_unlock(session->priv); // It causes UAF read and write
> >
> > return active;
> > }
> >
> > session can be freed by
> > j1939_session_deactivate_locked->j1939_session_put->__j1939_session_release->j1939_session_destroy->kfree.
> > Therefore it makes the unlock function perform UAF access.
>
> Great, can you make up a patch to fix this issue so you can get credit
> for finding and solving it?
>
> thanks,
>
> greg k-h



-- 
Xiaochen Zou
PhD Student
Department of Computer Science & Engineering
University of California, Riverside

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: Use-after-free access in j1939_session_deactivate
  2021-07-13  7:30   ` Xiaochen Zou
@ 2021-07-13  7:35     ` Marc Kleine-Budde
  2021-07-13  7:46       ` Xiaochen Zou
  0 siblings, 1 reply; 7+ messages in thread
From: Marc Kleine-Budde @ 2021-07-13  7:35 UTC (permalink / raw)
  To: Xiaochen Zou, Greg KH; +Cc: netdev, stable, kernel, linux-can


[-- Attachment #1.1: Type: text/plain, Size: 1005 bytes --]

On 7/13/21 9:30 AM, Xiaochen Zou wrote:
> j1939_session_destroy() will free both session and session->priv. It
> leads to multiple use-after-free read and write in
> j1939_session_deactivate() when session was freed in
> j1939_session_deactivate_locked(). The free chain is
> j1939_session_deactivate_locked()->
> j1939_session_put()->__j1939_session_release()->j1939_session_destroy().
> To fix this bug, I moved j1939_session_put() behind
> j1939_session_deactivate_locked() and guarded it with a check of
> active since the session would be freed only if active is true.

Please include your Signed-off-by.
See
https://elixir.bootlin.com/linux/v5.12/source/Documentation/process/submitting-patches.rst#L356

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Use-after-free access in j1939_session_deactivate
  2021-07-13  7:35     ` Marc Kleine-Budde
@ 2021-07-13  7:46       ` Xiaochen Zou
  2021-07-13 10:41         ` Greg KH
  0 siblings, 1 reply; 7+ messages in thread
From: Xiaochen Zou @ 2021-07-13  7:46 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: Greg KH, netdev, stable, kernel, linux-can

j1939_session_destroy() will free both session and session->priv. It
leads to multiple use-after-free read and write in
j1939_session_deactivate() when session was freed in
j1939_session_deactivate_locked(). The free chain is
j1939_session_deactivate_locked()->j1939_session_put()->__j1939_session_release()->j1939_session_destroy().
To fix this bug, I moved j1939_session_put() behind
j1939_session_deactivate_locked() and guarded it with a check of
active since the session would be freed only if active is true.

Signed-off-by: Xiaochen Zou <xzou017@ucr.edu>

diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index e5f1a56994c6..b6448f29a4bd 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -1018,7 +1018,6 @@ static bool
j1939_session_deactivate_locked(struct j1939_session *session)

        list_del_init(&session->active_session_list_entry);
        session->state = J1939_SESSION_DONE;
-       j1939_session_put(session);
    }

    return active;
@@ -1031,6 +1030,9 @@ static bool j1939_session_deactivate(struct
j1939_session *session)
    j1939_session_list_lock(session->priv);
    active = j1939_session_deactivate_locked(session);
    j1939_session_list_unlock(session->priv);
+   if (active) {
+       j1939_session_put(session);
+   }

    return active;
 }
@@ -2021,6 +2023,7 @@ void j1939_simple_recv(struct j1939_priv *priv,
struct sk_buff *skb)
 int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk)
 {
    struct j1939_session *session, *saved;
+   bool active;

    netdev_dbg(priv->ndev, "%s, sk: %p\n", __func__, sk);
    j1939_session_list_lock(priv);
@@ -2030,7 +2033,10 @@ int j1939_cancel_active_session(struct
j1939_priv *priv, struct sock *sk)
        if (!sk || sk == session->sk) {
            j1939_session_timers_cancel(session);
            session->err = ESHUTDOWN;
-           j1939_session_deactivate_locked(session);
+           active = j1939_session_deactivate_locked(session);
+           if (active) {
+               j1939_session_put(session);
+           }
        }
    }
    j1939_session_list_unlock(priv);

On Tue, Jul 13, 2021 at 12:35 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 7/13/21 9:30 AM, Xiaochen Zou wrote:
> > j1939_session_destroy() will free both session and session->priv. It
> > leads to multiple use-after-free read and write in
> > j1939_session_deactivate() when session was freed in
> > j1939_session_deactivate_locked(). The free chain is
> > j1939_session_deactivate_locked()->
> > j1939_session_put()->__j1939_session_release()->j1939_session_destroy().
> > To fix this bug, I moved j1939_session_put() behind
> > j1939_session_deactivate_locked() and guarded it with a check of
> > active since the session would be freed only if active is true.
>
> Please include your Signed-off-by.
> See
> https://elixir.bootlin.com/linux/v5.12/source/Documentation/process/submitting-patches.rst#L356
>
> Marc
>
> --
> Pengutronix e.K.                 | Marc Kleine-Budde           |
> Embedded Linux                   | https://www.pengutronix.de  |
> Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
> Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |
>


-- 
Xiaochen Zou
PhD Student
Department of Computer Science & Engineering
University of California, Riverside

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: Use-after-free access in j1939_session_deactivate
  2021-07-13  7:46       ` Xiaochen Zou
@ 2021-07-13 10:41         ` Greg KH
  0 siblings, 0 replies; 7+ messages in thread
From: Greg KH @ 2021-07-13 10:41 UTC (permalink / raw)
  To: Xiaochen Zou; +Cc: Marc Kleine-Budde, netdev, stable, kernel, linux-can

On Tue, Jul 13, 2021 at 12:46:07AM -0700, Xiaochen Zou wrote:
> j1939_session_destroy() will free both session and session->priv. It
> leads to multiple use-after-free read and write in
> j1939_session_deactivate() when session was freed in
> j1939_session_deactivate_locked(). The free chain is
> j1939_session_deactivate_locked()->j1939_session_put()->__j1939_session_release()->j1939_session_destroy().
> To fix this bug, I moved j1939_session_put() behind
> j1939_session_deactivate_locked() and guarded it with a check of
> active since the session would be freed only if active is true.
> 
> Signed-off-by: Xiaochen Zou <xzou017@ucr.edu>
> 
> diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
> index e5f1a56994c6..b6448f29a4bd 100644
> --- a/net/can/j1939/transport.c
> +++ b/net/can/j1939/transport.c
> @@ -1018,7 +1018,6 @@ static bool
> j1939_session_deactivate_locked(struct j1939_session *session)
> 
>         list_del_init(&session->active_session_list_entry);
>         session->state = J1939_SESSION_DONE;
> -       j1939_session_put(session);
>     }
> 
>     return active;
> @@ -1031,6 +1030,9 @@ static bool j1939_session_deactivate(struct
> j1939_session *session)
>     j1939_session_list_lock(session->priv);
>     active = j1939_session_deactivate_locked(session);
>     j1939_session_list_unlock(session->priv);
> +   if (active) {
> +       j1939_session_put(session);
> +   }
> 
>     return active;
>  }
> @@ -2021,6 +2023,7 @@ void j1939_simple_recv(struct j1939_priv *priv,
> struct sk_buff *skb)
>  int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk)
>  {
>     struct j1939_session *session, *saved;
> +   bool active;
> 
>     netdev_dbg(priv->ndev, "%s, sk: %p\n", __func__, sk);
>     j1939_session_list_lock(priv);
> @@ -2030,7 +2033,10 @@ int j1939_cancel_active_session(struct
> j1939_priv *priv, struct sock *sk)
>         if (!sk || sk == session->sk) {
>             j1939_session_timers_cancel(session);
>             session->err = ESHUTDOWN;
> -           j1939_session_deactivate_locked(session);
> +           active = j1939_session_deactivate_locked(session);
> +           if (active) {
> +               j1939_session_put(session);
> +           }
>         }
>     }
>     j1939_session_list_unlock(priv);
> 
> On Tue, Jul 13, 2021 at 12:35 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> >
> > On 7/13/21 9:30 AM, Xiaochen Zou wrote:
> > > j1939_session_destroy() will free both session and session->priv. It
> > > leads to multiple use-after-free read and write in
> > > j1939_session_deactivate() when session was freed in
> > > j1939_session_deactivate_locked(). The free chain is
> > > j1939_session_deactivate_locked()->
> > > j1939_session_put()->__j1939_session_release()->j1939_session_destroy().
> > > To fix this bug, I moved j1939_session_put() behind
> > > j1939_session_deactivate_locked() and guarded it with a check of
> > > active since the session would be freed only if active is true.
> >
> > Please include your Signed-off-by.
> > See
> > https://elixir.bootlin.com/linux/v5.12/source/Documentation/process/submitting-patches.rst#L356
> >
> > Marc
> >
> > --
> > Pengutronix e.K.                 | Marc Kleine-Budde           |
> > Embedded Linux                   | https://www.pengutronix.de  |
> > Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
> > Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |
> >
> 
> 

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
a patch that has triggered this response.  He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created.  Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- Your patch contains warnings and/or errors noticed by the
  scripts/checkpatch.pl tool.

- Your patch is malformed (tabs converted to spaces, linewrapped, etc.)
  and can not be applied.  Please read the file,
  Documentation/email-clients.txt in order to fix this.

- You did not specify a description of why the patch is needed, or
  possibly, any description at all, in the email body.  Please read the
  section entitled "The canonical patch format" in the kernel file,
  Documentation/SubmittingPatches for what is needed in order to
  properly describe the change.

- You did not write a descriptive Subject: for the patch, allowing Greg,
  and everyone else, to know what this patch is all about.  Please read
  the section entitled "The canonical patch format" in the kernel file,
  Documentation/SubmittingPatches for what a proper Subject: line should
  look like.

- This looks like a new version of a previously submitted patch, but you
  did not list below the --- line any changes from the previous version.
  Please read the section entitled "The canonical patch format" in the
  kernel file, Documentation/SubmittingPatches for what needs to be done
  here to properly describe this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-07-13 10:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-12 22:40 Use-after-free access in j1939_session_deactivate Xiaochen Zou
2021-07-13  4:43 ` Greg KH
2021-07-13  7:30   ` Xiaochen Zou
2021-07-13  7:35     ` Marc Kleine-Budde
2021-07-13  7:46       ` Xiaochen Zou
2021-07-13 10:41         ` Greg KH
2021-07-13  7:10 ` Oleksij Rempel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.