1 From 8438846cce61e284a22316c13aa4b63772963070 Mon Sep 17 00:00:00 2001
2 From: Jann Horn <jannh@google.com>
3 Date: Sat, 4 May 2019 15:56:08 +0200
4 Subject: habanalabs: fix debugfs code
6 From: Jann Horn <jannh@google.com>
8 commit 8438846cce61e284a22316c13aa4b63772963070 upstream.
10 This fixes multiple things in the habanalabs debugfs code, in particular:
12 - mmu_write() was unnecessarily verbose, copying around between multiple
14 - mmu_write() could write a user-specified, unbounded amount of userspace
15 memory into a kernel buffer (out-of-bounds write)
16 - multiple debugfs read handlers ignored the user-supplied count,
17 potentially corrupting out-of-bounds userspace data
18 - hl_device_read() was unnecessarily verbose
19 - hl_device_write() could read uninitialized stack memory
20 - multiple debugfs read handlers copied terminating null characters to
23 Signed-off-by: Jann Horn <jannh@google.com>
24 Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
25 Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
26 Cc: stable@vger.kernel.org
27 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
30 drivers/misc/habanalabs/debugfs.c | 60 +++++++++++---------------------------
31 1 file changed, 18 insertions(+), 42 deletions(-)
33 --- a/drivers/misc/habanalabs/debugfs.c
34 +++ b/drivers/misc/habanalabs/debugfs.c
35 @@ -459,41 +459,31 @@ static ssize_t mmu_write(struct file *fi
36 struct hl_debugfs_entry *entry = s->private;
37 struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
38 struct hl_device *hdev = dev_entry->hdev;
39 - char kbuf[MMU_KBUF_SIZE], asid_kbuf[MMU_ASID_BUF_SIZE],
40 - addr_kbuf[MMU_ADDR_BUF_SIZE];
41 + char kbuf[MMU_KBUF_SIZE];
45 if (!hdev->mmu_enable)
48 - memset(kbuf, 0, sizeof(kbuf));
49 - memset(asid_kbuf, 0, sizeof(asid_kbuf));
50 - memset(addr_kbuf, 0, sizeof(addr_kbuf));
52 + if (count > sizeof(kbuf) - 1)
54 if (copy_from_user(kbuf, buf, count))
57 - kbuf[MMU_KBUF_SIZE - 1] = 0;
60 c = strchr(kbuf, ' ');
65 - memcpy(asid_kbuf, kbuf, c - kbuf);
67 - rc = kstrtouint(asid_kbuf, 10, &dev_entry->mmu_asid);
68 + rc = kstrtouint(kbuf, 10, &dev_entry->mmu_asid);
72 - c = strstr(kbuf, " 0x");
74 + if (strncmp(c+1, "0x", 2))
78 - memcpy(addr_kbuf, c, (kbuf + count) - c);
80 - rc = kstrtoull(addr_kbuf, 16, &dev_entry->mmu_addr);
81 + rc = kstrtoull(c+3, 16, &dev_entry->mmu_addr);
85 @@ -525,10 +515,8 @@ static ssize_t hl_data_read32(struct fil
88 sprintf(tmp_buf, "0x%08x\n", val);
89 - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
90 - strlen(tmp_buf) + 1);
93 + return simple_read_from_buffer(buf, count, ppos, tmp_buf,
97 static ssize_t hl_data_write32(struct file *f, const char __user *buf,
98 @@ -559,7 +547,6 @@ static ssize_t hl_get_power_state(struct
99 struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
100 struct hl_device *hdev = entry->hdev;
106 @@ -574,10 +561,8 @@ static ssize_t hl_get_power_state(struct
109 "current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i);
110 - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
111 - strlen(tmp_buf) + 1);
114 + return simple_read_from_buffer(buf, count, ppos, tmp_buf,
118 static ssize_t hl_set_power_state(struct file *f, const char __user *buf,
119 @@ -630,8 +615,8 @@ static ssize_t hl_i2c_data_read(struct f
122 sprintf(tmp_buf, "0x%02x\n", val);
123 - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
124 - strlen(tmp_buf) + 1);
125 + rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,
130 @@ -720,18 +705,9 @@ static ssize_t hl_led2_write(struct file
131 static ssize_t hl_device_read(struct file *f, char __user *buf,
132 size_t count, loff_t *ppos)
141 - "Valid values: disable, enable, suspend, resume, cpu_timeout\n");
142 - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
143 - strlen(tmp_buf) + 1);
146 + static const char *help =
147 + "Valid values: disable, enable, suspend, resume, cpu_timeout\n";
148 + return simple_read_from_buffer(buf, count, ppos, help, strlen(help));
151 static ssize_t hl_device_write(struct file *f, const char __user *buf,
152 @@ -739,7 +715,7 @@ static ssize_t hl_device_write(struct fi
154 struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
155 struct hl_device *hdev = entry->hdev;
157 + char data[30] = {0};
159 /* don't allow partial writes */