Commit 8438846c authored by Jann Horn's avatar Jann Horn Committed by Oded Gabbay

habanalabs: fix debugfs code

This fixes multiple things in the habanalabs debugfs code, in particular:

 - mmu_write() was unnecessarily verbose, copying around between multiple
   buffers
 - mmu_write() could write a user-specified, unbounded amount of userspace
   memory into a kernel buffer (out-of-bounds write)
 - multiple debugfs read handlers ignored the user-supplied count,
   potentially corrupting out-of-bounds userspace data
 - hl_device_read() was unnecessarily verbose
 - hl_device_write() could read uninitialized stack memory
 - multiple debugfs read handlers copied terminating null characters to
   userspace
Signed-off-by: default avatarJann Horn <jannh@google.com>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Cc: stable@vger.kernel.org
parent 2add64eb
...@@ -459,41 +459,31 @@ static ssize_t mmu_write(struct file *file, const char __user *buf, ...@@ -459,41 +459,31 @@ static ssize_t mmu_write(struct file *file, const char __user *buf,
struct hl_debugfs_entry *entry = s->private; struct hl_debugfs_entry *entry = s->private;
struct hl_dbg_device_entry *dev_entry = entry->dev_entry; struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
struct hl_device *hdev = dev_entry->hdev; struct hl_device *hdev = dev_entry->hdev;
char kbuf[MMU_KBUF_SIZE], asid_kbuf[MMU_ASID_BUF_SIZE], char kbuf[MMU_KBUF_SIZE];
addr_kbuf[MMU_ADDR_BUF_SIZE];
char *c; char *c;
ssize_t rc; ssize_t rc;
if (!hdev->mmu_enable) if (!hdev->mmu_enable)
return count; return count;
memset(kbuf, 0, sizeof(kbuf)); if (count > sizeof(kbuf) - 1)
memset(asid_kbuf, 0, sizeof(asid_kbuf)); goto err;
memset(addr_kbuf, 0, sizeof(addr_kbuf));
if (copy_from_user(kbuf, buf, count)) if (copy_from_user(kbuf, buf, count))
goto err; goto err;
kbuf[count] = 0;
kbuf[MMU_KBUF_SIZE - 1] = 0;
c = strchr(kbuf, ' '); c = strchr(kbuf, ' ');
if (!c) if (!c)
goto err; goto err;
*c = '\0';
memcpy(asid_kbuf, kbuf, c - kbuf); rc = kstrtouint(kbuf, 10, &dev_entry->mmu_asid);
rc = kstrtouint(asid_kbuf, 10, &dev_entry->mmu_asid);
if (rc) if (rc)
goto err; goto err;
c = strstr(kbuf, " 0x"); if (strncmp(c+1, "0x", 2))
if (!c)
goto err; goto err;
rc = kstrtoull(c+3, 16, &dev_entry->mmu_addr);
c += 3;
memcpy(addr_kbuf, c, (kbuf + count) - c);
rc = kstrtoull(addr_kbuf, 16, &dev_entry->mmu_addr);
if (rc) if (rc)
goto err; goto err;
...@@ -600,10 +590,8 @@ static ssize_t hl_data_read32(struct file *f, char __user *buf, ...@@ -600,10 +590,8 @@ static ssize_t hl_data_read32(struct file *f, char __user *buf,
} }
sprintf(tmp_buf, "0x%08x\n", val); sprintf(tmp_buf, "0x%08x\n", val);
rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, return simple_read_from_buffer(buf, count, ppos, tmp_buf,
strlen(tmp_buf) + 1); strlen(tmp_buf));
return rc;
} }
static ssize_t hl_data_write32(struct file *f, const char __user *buf, static ssize_t hl_data_write32(struct file *f, const char __user *buf,
...@@ -645,7 +633,6 @@ static ssize_t hl_get_power_state(struct file *f, char __user *buf, ...@@ -645,7 +633,6 @@ static ssize_t hl_get_power_state(struct file *f, char __user *buf,
struct hl_dbg_device_entry *entry = file_inode(f)->i_private; struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
struct hl_device *hdev = entry->hdev; struct hl_device *hdev = entry->hdev;
char tmp_buf[200]; char tmp_buf[200];
ssize_t rc;
int i; int i;
if (*ppos) if (*ppos)
...@@ -660,10 +647,8 @@ static ssize_t hl_get_power_state(struct file *f, char __user *buf, ...@@ -660,10 +647,8 @@ static ssize_t hl_get_power_state(struct file *f, char __user *buf,
sprintf(tmp_buf, sprintf(tmp_buf,
"current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i); "current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i);
rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, return simple_read_from_buffer(buf, count, ppos, tmp_buf,
strlen(tmp_buf) + 1); strlen(tmp_buf));
return rc;
} }
static ssize_t hl_set_power_state(struct file *f, const char __user *buf, static ssize_t hl_set_power_state(struct file *f, const char __user *buf,
...@@ -716,8 +701,8 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf, ...@@ -716,8 +701,8 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,
} }
sprintf(tmp_buf, "0x%02x\n", val); sprintf(tmp_buf, "0x%02x\n", val);
rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,
strlen(tmp_buf) + 1); strlen(tmp_buf));
return rc; return rc;
} }
...@@ -806,18 +791,9 @@ static ssize_t hl_led2_write(struct file *f, const char __user *buf, ...@@ -806,18 +791,9 @@ static ssize_t hl_led2_write(struct file *f, const char __user *buf,
static ssize_t hl_device_read(struct file *f, char __user *buf, static ssize_t hl_device_read(struct file *f, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
char tmp_buf[200]; static const char *help =
ssize_t rc; "Valid values: disable, enable, suspend, resume, cpu_timeout\n";
return simple_read_from_buffer(buf, count, ppos, help, strlen(help));
if (*ppos)
return 0;
sprintf(tmp_buf,
"Valid values: disable, enable, suspend, resume, cpu_timeout\n");
rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
strlen(tmp_buf) + 1);
return rc;
} }
static ssize_t hl_device_write(struct file *f, const char __user *buf, static ssize_t hl_device_write(struct file *f, const char __user *buf,
...@@ -825,7 +801,7 @@ static ssize_t hl_device_write(struct file *f, const char __user *buf, ...@@ -825,7 +801,7 @@ static ssize_t hl_device_write(struct file *f, const char __user *buf,
{ {
struct hl_dbg_device_entry *entry = file_inode(f)->i_private; struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
struct hl_device *hdev = entry->hdev; struct hl_device *hdev = entry->hdev;
char data[30]; char data[30] = {0};
/* don't allow partial writes */ /* don't allow partial writes */
if (*ppos != 0) if (*ppos != 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment