2022-08-19 17:29:03

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.10 540/545] tee: add overflow check in register_shm_helper()

From: Jens Wiklander <[email protected]>

commit 573ae4f13f630d6660008f1974c0a8a29c30e18a upstream.

With special lengths supplied by user space, register_shm_helper() has
an integer overflow when calculating the number of pages covered by a
supplied user space memory region.

This causes internal_get_user_pages_fast() a helper function of
pin_user_pages_fast() to do a NULL pointer dereference:

Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010
Modules linked in:
CPU: 1 PID: 173 Comm: optee_example_a Not tainted 5.19.0 #11
Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015
pc : internal_get_user_pages_fast+0x474/0xa80
Call trace:
internal_get_user_pages_fast+0x474/0xa80
pin_user_pages_fast+0x24/0x4c
register_shm_helper+0x194/0x330
tee_shm_register_user_buf+0x78/0x120
tee_ioctl+0xd0/0x11a0
__arm64_sys_ioctl+0xa8/0xec
invoke_syscall+0x48/0x114

Fix this by adding an an explicit call to access_ok() in
tee_shm_register_user_buf() to catch an invalid user space address
early.

Fixes: 033ddf12bcf5 ("tee: add register user memory")
Cc: [email protected]
Reported-by: Nimish Mishra <[email protected]>
Reported-by: Anirban Chakraborty <[email protected]>
Reported-by: Debdeep Mukhopadhyay <[email protected]>
Suggested-by: Jerome Forissier <[email protected]>
Signed-off-by: Jens Wiklander <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/tee/tee_shm.c | 3 +++
1 file changed, 3 insertions(+)

--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -222,6 +222,9 @@ struct tee_shm *tee_shm_register(struct
goto err;
}

+ if (!access_ok((void __user *)addr, length))
+ return ERR_PTR(-EFAULT);
+
mutex_lock(&teedev->mutex);
shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
mutex_unlock(&teedev->mutex);



2022-08-22 11:26:10

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 5.10 540/545] tee: add overflow check in register_shm_helper()

Hi!

> From: Jens Wiklander <[email protected]>
>
> commit 573ae4f13f630d6660008f1974c0a8a29c30e18a upstream.
>
> With special lengths supplied by user space, register_shm_helper() has
> an integer overflow when calculating the number of pages covered by a
> supplied user space memory region.
>
> This causes internal_get_user_pages_fast() a helper function of
> pin_user_pages_fast() to do a NULL pointer dereference:

Maybe this needs fixing, but this fix adds a memory leak or two. Note
the goto err, that needs to be done.

Best regards,
Pavel

Signed-off-by: Pavel Machek <[email protected]>

> +++ b/drivers/tee/tee_shm.c
> @@ -222,6 +222,9 @@ struct tee_shm *tee_shm_register(struct
> goto err;
> }
>
> + if (!access_ok((void __user *)addr, length))
> + return ERR_PTR(-EFAULT);
> +
> mutex_lock(&teedev->mutex);
> shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> mutex_unlock(&teedev->mutex);
>


diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 6e662fb131d5..283fa50676a2 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -222,8 +222,10 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
goto err;
}

- if (!access_ok((void __user *)addr, length))
- return ERR_PTR(-EFAULT);
+ if (!access_ok((void __user *)addr, length)) {
+ ret = ERR_PTR(-EFAULT);
+ goto err;
+ }

mutex_lock(&teedev->mutex);
shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);

--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


Attachments:
(No filename) (1.64 kB)
signature.asc (201.00 B)
Download all attachments

2022-08-22 13:04:56

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH 5.10 540/545] tee: add overflow check in register_shm_helper()

Hi,

On Mon, Aug 22, 2022 at 1:15 PM Pavel Machek <[email protected]> wrote:
>
> Hi!
>
> > From: Jens Wiklander <[email protected]>
> >
> > commit 573ae4f13f630d6660008f1974c0a8a29c30e18a upstream.
> >
> > With special lengths supplied by user space, register_shm_helper() has
> > an integer overflow when calculating the number of pages covered by a
> > supplied user space memory region.
> >
> > This causes internal_get_user_pages_fast() a helper function of
> > pin_user_pages_fast() to do a NULL pointer dereference:
>
> Maybe this needs fixing, but this fix adds a memory leak or two. Note
> the goto err, that needs to be done.

Thanks for bringing this up. I believe the best option is to take the
backport I just did for 5.4, it should apply cleanly on the 5.10
stable kernel too.

Greg, can you cherry-pick the 5.4 backport patch, or would you rather
have an explicit backport for this stable kernel?

Cheers,
Jens

>
> Best regards,
> Pavel
>
> Signed-off-by: Pavel Machek <[email protected]>
>
> > +++ b/drivers/tee/tee_shm.c
> > @@ -222,6 +222,9 @@ struct tee_shm *tee_shm_register(struct
> > goto err;
> > }
> >
> > + if (!access_ok((void __user *)addr, length))
> > + return ERR_PTR(-EFAULT);
> > +
> > mutex_lock(&teedev->mutex);
> > shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> > mutex_unlock(&teedev->mutex);
> >
>
>
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index 6e662fb131d5..283fa50676a2 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -222,8 +222,10 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> goto err;
> }
>
> - if (!access_ok((void __user *)addr, length))
> - return ERR_PTR(-EFAULT);
> + if (!access_ok((void __user *)addr, length)) {
> + ret = ERR_PTR(-EFAULT);
> + goto err;
> + }
>
> mutex_lock(&teedev->mutex);
> shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
>
> --
> DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

2022-08-22 13:22:36

by Jens Wiklander

[permalink] [raw]
Subject: Re: [PATCH 5.10 540/545] tee: add overflow check in register_shm_helper()

On Mon, Aug 22, 2022 at 3:03 PM Jens Wiklander
<[email protected]> wrote:
>
> Hi,
>
> On Mon, Aug 22, 2022 at 1:15 PM Pavel Machek <[email protected]> wrote:
> >
> > Hi!
> >
> > > From: Jens Wiklander <[email protected]>
> > >
> > > commit 573ae4f13f630d6660008f1974c0a8a29c30e18a upstream.
> > >
> > > With special lengths supplied by user space, register_shm_helper() has
> > > an integer overflow when calculating the number of pages covered by a
> > > supplied user space memory region.
> > >
> > > This causes internal_get_user_pages_fast() a helper function of
> > > pin_user_pages_fast() to do a NULL pointer dereference:
> >
> > Maybe this needs fixing, but this fix adds a memory leak or two. Note
> > the goto err, that needs to be done.
>
> Thanks for bringing this up. I believe the best option is to take the
> backport I just did for 5.4, it should apply cleanly on the 5.10
> stable kernel too.
>
> Greg, can you cherry-pick the 5.4 backport patch, or would you rather
> have an explicit backport for this stable kernel?

I'm sorry, I'm confused by all the backports. I haven't posted the 5.4
yet, I've only just tested it. I'll tag that backport patch for 5.10
stable too.

Thanks,
Jens

>
> Cheers,
> Jens
>
> >
> > Best regards,
> > Pavel
> >
> > Signed-off-by: Pavel Machek <[email protected]>
> >
> > > +++ b/drivers/tee/tee_shm.c
> > > @@ -222,6 +222,9 @@ struct tee_shm *tee_shm_register(struct
> > > goto err;
> > > }
> > >
> > > + if (!access_ok((void __user *)addr, length))
> > > + return ERR_PTR(-EFAULT);
> > > +
> > > mutex_lock(&teedev->mutex);
> > > shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> > > mutex_unlock(&teedev->mutex);
> > >
> >
> >
> > diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> > index 6e662fb131d5..283fa50676a2 100644
> > --- a/drivers/tee/tee_shm.c
> > +++ b/drivers/tee/tee_shm.c
> > @@ -222,8 +222,10 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
> > goto err;
> > }
> >
> > - if (!access_ok((void __user *)addr, length))
> > - return ERR_PTR(-EFAULT);
> > + if (!access_ok((void __user *)addr, length)) {
> > + ret = ERR_PTR(-EFAULT);
> > + goto err;
> > + }
> >
> > mutex_lock(&teedev->mutex);
> > shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
> >
> > --
> > DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
> > HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany