* [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory
@ 2023-05-30 2:01 Jarkko Sakkinen
2023-05-30 17:36 ` Stefan Berger
2023-05-30 17:45 ` Stefan Berger
0 siblings, 2 replies; 6+ messages in thread
From: Jarkko Sakkinen @ 2023-05-30 2:01 UTC (permalink / raw)
To: linux-integrity
Cc: Jason Gunthorpe, Alejandro Cabrera, Jarkko Sakkinen, stable,
Jarkko Sakkinen, Stefan Berger, linux-kernel
From: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
The driver has two issues (in priority order) in the locality change:
1. The driver uses __user pointer and copy_to_user() and
copy_from_user() with a kernel address during the locality change.
2. For invalid locality change request from user space, the driver
sets errno to EFAULT, while for invalid input data EINVAL should
be used.
Address this by:
1. Introduce __vtpm_proxy_read_unlocked(), __vtpm_proxy_write_unlocked()
and __vtpm_proxy_read_write_locked().
2. Make locality change atomic by calling __vtpm_proxy_read_write_locked(),
instead of tpm_transmit_cmd().
Cc: stable@vger.kernel.org
Fixes: be4c9acfe297 ("tpm: vtpm_proxy: Implement request_locality function.")
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
---
v2:
* Acquiring and releasing mutex in-between should not be an issue
because they are executed with the chip locked.
---
drivers/char/tpm/tpm_vtpm_proxy.c | 162 ++++++++++++++----------------
1 file changed, 73 insertions(+), 89 deletions(-)
diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c
index 30e953988cab..8f43a82e5590 100644
--- a/drivers/char/tpm/tpm_vtpm_proxy.c
+++ b/drivers/char/tpm/tpm_vtpm_proxy.c
@@ -38,7 +38,6 @@ struct proxy_dev {
#define STATE_OPENED_FLAG BIT(0)
#define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */
#define STATE_REGISTERED_FLAG BIT(2)
-#define STATE_DRIVER_COMMAND BIT(3) /* sending a driver specific command */
size_t req_len; /* length of queued TPM request */
size_t resp_len; /* length of queued TPM response */
@@ -58,106 +57,112 @@ static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev);
* Functions related to 'server side'
*/
-/**
- * vtpm_proxy_fops_read - Read TPM commands on 'server side'
- *
- * @filp: file pointer
- * @buf: read buffer
- * @count: number of bytes to read
- * @off: offset
- *
- * Return:
- * Number of bytes read or negative error code
- */
-static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf,
- size_t count, loff_t *off)
+static ssize_t __vtpm_proxy_read_unlocked(struct proxy_dev *proxy_dev, char __user *buf,
+ size_t count)
{
- struct proxy_dev *proxy_dev = filp->private_data;
size_t len;
- int sig, rc;
-
- sig = wait_event_interruptible(proxy_dev->wq,
- proxy_dev->req_len != 0 ||
- !(proxy_dev->state & STATE_OPENED_FLAG));
- if (sig)
- return -EINTR;
-
- mutex_lock(&proxy_dev->buf_lock);
+ int rc;
- if (!(proxy_dev->state & STATE_OPENED_FLAG)) {
- mutex_unlock(&proxy_dev->buf_lock);
+ if (!(proxy_dev->state & STATE_OPENED_FLAG))
return -EPIPE;
- }
len = proxy_dev->req_len;
if (count < len || len > sizeof(proxy_dev->buffer)) {
- mutex_unlock(&proxy_dev->buf_lock);
pr_debug("Invalid size in recv: count=%zd, req_len=%zd\n",
count, len);
return -EIO;
}
- rc = copy_to_user(buf, proxy_dev->buffer, len);
+ if (buf)
+ rc = copy_to_user(buf, proxy_dev->buffer, len);
+
memset(proxy_dev->buffer, 0, len);
proxy_dev->req_len = 0;
if (!rc)
proxy_dev->state |= STATE_WAIT_RESPONSE_FLAG;
- mutex_unlock(&proxy_dev->buf_lock);
-
if (rc)
return -EFAULT;
return len;
}
-/**
- * vtpm_proxy_fops_write - Write TPM responses on 'server side'
- *
- * @filp: file pointer
- * @buf: write buffer
- * @count: number of bytes to write
- * @off: offset
- *
- * Return:
- * Number of bytes read or negative error value
- */
-static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *off)
+static ssize_t __vtpm_proxy_write_unlocked(struct proxy_dev *proxy_dev, const char __user *buf,
+ size_t count)
{
- struct proxy_dev *proxy_dev = filp->private_data;
-
- mutex_lock(&proxy_dev->buf_lock);
-
- if (!(proxy_dev->state & STATE_OPENED_FLAG)) {
- mutex_unlock(&proxy_dev->buf_lock);
+ if (!(proxy_dev->state & STATE_OPENED_FLAG))
return -EPIPE;
- }
if (count > sizeof(proxy_dev->buffer) ||
- !(proxy_dev->state & STATE_WAIT_RESPONSE_FLAG)) {
- mutex_unlock(&proxy_dev->buf_lock);
+ !(proxy_dev->state & STATE_WAIT_RESPONSE_FLAG))
return -EIO;
- }
proxy_dev->state &= ~STATE_WAIT_RESPONSE_FLAG;
proxy_dev->req_len = 0;
- if (copy_from_user(proxy_dev->buffer, buf, count)) {
- mutex_unlock(&proxy_dev->buf_lock);
+ if (buf && copy_from_user(proxy_dev->buffer, buf, count))
return -EFAULT;
- }
proxy_dev->resp_len = count;
+ return count;
+}
+static ssize_t __vtpm_proxy_read_write_unlocked(struct proxy_dev *proxy_dev, char __user *buf,
+ size_t count)
+{
+ ssize_t rc;
+
+ do {
+ rc = __vtpm_proxy_write_unlocked(proxy_dev, buf, count);
+ if (rc < 0)
+ break;
+ rc = __vtpm_proxy_read_unlocked(proxy_dev, buf, rc);
+ } while (0);
+
+ return rc;
+}
+
+/*
+ * See struct file_operations.
+ */
+static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct proxy_dev *proxy_dev = filp->private_data;
+ ssize_t rc;
+ int sig;
+
+ sig = wait_event_interruptible(proxy_dev->wq,
+ proxy_dev->req_len != 0 ||
+ !(proxy_dev->state & STATE_OPENED_FLAG));
+ if (sig)
+ return -EINTR;
+
+ mutex_lock(&proxy_dev->buf_lock);
+ rc = __vtpm_proxy_read_unlocked(proxy_dev, buf, count);
mutex_unlock(&proxy_dev->buf_lock);
+ return rc;
+}
+
+/*
+ * See struct file_operations.
+ */
+static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct proxy_dev *proxy_dev = filp->private_data;
+ int rc;
+
+ mutex_lock(&proxy_dev->buf_lock);
+ rc = __vtpm_proxy_write_unlocked(proxy_dev, buf, count);
+ mutex_unlock(&proxy_dev->buf_lock);
wake_up_interruptible(&proxy_dev->wq);
- return count;
+ return rc;
}
/*
@@ -295,28 +300,6 @@ static int vtpm_proxy_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return len;
}
-static int vtpm_proxy_is_driver_command(struct tpm_chip *chip,
- u8 *buf, size_t count)
-{
- struct tpm_header *hdr = (struct tpm_header *)buf;
-
- if (count < sizeof(struct tpm_header))
- return 0;
-
- if (chip->flags & TPM_CHIP_FLAG_TPM2) {
- switch (be32_to_cpu(hdr->ordinal)) {
- case TPM2_CC_SET_LOCALITY:
- return 1;
- }
- } else {
- switch (be32_to_cpu(hdr->ordinal)) {
- case TPM_ORD_SET_LOCALITY:
- return 1;
- }
- }
- return 0;
-}
-
/*
* Called when core TPM driver forwards TPM requests to 'server side'.
*
@@ -330,6 +313,7 @@ static int vtpm_proxy_is_driver_command(struct tpm_chip *chip,
static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev);
+ unsigned int ord = ((struct tpm_header *)buf)->ordinal;
if (count > sizeof(proxy_dev->buffer)) {
dev_err(&chip->dev,
@@ -338,9 +322,11 @@ static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count)
return -EIO;
}
- if (!(proxy_dev->state & STATE_DRIVER_COMMAND) &&
- vtpm_proxy_is_driver_command(chip, buf, count))
- return -EFAULT;
+ if ((chip->flags & TPM_CHIP_FLAG_TPM2) && ord == TPM2_CC_SET_LOCALITY)
+ return -EINVAL;
+
+ if (ord == TPM_ORD_SET_LOCALITY)
+ return -EINVAL;
mutex_lock(&proxy_dev->buf_lock);
@@ -409,12 +395,10 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality)
return rc;
tpm_buf_append_u8(&buf, locality);
- proxy_dev->state |= STATE_DRIVER_COMMAND;
-
- rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to set locality");
-
- proxy_dev->state &= ~STATE_DRIVER_COMMAND;
-
+ mutex_lock(&proxy_dev->buf_lock);
+ memcpy(proxy_dev->buffer, buf.data, tpm_buf_length(&buf));
+ rc = __vtpm_proxy_read_write_unlocked(proxy_dev, NULL, tpm_buf_length(&buf));
+ mutex_unlock(&proxy_dev->buf_lock);
if (rc < 0) {
locality = rc;
goto out;
--
2.39.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory
2023-05-30 2:01 [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory Jarkko Sakkinen
@ 2023-05-30 17:36 ` Stefan Berger
2023-05-30 17:45 ` Stefan Berger
1 sibling, 0 replies; 6+ messages in thread
From: Stefan Berger @ 2023-05-30 17:36 UTC (permalink / raw)
To: Jarkko Sakkinen, linux-integrity
Cc: Jason Gunthorpe, Alejandro Cabrera, Jarkko Sakkinen, stable,
Stefan Berger, linux-kernel
On 5/29/23 22:01, Jarkko Sakkinen wrote:
> From: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
>
> The driver has two issues (in priority order) in the locality change:
>
> 1. The driver uses __user pointer and copy_to_user() and
> copy_from_user() with a kernel address during the locality change.
This can lead to ... bad things ?
> 2. For invalid locality change request from user space, the driver
> sets errno to EFAULT, while for invalid input data EINVAL should
> be used.
>
> Address this by:
>
> 1. Introduce __vtpm_proxy_read_unlocked(), __vtpm_proxy_write_unlocked()
> and __vtpm_proxy_read_write_locked().
> 2. Make locality change atomic by calling __vtpm_proxy_read_write_locked(),
> instead of tpm_transmit_cmd().
2. sounds like it should be addressable by changing -EFAULT to -EINVAL but there's more to it?
>
> Cc: stable@vger.kernel.org
> Fixes: be4c9acfe297 ("tpm: vtpm_proxy: Implement request_locality function.")
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
> ---
> v2:
> * Acquiring and releasing mutex in-between should not be an issue
> because they are executed with the chip locked.
> ---
> drivers/char/tpm/tpm_vtpm_proxy.c | 162 ++++++++++++++----------------
> 1 file changed, 73 insertions(+), 89 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c
> index 30e953988cab..8f43a82e5590 100644
> --- a/drivers/char/tpm/tpm_vtpm_proxy.c
> +++ b/drivers/char/tpm/tpm_vtpm_proxy.c
> @@ -38,7 +38,6 @@ struct proxy_dev {
> #define STATE_OPENED_FLAG BIT(0)
> #define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */
> #define STATE_REGISTERED_FLAG BIT(2)
> -#define STATE_DRIVER_COMMAND BIT(3) /* sending a driver specific command */
>
> size_t req_len; /* length of queued TPM request */
> size_t resp_len; /* length of queued TPM response */
> @@ -58,106 +57,112 @@ static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev);
> * Functions related to 'server side'
> */
>
> -/**
> - * vtpm_proxy_fops_read - Read TPM commands on 'server side'
> - *
> - * @filp: file pointer
> - * @buf: read buffer
> - * @count: number of bytes to read
> - * @off: offset
> - *
> - * Return:
> - * Number of bytes read or negative error code
> - */
> -static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf,
> - size_t count, loff_t *off)
> +static ssize_t __vtpm_proxy_read_unlocked(struct proxy_dev *proxy_dev, char __user *buf,
> + size_t count)
> {
> - struct proxy_dev *proxy_dev = filp->private_data;
> size_t len;
> - int sig, rc;
> -
> - sig = wait_event_interruptible(proxy_dev->wq,
> - proxy_dev->req_len != 0 ||
> - !(proxy_dev->state & STATE_OPENED_FLAG));
> - if (sig)
> - return -EINTR;
> -
> - mutex_lock(&proxy_dev->buf_lock);
> + int rc;
>
> - if (!(proxy_dev->state & STATE_OPENED_FLAG)) {
> - mutex_unlock(&proxy_dev->buf_lock);
> + if (!(proxy_dev->state & STATE_OPENED_FLAG))
> return -EPIPE;
> - }
>
> len = proxy_dev->req_len;
>
> if (count < len || len > sizeof(proxy_dev->buffer)) {
> - mutex_unlock(&proxy_dev->buf_lock);
> pr_debug("Invalid size in recv: count=%zd, req_len=%zd\n",
> count, len);
> return -EIO;
> }
>
> - rc = copy_to_user(buf, proxy_dev->buffer, len);
> + if (buf)
> + rc = copy_to_user(buf, proxy_dev->buffer, len);
> +
> memset(proxy_dev->buffer, 0, len);
> proxy_dev->req_len = 0;
>
> if (!rc)
> proxy_dev->state |= STATE_WAIT_RESPONSE_FLAG;
>
> - mutex_unlock(&proxy_dev->buf_lock);
> -
> if (rc)
> return -EFAULT;
>
> return len;
> }
>
> -/**
> - * vtpm_proxy_fops_write - Write TPM responses on 'server side'
> - *
> - * @filp: file pointer
> - * @buf: write buffer
> - * @count: number of bytes to write
> - * @off: offset
> - *
> - * Return:
> - * Number of bytes read or negative error value
> - */
> -static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf,
> - size_t count, loff_t *off)
> +static ssize_t __vtpm_proxy_write_unlocked(struct proxy_dev *proxy_dev, const char __user *buf,
> + size_t count)
> {
> - struct proxy_dev *proxy_dev = filp->private_data;
> -
> - mutex_lock(&proxy_dev->buf_lock);
> -
> - if (!(proxy_dev->state & STATE_OPENED_FLAG)) {
> - mutex_unlock(&proxy_dev->buf_lock);
> + if (!(proxy_dev->state & STATE_OPENED_FLAG))
> return -EPIPE;
> - }
>
> if (count > sizeof(proxy_dev->buffer) ||
> - !(proxy_dev->state & STATE_WAIT_RESPONSE_FLAG)) {
> - mutex_unlock(&proxy_dev->buf_lock);
> + !(proxy_dev->state & STATE_WAIT_RESPONSE_FLAG))
> return -EIO;
> - }
>
> proxy_dev->state &= ~STATE_WAIT_RESPONSE_FLAG;
>
> proxy_dev->req_len = 0;
>
> - if (copy_from_user(proxy_dev->buffer, buf, count)) {
> - mutex_unlock(&proxy_dev->buf_lock);
> + if (buf && copy_from_user(proxy_dev->buffer, buf, count))
> return -EFAULT;
> - }
>
> proxy_dev->resp_len = count;
> + return count;
> +}
>
> +static ssize_t __vtpm_proxy_read_write_unlocked(struct proxy_dev *proxy_dev, char __user *buf,
> + size_t count)
> +{
> + ssize_t rc;
> +
> + do {
> + rc = __vtpm_proxy_write_unlocked(proxy_dev, buf, count);
> + if (rc < 0)
> + break;
> + rc = __vtpm_proxy_read_unlocked(proxy_dev, buf, rc);
> + } while (0);
> +
> + return rc;
> +}
> +
> +/*
> + * See struct file_operations.
> + */
> +static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf,
> + size_t count, loff_t *off)
> +{
> + struct proxy_dev *proxy_dev = filp->private_data;
> + ssize_t rc;
> + int sig;
> +
> + sig = wait_event_interruptible(proxy_dev->wq,
> + proxy_dev->req_len != 0 ||
> + !(proxy_dev->state & STATE_OPENED_FLAG));
> + if (sig)
> + return -EINTR;
> +
> + mutex_lock(&proxy_dev->buf_lock);
> + rc = __vtpm_proxy_read_unlocked(proxy_dev, buf, count);
> mutex_unlock(&proxy_dev->buf_lock);
>
> + return rc;
> +}
> +
> +/*
> + * See struct file_operations.
> + */
> +static ssize_t vtpm_proxy_fops_write(struct file *filp, const char __user *buf,
> + size_t count, loff_t *off)
> +{
> + struct proxy_dev *proxy_dev = filp->private_data;
> + int rc;
ssize_t rc;
> +
> + mutex_lock(&proxy_dev->buf_lock);
> + rc = __vtpm_proxy_write_unlocked(proxy_dev, buf, count);
> + mutex_unlock(&proxy_dev->buf_lock);
> wake_up_interruptible(&proxy_dev->wq);
>
> - return count;
> + return rc;
> }
>
> /*
> @@ -295,28 +300,6 @@ static int vtpm_proxy_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> return len;
> }
>
> -static int vtpm_proxy_is_driver_command(struct tpm_chip *chip,
> - u8 *buf, size_t count)
> -{
> - struct tpm_header *hdr = (struct tpm_header *)buf;
> -
> - if (count < sizeof(struct tpm_header))
> - return 0;
> -
> - if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> - switch (be32_to_cpu(hdr->ordinal)) {
> - case TPM2_CC_SET_LOCALITY:
> - return 1;
> - }
> - } else {
> - switch (be32_to_cpu(hdr->ordinal)) {
> - case TPM_ORD_SET_LOCALITY:
> - return 1;
> - }
> - }
> - return 0;
> -}
> -
> /*
> * Called when core TPM driver forwards TPM requests to 'server side'.
> *
> @@ -330,6 +313,7 @@ static int vtpm_proxy_is_driver_command(struct tpm_chip *chip,
> static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count)
> {
> struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev);
> + unsigned int ord = ((struct tpm_header *)buf)->ordinal;
'u32 ordinal' like in tpm_try_transmit ?
you need this here in some form: be32_to_cpu(hdr->ordinal)
>
> if (count > sizeof(proxy_dev->buffer)) {
> dev_err(&chip->dev,(chip->flags & TPM_CHIP_FLAG_TPM2)
> @@ -338,9 +322,11 @@ static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count)
> return -EIO;
> }
>
> - if (!(proxy_dev->state & STATE_DRIVER_COMMAND) &&
> - vtpm_proxy_is_driver_command(chip, buf, count))
> - return -EFAULT;
> + if ((chip->flags & TPM_CHIP_FLAG_TPM2) && ord == TPM2_CC_SET_LOCALITY)
> + return -EINVAL;
> +
> + if (ord == TPM_ORD_SET_LOCALITY)
> + return -EINVAL;
if ((chip->flags & TPM_CHIP_FLAG_TPM2)) {
if (ord == )
return -EINVAL;
} else if (ord == ) {
return -EINVAL;
}
>
> mutex_lock(&proxy_dev->buf_lock);
>
> @@ -409,12 +395,10 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality)
> return rc;
> tpm_buf_append_u8(&buf, locality);
>
> - proxy_dev->state |= STATE_DRIVER_COMMAND;
> -
> - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to set locality");
> -
> - proxy_dev->state &= ~STATE_DRIVER_COMMAND;
> -
> + mutex_lock(&proxy_dev->buf_lock);
> + memcpy(proxy_dev->buffer, buf.data, tpm_buf_length(&buf));
> + rc = __vtpm_proxy_read_write_unlocked(proxy_dev, NULL, tpm_buf_length(&buf));
> + mutex_unlock(&proxy_dev->buf_lock);
> if (rc < 0) {
> locality = rc;
> goto out;
Stefan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory
2023-05-30 2:01 [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory Jarkko Sakkinen
2023-05-30 17:36 ` Stefan Berger
@ 2023-05-30 17:45 ` Stefan Berger
2023-05-31 7:47 ` David Laight
2023-05-31 17:17 ` Jarkko Sakkinen
1 sibling, 2 replies; 6+ messages in thread
From: Stefan Berger @ 2023-05-30 17:45 UTC (permalink / raw)
To: Jarkko Sakkinen, linux-integrity
Cc: Jason Gunthorpe, Alejandro Cabrera, Jarkko Sakkinen, stable,
Stefan Berger, linux-kernel
On 5/29/23 22:01, Jarkko Sakkinen wrote:
> From: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
>
> - rc = copy_to_user(buf, proxy_dev->buffer, len);
> + if (buf)
> + rc = copy_to_user(buf, proxy_dev->buffer, len);
> +
Looking through other drivers it seems buf is always expected to be a valid non-NULL pointer on file_operations.read().
https://elixir.bootlin.com/linux/latest/source/arch/x86/mm/tlb.c#L1279 simple_read_from_buffer will pass the pointer to the user buffer along and it ('to') ends up in copy_to_user(to, ...);
Same here: https://elixir.bootlin.com/linux/latest/source/security/integrity/ima/ima_fs.c#L41
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory
2023-05-30 17:45 ` Stefan Berger
@ 2023-05-31 7:47 ` David Laight
2023-05-31 17:17 ` Jarkko Sakkinen
1 sibling, 0 replies; 6+ messages in thread
From: David Laight @ 2023-05-31 7:47 UTC (permalink / raw)
To: 'Stefan Berger', Jarkko Sakkinen,
linux-integrity@vger.kernel.org
Cc: Jason Gunthorpe, Alejandro Cabrera, Jarkko Sakkinen,
stable@vger.kernel.org, Stefan Berger,
linux-kernel@vger.kernel.org
From: Stefan Berger
> Sent: 30 May 2023 18:46
>
> On 5/29/23 22:01, Jarkko Sakkinen wrote:
> > From: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
> >
>
> > - rc = copy_to_user(buf, proxy_dev->buffer, len);
> > + if (buf)
> > + rc = copy_to_user(buf, proxy_dev->buffer, len);
> > +
>
> Looking through other drivers it seems buf is always expected to be a valid non-NULL pointer on
> file_operations.read().
If the user passes NULL the copy_to/from_user() fails and
-EFAULT is returned.
Adding the NULL check makes the request silently succeed.
I doubt that is anywhere near right when you ignore copy_from_user().
I'm not sure what the rational/subject is about either.
copy_to/from_user() calls access_ok() and will fail on
a kernel address.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory
2023-05-30 17:45 ` Stefan Berger
2023-05-31 7:47 ` David Laight
@ 2023-05-31 17:17 ` Jarkko Sakkinen
2023-05-31 17:20 ` Stefan Berger
1 sibling, 1 reply; 6+ messages in thread
From: Jarkko Sakkinen @ 2023-05-31 17:17 UTC (permalink / raw)
To: Stefan Berger, linux-integrity
Cc: Jason Gunthorpe, Alejandro Cabrera, Jarkko Sakkinen, stable,
Stefan Berger, linux-kernel
On Tue, 2023-05-30 at 13:45 -0400, Stefan Berger wrote:
>
> On 5/29/23 22:01, Jarkko Sakkinen wrote:
> > From: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
> >
>
> > - rc = copy_to_user(buf, proxy_dev->buffer, len);
> > + if (buf)
> > + rc = copy_to_user(buf, proxy_dev->buffer, len);
> > +
>
> Looking through other drivers it seems buf is always expected to be a valid non-NULL pointer on file_operations.read().
>
>
> https://elixir.bootlin.com/linux/latest/source/arch/x86/mm/tlb.c#L1279 simple_read_from_buffer will pass the pointer to the user buffer along and it ('to') ends up in copy_to_user(to, ...);
>
>
> Same here: https://elixir.bootlin.com/linux/latest/source/security/integrity/ima/ima_fs.c#L41
It is good to mention here that IMA uses __user tagged pointers
correctly, and it does not really compare to the vtpm driver code
by any possible means. So let's not add illegit comparison points.
BR, Jarkko
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory
2023-05-31 17:17 ` Jarkko Sakkinen
@ 2023-05-31 17:20 ` Stefan Berger
0 siblings, 0 replies; 6+ messages in thread
From: Stefan Berger @ 2023-05-31 17:20 UTC (permalink / raw)
To: Jarkko Sakkinen, linux-integrity
Cc: Jason Gunthorpe, Alejandro Cabrera, Jarkko Sakkinen, stable,
Stefan Berger, linux-kernel
On 5/31/23 13:17, Jarkko Sakkinen wrote:
> On Tue, 2023-05-30 at 13:45 -0400, Stefan Berger wrote:
>>
>> On 5/29/23 22:01, Jarkko Sakkinen wrote:
>>> From: Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
>>>
>>
>>> - rc = copy_to_user(buf, proxy_dev->buffer, len);
>>> + if (buf)
>>> + rc = copy_to_user(buf, proxy_dev->buffer, len);
>>> +
>>
>> Looking through other drivers it seems buf is always expected to be a valid non-NULL pointer on file_operations.read().
>>
>>
>> https://elixir.bootlin.com/linux/latest/source/arch/x86/mm/tlb.c#L1279 simple_read_from_buffer will pass the pointer to the user buffer along and it ('to') ends up in copy_to_user(to, ...);
>>
>>
>> Same here: https://elixir.bootlin.com/linux/latest/source/security/integrity/ima/ima_fs.c#L41
>
> It is good to mention here that IMA uses __user tagged pointers
> correctly, and it does not really compare to the vtpm driver code
> by any possible means. So let's not add illegit comparison points.
Yes, sir. Did you read David' response?
>
> BR, Jarkko
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-05-31 17:21 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-30 2:01 [PATCH RFC v2] tpm: tpm_vtpm_proxy: do not reference kernel memory as user memory Jarkko Sakkinen
2023-05-30 17:36 ` Stefan Berger
2023-05-30 17:45 ` Stefan Berger
2023-05-31 7:47 ` David Laight
2023-05-31 17:17 ` Jarkko Sakkinen
2023-05-31 17:20 ` Stefan Berger
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).