From: Gustavo Padovan <gustavo@padovan.org>
To: dean_jenkins@mentor.com
Cc: linux-bluetooth@vger.kernel.org, marcel@holtmann.org
Subject: Re: [PATCH 3/6] Bluetooth: Return RFCOMM session ptrs to avoid freed session
Date: Tue, 26 Feb 2013 16:21:07 -0300 [thread overview]
Message-ID: <20130226192107.GB4176@joana> (raw)
In-Reply-To: <1361810317-4005-4-git-send-email-dean_jenkins@mentor.com>
Hi Dean,
* dean_jenkins@mentor.com <dean_jenkins@mentor.com> [2013-02-25 16:38:34 +0000]:
> From: Dean Jenkins <Dean_Jenkins@mentor.com>
>
> Unfortunately, the design retains local copies of the s RFCOMM
> session pointer in various code blocks and this invites the erroneous
> access to a freed RFCOMM session structure.
>
> Therefore, return the RFCOMM session pointer back up the call stack
> to avoid accessing a freed RFCOMM session structure. When the RFCOMM
> session is deleted, NULL is passed up the call stack.
>
> If active DLCs exist when the rfcomm session is terminating,
> avoid a memory leak of rfcomm_dlc structures by ensuring that
> rfcomm_session_close() is used instead of rfcomm_session_del().
>
> Signed-off-by: Dean Jenkins <Dean_Jenkins@mentor.com>
> ---
> include/net/bluetooth/rfcomm.h | 3 +-
> net/bluetooth/rfcomm/core.c | 106 +++++++++++++++++++++-------------------
> 2 files changed, 58 insertions(+), 51 deletions(-)
>
> diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
> index e2e3eca..a4e38ea 100644
> --- a/include/net/bluetooth/rfcomm.h
> +++ b/include/net/bluetooth/rfcomm.h
> @@ -278,7 +278,8 @@ void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
>
> static inline void rfcomm_session_hold(struct rfcomm_session *s)
> {
> - atomic_inc(&s->refcnt);
> + if (s)
> + atomic_inc(&s->refcnt);
> }
>
> /* ---- RFCOMM sockets ---- */
> diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
> index af0c26d..60d2f1a 100644
> --- a/net/bluetooth/rfcomm/core.c
> +++ b/net/bluetooth/rfcomm/core.c
> @@ -69,7 +69,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
> u8 sec_level,
> int *err);
> static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
> -static void rfcomm_session_del(struct rfcomm_session *s);
> +static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s);
>
> /* ---- RFCOMM frame parsing macros ---- */
> #define __get_dlci(b) ((b & 0xfc) >> 2)
> @@ -108,10 +108,12 @@ static void rfcomm_schedule(void)
> wake_up_process(rfcomm_thread);
> }
>
> -static void rfcomm_session_put(struct rfcomm_session *s)
> +static struct rfcomm_session *rfcomm_session_put(struct rfcomm_session *s)
> {
> - if (atomic_dec_and_test(&s->refcnt))
> - rfcomm_session_del(s);
> + if (s && atomic_dec_and_test(&s->refcnt))
> + s = rfcomm_session_del(s);
> +
> + return s;
> }
>
> /* ---- RFCOMM FCS computation ---- */
> @@ -631,7 +633,7 @@ static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
> return s;
> }
>
> -static void rfcomm_session_del(struct rfcomm_session *s)
> +static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s)
> {
> int state = s->state;
>
> @@ -648,6 +650,8 @@ static void rfcomm_session_del(struct rfcomm_session *s)
>
> if (state != BT_LISTEN)
> module_put(THIS_MODULE);
> +
> + return NULL;
> }
>
> static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
> @@ -666,7 +670,8 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
> return NULL;
> }
>
> -static void rfcomm_session_close(struct rfcomm_session *s, int err)
> +static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s,
> + int err)
wrong identation here, you have to align with the opening parenthesis:
static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s,
int err)
> {
> struct rfcomm_dlc *d;
> struct list_head *p, *n;
> @@ -685,7 +690,7 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
> }
>
> rfcomm_session_clear_timer(s);
> - rfcomm_session_put(s);
> + return rfcomm_session_put(s);
> }
>
> static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
> @@ -737,8 +742,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
> if (*err == 0 || *err == -EINPROGRESS)
> return s;
>
> - rfcomm_session_del(s);
> - return NULL;
> + return rfcomm_session_del(s);
>
> failed:
> sock_release(sock);
> @@ -1127,7 +1131,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
> }
>
> /* ---- RFCOMM frame reception ---- */
> -static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
> +static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
> {
> BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
>
> @@ -1136,7 +1140,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
> struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci);
> if (!d) {
> rfcomm_send_dm(s, dlci);
> - return 0;
> + return s;
> }
>
> switch (d->state) {
> @@ -1172,25 +1176,14 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
> break;
>
> case BT_DISCONN:
> - /* rfcomm_session_put is called later so don't do
> - * anything here otherwise we will mess up the session
> - * reference counter:
> - *
> - * (a) when we are the initiator dlc_unlink will drive
> - * the reference counter to 0 (there is no initial put
> - * after session_add)
> - *
> - * (b) when we are not the initiator rfcomm_rx_process
> - * will explicitly call put to balance the initial hold
> - * done after session add.
> - */
> + s = rfcomm_session_close(s, ECONNRESET);
> break;
> }
> }
> - return 0;
> + return s;
> }
>
> -static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
> +static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
> {
> int err = 0;
>
> @@ -1215,12 +1208,13 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
> err = ECONNRESET;
>
> s->state = BT_CLOSED;
> - rfcomm_session_close(s, err);
> + s = rfcomm_session_close(s, err);
> }
> - return 0;
> + return s;
> }
>
> -static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
> +static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s,
> + u8 dlci)
> {
> int err = 0;
>
> @@ -1250,10 +1244,9 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
> err = ECONNRESET;
>
> s->state = BT_CLOSED;
> - rfcomm_session_close(s, err);
> + s = rfcomm_session_close(s, err);
> }
> -
> - return 0;
> + return s;
> }
>
> void rfcomm_dlc_accept(struct rfcomm_dlc *d)
> @@ -1674,11 +1667,18 @@ drop:
> return 0;
> }
>
> -static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb)
> +static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s,
> + struct sk_buff *skb)
Same here.
Please fix this. You can collect Marcel's Ack and add them to your patches and
resend and updated version with these fixes in it.
Gustavo
next prev parent reply other threads:[~2013-02-26 19:21 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-25 16:38 [PATCH 0/6] Bluetooth: Rework the RFCOMM session refcnt dean_jenkins
2013-02-25 16:38 ` [PATCH 1/6] Bluetooth: Avoid rfcomm_session_timeout using freed session dean_jenkins
2013-02-25 16:38 ` [PATCH 2/6] Bluetooth: Check rfcomm session and DLC exists on socket close dean_jenkins
2013-02-26 19:12 ` Gustavo Padovan
2013-02-25 16:38 ` [PATCH 3/6] Bluetooth: Return RFCOMM session ptrs to avoid freed session dean_jenkins
2013-02-26 19:21 ` Gustavo Padovan [this message]
2013-02-25 16:38 ` [PATCH 4/6] Bluetooth: Remove RFCOMM session refcnt dean_jenkins
2013-02-25 23:08 ` David Herrmann
2013-02-25 16:38 ` [PATCH 5/6] Bluetooth: Remove redundant call to rfcomm_send_disc dean_jenkins
2013-02-25 16:38 ` [PATCH 6/6] Bluetooth: Remove redundant RFCOMM BT_CLOSED settings dean_jenkins
2013-02-25 18:32 ` [PATCH 0/6] Bluetooth: Rework the RFCOMM session refcnt Marcel Holtmann
2013-02-26 18:13 ` Dean Jenkins
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130226192107.GB4176@joana \
--to=gustavo@padovan.org \
--cc=dean_jenkins@mentor.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox