Skip to content

Commit 9c97cec

Browse files
committed
Merge tag 'misc-habanalabs-fixes-2020-08-22' of git://people.freedesktop.org/~gabbayo/linux into char-misc-linus
Oded writes: This tag contains the following bug fixes for 5.9-rc2/3: - Correct cleanup of PCI bar mapping in case of failure during initialization. - Several security fixes: - Validating user addresses before mapping them - Validating packet id (from user) before using it as index for array. - Validating F/W file size before coping it. - Prevent possible overflow when validating address from user in profiler. - Validate queue index (from user) before using it as index for array. - Check for correct vmalloc return code - Fix memory corruption in debugfs entry - Fix a loop in gaudi_extract_ecc_info() - Fix the set clock gating function in gaudi code - Set maximum power to F/W according to the card type - Cix incorrect check on failed workqueue create - Correctly report error when configuring the PCI controller * tag 'misc-habanalabs-fixes-2020-08-22' of git://people.freedesktop.org/~gabbayo/linux: habanalabs: correctly report inbound pci region cfg error habanalabs: check correct vmalloc return code habanalabs: validate FW file size habanalabs: fix incorrect check on failed workqueue create habanalabs: set max power according to card type habanalabs: proper handling of alloc size in coresight habanalabs: set clock gating according to mask habanalabs: verify user input in cs_ioctl_signal_wait habanalabs: Fix a loop in gaudi_extract_ecc_info() habanalabs: Fix memory corruption in debugfs habanalabs: validate packet id during CB parse habanalabs: Validate user address before mapping habanalabs: unmap PCI bars upon iATU failure
2 parents 51072c0 + 5aba368 commit 9c97cec

15 files changed

Lines changed: 178 additions & 47 deletions

File tree

drivers/misc/habanalabs/common/command_buffer.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <linux/mm.h>
1212
#include <linux/slab.h>
13+
#include <linux/uaccess.h>
1314
#include <linux/genalloc.h>
1415

1516
static void cb_fini(struct hl_device *hdev, struct hl_cb *cb)
@@ -300,7 +301,7 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
300301
struct hl_device *hdev = hpriv->hdev;
301302
struct hl_cb *cb;
302303
phys_addr_t address;
303-
u32 handle;
304+
u32 handle, user_cb_size;
304305
int rc;
305306

306307
handle = vma->vm_pgoff;
@@ -314,14 +315,25 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
314315
}
315316

316317
/* Validation check */
317-
if ((vma->vm_end - vma->vm_start) != ALIGN(cb->size, PAGE_SIZE)) {
318+
user_cb_size = vma->vm_end - vma->vm_start;
319+
if (user_cb_size != ALIGN(cb->size, PAGE_SIZE)) {
318320
dev_err(hdev->dev,
319321
"CB mmap failed, mmap size 0x%lx != 0x%x cb size\n",
320322
vma->vm_end - vma->vm_start, cb->size);
321323
rc = -EINVAL;
322324
goto put_cb;
323325
}
324326

327+
if (!access_ok((void __user *) (uintptr_t) vma->vm_start,
328+
user_cb_size)) {
329+
dev_err(hdev->dev,
330+
"user pointer is invalid - 0x%lx\n",
331+
vma->vm_start);
332+
333+
rc = -EINVAL;
334+
goto put_cb;
335+
}
336+
325337
spin_lock(&cb->lock);
326338

327339
if (cb->mmap) {

drivers/misc/habanalabs/common/command_submission.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,14 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type,
808808

809809
/* currently it is guaranteed to have only one chunk */
810810
chunk = &cs_chunk_array[0];
811+
812+
if (chunk->queue_index >= hdev->asic_prop.max_queues) {
813+
dev_err(hdev->dev, "Queue index %d is invalid\n",
814+
chunk->queue_index);
815+
rc = -EINVAL;
816+
goto free_cs_chunk_array;
817+
}
818+
811819
q_idx = chunk->queue_index;
812820
hw_queue_prop = &hdev->asic_prop.hw_queues_props[q_idx];
813821
q_type = hw_queue_prop->type;

drivers/misc/habanalabs/common/debugfs.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
static struct dentry *hl_debug_root;
2020

2121
static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
22-
u8 i2c_reg, u32 *val)
22+
u8 i2c_reg, long *val)
2323
{
2424
struct armcp_packet pkt;
2525
int rc;
@@ -36,7 +36,7 @@ static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
3636
pkt.i2c_reg = i2c_reg;
3737

3838
rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
39-
0, (long *) val);
39+
0, val);
4040

4141
if (rc)
4242
dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc);
@@ -827,7 +827,7 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,
827827
struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
828828
struct hl_device *hdev = entry->hdev;
829829
char tmp_buf[32];
830-
u32 val;
830+
long val;
831831
ssize_t rc;
832832

833833
if (*ppos)
@@ -842,7 +842,7 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,
842842
return rc;
843843
}
844844

845-
sprintf(tmp_buf, "0x%02x\n", val);
845+
sprintf(tmp_buf, "0x%02lx\n", val);
846846
rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,
847847
strlen(tmp_buf));
848848

drivers/misc/habanalabs/common/device.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ static int device_early_init(struct hl_device *hdev)
288288
for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) {
289289
snprintf(workq_name, 32, "hl-free-jobs-%u", i);
290290
hdev->cq_wq[i] = create_singlethread_workqueue(workq_name);
291-
if (hdev->cq_wq == NULL) {
291+
if (hdev->cq_wq[i] == NULL) {
292292
dev_err(hdev->dev, "Failed to allocate CQ workqueue\n");
293293
rc = -ENOMEM;
294294
goto free_cq_wq;
@@ -1069,7 +1069,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset,
10691069
goto out_err;
10701070
}
10711071

1072-
hl_set_max_power(hdev, hdev->max_power);
1072+
hl_set_max_power(hdev);
10731073
} else {
10741074
rc = hdev->asic_funcs->soft_reset_late_init(hdev);
10751075
if (rc) {
@@ -1318,6 +1318,11 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
13181318
goto out_disabled;
13191319
}
13201320

1321+
/* Need to call this again because the max power might change,
1322+
* depending on card type for certain ASICs
1323+
*/
1324+
hl_set_max_power(hdev);
1325+
13211326
/*
13221327
* hl_hwmon_init() must be called after device_late_init(), because only
13231328
* there we get the information from the device about which

drivers/misc/habanalabs/common/firmware_if.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/io-64-nonatomic-lo-hi.h>
1414
#include <linux/slab.h>
1515

16+
#define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */
1617
/**
1718
* hl_fw_load_fw_to_device() - Load F/W code to device's memory.
1819
*
@@ -48,6 +49,14 @@ int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name,
4849

4950
dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size);
5051

52+
if (fw_size > FW_FILE_MAX_SIZE) {
53+
dev_err(hdev->dev,
54+
"FW file size %zu exceeds maximum of %u bytes\n",
55+
fw_size, FW_FILE_MAX_SIZE);
56+
rc = -EINVAL;
57+
goto out;
58+
}
59+
5160
fw_data = (const u64 *) fw->data;
5261

5362
memcpy_toio(dst, fw_data, fw_size);

drivers/misc/habanalabs/common/habanalabs.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,8 @@ struct hl_device_idle_busy_ts {
14621462
* details.
14631463
* @in_reset: is device in reset flow.
14641464
* @curr_pll_profile: current PLL profile.
1465+
* @card_type: Various ASICs have several card types. This indicates the card
1466+
* type of the current device.
14651467
* @cs_active_cnt: number of active command submissions on this device (active
14661468
* means already in H/W queues)
14671469
* @major: habanalabs kernel driver major.
@@ -1566,6 +1568,7 @@ struct hl_device {
15661568
u64 clock_gating_mask;
15671569
atomic_t in_reset;
15681570
enum hl_pll_frequency curr_pll_profile;
1571+
enum armcp_card_types card_type;
15691572
int cs_active_cnt;
15701573
u32 major;
15711574
u32 high_pll;
@@ -1651,7 +1654,7 @@ struct hl_ioctl_desc {
16511654
*
16521655
* Return: true if the area is inside the valid range, false otherwise.
16531656
*/
1654-
static inline bool hl_mem_area_inside_range(u64 address, u32 size,
1657+
static inline bool hl_mem_area_inside_range(u64 address, u64 size,
16551658
u64 range_start_address, u64 range_end_address)
16561659
{
16571660
u64 end_address = address + size;
@@ -1858,7 +1861,7 @@ int hl_get_pwm_info(struct hl_device *hdev,
18581861
void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
18591862
long value);
18601863
u64 hl_get_max_power(struct hl_device *hdev);
1861-
void hl_set_max_power(struct hl_device *hdev, u64 value);
1864+
void hl_set_max_power(struct hl_device *hdev);
18621865
int hl_set_voltage(struct hl_device *hdev,
18631866
int sensor_index, u32 attr, long value);
18641867
int hl_set_current(struct hl_device *hdev,

drivers/misc/habanalabs/common/memory.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
6666
num_pgs = (args->alloc.mem_size + (page_size - 1)) >> page_shift;
6767
total_size = num_pgs << page_shift;
6868

69+
if (!total_size) {
70+
dev_err(hdev->dev, "Cannot allocate 0 bytes\n");
71+
return -EINVAL;
72+
}
73+
6974
contiguous = args->flags & HL_MEM_CONTIGUOUS;
7075

7176
if (contiguous) {
@@ -93,7 +98,7 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
9398
phys_pg_pack->contiguous = contiguous;
9499

95100
phys_pg_pack->pages = kvmalloc_array(num_pgs, sizeof(u64), GFP_KERNEL);
96-
if (!phys_pg_pack->pages) {
101+
if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
97102
rc = -ENOMEM;
98103
goto pages_arr_err;
99104
}
@@ -683,7 +688,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
683688

684689
phys_pg_pack->pages = kvmalloc_array(total_npages, sizeof(u64),
685690
GFP_KERNEL);
686-
if (!phys_pg_pack->pages) {
691+
if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
687692
rc = -ENOMEM;
688693
goto page_pack_arr_mem_err;
689694
}

drivers/misc/habanalabs/common/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ int hl_mmu_init(struct hl_device *hdev)
450450
hdev->mmu_shadow_hop0 = kvmalloc_array(prop->max_asid,
451451
prop->mmu_hop_table_size,
452452
GFP_KERNEL | __GFP_ZERO);
453-
if (!hdev->mmu_shadow_hop0) {
453+
if (ZERO_OR_NULL_PTR(hdev->mmu_shadow_hop0)) {
454454
rc = -ENOMEM;
455455
goto err_pool_add;
456456
}

drivers/misc/habanalabs/common/pci.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region,
227227
}
228228

229229
/* Point to the specified address */
230-
rc = hl_pci_iatu_write(hdev, offset + 0x14,
230+
rc |= hl_pci_iatu_write(hdev, offset + 0x14,
231231
lower_32_bits(pci_region->addr));
232232
rc |= hl_pci_iatu_write(hdev, offset + 0x18,
233233
upper_32_bits(pci_region->addr));
@@ -369,15 +369,17 @@ int hl_pci_init(struct hl_device *hdev)
369369
rc = hdev->asic_funcs->init_iatu(hdev);
370370
if (rc) {
371371
dev_err(hdev->dev, "Failed to initialize iATU\n");
372-
goto disable_device;
372+
goto unmap_pci_bars;
373373
}
374374

375375
rc = hl_pci_set_dma_mask(hdev);
376376
if (rc)
377-
goto disable_device;
377+
goto unmap_pci_bars;
378378

379379
return 0;
380380

381+
unmap_pci_bars:
382+
hl_pci_bars_unmap(hdev);
381383
disable_device:
382384
pci_clear_master(pdev);
383385
pci_disable_device(pdev);

drivers/misc/habanalabs/common/sysfs.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ u64 hl_get_max_power(struct hl_device *hdev)
8181
return result;
8282
}
8383

84-
void hl_set_max_power(struct hl_device *hdev, u64 value)
84+
void hl_set_max_power(struct hl_device *hdev)
8585
{
8686
struct armcp_packet pkt;
8787
int rc;
@@ -90,7 +90,7 @@ void hl_set_max_power(struct hl_device *hdev, u64 value)
9090

9191
pkt.ctl = cpu_to_le32(ARMCP_PACKET_MAX_POWER_SET <<
9292
ARMCP_PKT_CTL_OPCODE_SHIFT);
93-
pkt.value = cpu_to_le64(value);
93+
pkt.value = cpu_to_le64(hdev->max_power);
9494

9595
rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
9696
0, NULL);
@@ -316,7 +316,7 @@ static ssize_t max_power_store(struct device *dev,
316316
}
317317

318318
hdev->max_power = value;
319-
hl_set_max_power(hdev, value);
319+
hl_set_max_power(hdev);
320320

321321
out:
322322
return count;
@@ -422,6 +422,7 @@ int hl_sysfs_init(struct hl_device *hdev)
422422
hdev->pm_mng_profile = PM_AUTO;
423423
else
424424
hdev->pm_mng_profile = PM_MANUAL;
425+
425426
hdev->max_power = hdev->asic_prop.max_power_default;
426427

427428
hdev->asic_funcs->add_device_attr(hdev, &hl_dev_clks_attr_group);

0 commit comments

Comments
 (0)