diff mbox

[RESEND,2/4] NFC: st21nfca: Fix memory OOB and leak issues in connectivity events handler

Message ID 1524045904-7005-3-git-send-email-amit.pundir@linaro.org (mailing list archive)
State Accepted
Delegated to: Samuel Ortiz
Headers show

Commit Message

Amit Pundir April 18, 2018, 10:05 a.m. UTC
From: Suren Baghdasaryan <surenb@google.com>

Overflow on memcpy is possible in kernel driver for st21nfca's
NFC HCI layer when handling connectivity events if aid_len or
params_len are bigger than the buffer size.
Memory leak is possible when parameter tag is invalid.

Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
---
 drivers/nfc/st21nfca/se.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

Comments

Andy Shevchenko April 20, 2018, 12:39 p.m. UTC | #1
On Wed, 2018-04-18 at 15:35 +0530, Amit Pundir wrote:

>  		if (skb->data[transaction->aid_len + 2] !=
> -		    NFC_EVT_TRANSACTION_PARAMS_TAG)
> +		    NFC_EVT_TRANSACTION_PARAMS_TAG ||
> +		    skb->len < transaction->aid_len + transaction-
> >params_len + 4) {

> +			devm_kfree(dev, transaction);

Oh, no.

This is not memory leak per se, this is bad choice of devm_ API where it
should use plain kmalloc() / kfree().

>  			return -EPROTO;
> +		}
Mark Greer April 20, 2018, 4:45 p.m. UTC | #2
On Fri, Apr 20, 2018 at 03:39:46PM +0300, Andy Shevchenko wrote:
> On Wed, 2018-04-18 at 15:35 +0530, Amit Pundir wrote:
> 
> >  		if (skb->data[transaction->aid_len + 2] !=
> > -		    NFC_EVT_TRANSACTION_PARAMS_TAG)
> > +		    NFC_EVT_TRANSACTION_PARAMS_TAG ||
> > +		    skb->len < transaction->aid_len + transaction-
> > >params_len + 4) {
> 
> > +			devm_kfree(dev, transaction);
> 
> Oh, no.
> 
> This is not memory leak per se, this is bad choice of devm_ API where it
> should use plain kmalloc() / kfree().

Also, there is no check to see if the allocation worked at all.

Mark
--
Amit Pundir April 23, 2018, 5:20 p.m. UTC | #3
On 20 April 2018 at 18:09, Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
> On Wed, 2018-04-18 at 15:35 +0530, Amit Pundir wrote:
>
>>               if (skb->data[transaction->aid_len + 2] !=
>> -                 NFC_EVT_TRANSACTION_PARAMS_TAG)
>> +                 NFC_EVT_TRANSACTION_PARAMS_TAG ||
>> +                 skb->len < transaction->aid_len + transaction-
>> >params_len + 4) {
>
>> +                     devm_kfree(dev, transaction);
>
> Oh, no.
>
> This is not memory leak per se, this is bad choice of devm_ API where it
> should use plain kmalloc() / kfree().
>

Hi, If I switch to kmalloc()/kfree() with allocation and may be
pre-usage checks along the way up to nfc_genl_se_transaction() would
that suffice? I believe, I still be needing the additional aid_len and
params_len checks regardless, right?

Regards,
Amit Pundir

>>                       return -EPROTO;
>> +             }
>
> --
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Intel Finland Oy
Amit Pundir April 23, 2018, 5:21 p.m. UTC | #4
On 20 April 2018 at 22:15, Mark Greer <mgreer@animalcreek.com> wrote:
> On Fri, Apr 20, 2018 at 03:39:46PM +0300, Andy Shevchenko wrote:
>> On Wed, 2018-04-18 at 15:35 +0530, Amit Pundir wrote:
>>
>> >             if (skb->data[transaction->aid_len + 2] !=
>> > -               NFC_EVT_TRANSACTION_PARAMS_TAG)
>> > +               NFC_EVT_TRANSACTION_PARAMS_TAG ||
>> > +               skb->len < transaction->aid_len + transaction-
>> > >params_len + 4) {
>>
>> > +                   devm_kfree(dev, transaction);
>>
>> Oh, no.
>>
>> This is not memory leak per se, this is bad choice of devm_ API where it
>> should use plain kmalloc() / kfree().
>
> Also, there is no check to see if the allocation worked at all.

Ack. I'll add that in v2.
Thanks.

Regards,
Amit Pundir

>
> Mark
> --
diff mbox

Patch

diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c
index 4bed9e842db3..acdce231e227 100644
--- a/drivers/nfc/st21nfca/se.c
+++ b/drivers/nfc/st21nfca/se.c
@@ -322,23 +322,33 @@  int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
 		 * AID		81	5 to 16
 		 * PARAMETERS	82	0 to 255
 		 */
-		if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
+		if (skb->len < NFC_MIN_AID_LENGTH + 2 ||
 		    skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
 			return -EPROTO;
 
+		/*
+		 * Buffer should have enough space for at least
+		 * two tag fields + two length fields + aid_len (skb->data[1])
+		 */
+		if (skb->len < skb->data[1] + 4)
+			return -EPROTO;
+
 		transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
 						   skb->len - 2, GFP_KERNEL);
 
 		transaction->aid_len = skb->data[1];
 		memcpy(transaction->aid, &skb->data[2],
 		       transaction->aid_len);
+		transaction->params_len = skb->data[transaction->aid_len + 3];
 
-		/* Check next byte is PARAMETERS tag (82) */
+		/* Check next byte is PARAMETERS tag (82) and the length field */
 		if (skb->data[transaction->aid_len + 2] !=
-		    NFC_EVT_TRANSACTION_PARAMS_TAG)
+		    NFC_EVT_TRANSACTION_PARAMS_TAG ||
+		    skb->len < transaction->aid_len + transaction->params_len + 4) {
+			devm_kfree(dev, transaction);
 			return -EPROTO;
+		}
 
-		transaction->params_len = skb->data[transaction->aid_len + 3];
 		memcpy(transaction->params, skb->data +
 		       transaction->aid_len + 4, transaction->params_len);