* 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-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
* 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
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 a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).