Commit 9c97ceca authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'misc-habanalabs-fixes-2020-08-22' of...

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
parents 51072c0f 5aba3688
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@

#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/genalloc.h>

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)
	struct hl_device *hdev = hpriv->hdev;
	struct hl_cb *cb;
	phys_addr_t address;
	u32 handle;
	u32 handle, user_cb_size;
	int rc;

	handle = vma->vm_pgoff;
@@ -314,7 +315,8 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
	}

	/* Validation check */
	if ((vma->vm_end - vma->vm_start) != ALIGN(cb->size, PAGE_SIZE)) {
	user_cb_size = vma->vm_end - vma->vm_start;
	if (user_cb_size != ALIGN(cb->size, PAGE_SIZE)) {
		dev_err(hdev->dev,
			"CB mmap failed, mmap size 0x%lx != 0x%x cb size\n",
			vma->vm_end - vma->vm_start, cb->size);
@@ -322,6 +324,16 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
		goto put_cb;
	}

	if (!access_ok((void __user *) (uintptr_t) vma->vm_start,
							user_cb_size)) {
		dev_err(hdev->dev,
			"user pointer is invalid - 0x%lx\n",
			vma->vm_start);

		rc = -EINVAL;
		goto put_cb;
	}

	spin_lock(&cb->lock);

	if (cb->mmap) {
+8 −0
Original line number Diff line number Diff line
@@ -808,6 +808,14 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type,

	/* currently it is guaranteed to have only one chunk */
	chunk = &cs_chunk_array[0];

	if (chunk->queue_index >= hdev->asic_prop.max_queues) {
		dev_err(hdev->dev, "Queue index %d is invalid\n",
			chunk->queue_index);
		rc = -EINVAL;
		goto free_cs_chunk_array;
	}

	q_idx = chunk->queue_index;
	hw_queue_prop = &hdev->asic_prop.hw_queues_props[q_idx];
	q_type = hw_queue_prop->type;
+4 −4
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
static struct dentry *hl_debug_root;

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

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

	if (rc)
		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,
	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
	struct hl_device *hdev = entry->hdev;
	char tmp_buf[32];
	u32 val;
	long val;
	ssize_t rc;

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

	sprintf(tmp_buf, "0x%02x\n", val);
	sprintf(tmp_buf, "0x%02lx\n", val);
	rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,
			strlen(tmp_buf));

+7 −2
Original line number Diff line number Diff line
@@ -288,7 +288,7 @@ static int device_early_init(struct hl_device *hdev)
	for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) {
		snprintf(workq_name, 32, "hl-free-jobs-%u", i);
		hdev->cq_wq[i] = create_singlethread_workqueue(workq_name);
		if (hdev->cq_wq == NULL) {
		if (hdev->cq_wq[i] == NULL) {
			dev_err(hdev->dev, "Failed to allocate CQ workqueue\n");
			rc = -ENOMEM;
			goto free_cq_wq;
@@ -1069,7 +1069,7 @@ again:
			goto out_err;
		}

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

	/* Need to call this again because the max power might change,
	 * depending on card type for certain ASICs
	 */
	hl_set_max_power(hdev);

	/*
	 * hl_hwmon_init() must be called after device_late_init(), because only
	 * there we get the information from the device about which
+9 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/slab.h>

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

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

	if (fw_size > FW_FILE_MAX_SIZE) {
		dev_err(hdev->dev,
			"FW file size %zu exceeds maximum of %u bytes\n",
			fw_size, FW_FILE_MAX_SIZE);
		rc = -EINVAL;
		goto out;
	}

	fw_data = (const u64 *) fw->data;

	memcpy_toio(dst, fw_data, fw_size);
Loading