Skip to content

Commit

Permalink
habanalabs: don't allow user to destroy CB handle more than once
Browse files Browse the repository at this point in the history
The refcount of a CB buffer is initialized when user allocates a CB,
and is decreased when he destroys the CB handle.

If this refcount is increased also from kernel and user sends more than
one destroy requests for the handle, the buffer will be released/freed
and later be accessed when the refcount is put from kernel side.

To avoid it, prevent user from destroying the handle more than once.

Signed-off-by: Tomer Tayar <ttayar@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
  • Loading branch information
Tomer Tayar authored and ogabbay committed Jan 26, 2023
1 parent 6710444 commit 6003cb4
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 4 deletions.
22 changes: 22 additions & 0 deletions drivers/misc/habanalabs/common/command_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,31 @@ int hl_cb_create(struct hl_device *hdev, struct hl_mem_mgr *mmg,

int hl_cb_destroy(struct hl_mem_mgr *mmg, u64 cb_handle)
{
struct hl_cb *cb;
int rc;

/* Make sure that a CB handle isn't destroyed by user more than once */
if (!mmg->is_kernel_mem_mgr) {
cb = hl_cb_get(mmg, cb_handle);
if (!cb) {
dev_dbg(mmg->dev, "CB destroy failed, no CB was found for handle %#llx\n",
cb_handle);
rc = -EINVAL;
goto out;
}

rc = atomic_cmpxchg(&cb->is_handle_destroyed, 0, 1);
hl_cb_put(cb);
if (rc) {
dev_dbg(mmg->dev, "CB destroy failed, handle %#llx was already destroyed\n",
cb_handle);
rc = -EINVAL;
goto out;
}
}

rc = hl_mmap_mem_buf_put_handle(mmg, cb_handle);
out:
if (rc < 0)
return rc; /* Invalid handle */

Expand Down
2 changes: 1 addition & 1 deletion drivers/misc/habanalabs/common/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,7 @@ static int device_early_init(struct hl_device *hdev)
if (rc)
goto free_chip_info;

hl_mem_mgr_init(hdev->dev, &hdev->kernel_mem_mgr);
hl_mem_mgr_init(hdev->dev, &hdev->kernel_mem_mgr, 1);

hdev->reset_wq = create_singlethread_workqueue("hl_device_reset");
if (!hdev->reset_wq) {
Expand Down
6 changes: 5 additions & 1 deletion drivers/misc/habanalabs/common/habanalabs.h
Original file line number Diff line number Diff line change
Expand Up @@ -872,11 +872,13 @@ struct hl_mmap_mem_buf;
* @dev: back pointer to the owning device
* @lock: protects handles
* @handles: an idr holding all active handles to the memory buffers in the system.
* @is_kernel_mem_mgr: indicate whether the memory manager is the per-device kernel memory manager
*/
struct hl_mem_mgr {
struct device *dev;
spinlock_t lock;
struct idr handles;
u8 is_kernel_mem_mgr;
};

/**
Expand Down Expand Up @@ -935,6 +937,7 @@ struct hl_mmap_mem_buf {
* @size: holds the CB's size.
* @roundup_size: holds the cb size after roundup to page size.
* @cs_cnt: holds number of CS that this CB participates in.
* @is_handle_destroyed: atomic boolean indicating whether or not the CB handle was destroyed.
* @is_pool: true if CB was acquired from the pool, false otherwise.
* @is_internal: internally allocated
* @is_mmu_mapped: true if the CB is mapped to the device's MMU.
Expand All @@ -951,6 +954,7 @@ struct hl_cb {
u32 size;
u32 roundup_size;
atomic_t cs_cnt;
atomic_t is_handle_destroyed;
u8 is_pool;
u8 is_internal;
u8 is_mmu_mapped;
Expand Down Expand Up @@ -3805,7 +3809,7 @@ __printf(4, 5) int hl_snprintf_resize(char **buf, size_t *size, size_t *offset,
char *hl_format_as_binary(char *buf, size_t buf_len, u32 n);
const char *hl_sync_engine_to_string(enum hl_sync_engine_type engine_type);

void hl_mem_mgr_init(struct device *dev, struct hl_mem_mgr *mmg);
void hl_mem_mgr_init(struct device *dev, struct hl_mem_mgr *mmg, u8 is_kernel_mem_mgr);
void hl_mem_mgr_fini(struct hl_mem_mgr *mmg);
int hl_mem_mgr_mmap(struct hl_mem_mgr *mmg, struct vm_area_struct *vma,
void *args);
Expand Down
2 changes: 1 addition & 1 deletion drivers/misc/habanalabs/common/habanalabs_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ int hl_device_open(struct inode *inode, struct file *filp)
nonseekable_open(inode, filp);

hl_ctx_mgr_init(&hpriv->ctx_mgr);
hl_mem_mgr_init(hpriv->hdev->dev, &hpriv->mem_mgr);
hl_mem_mgr_init(hpriv->hdev->dev, &hpriv->mem_mgr, 0);

hpriv->taskpid = get_task_pid(current, PIDTYPE_PID);

Expand Down
4 changes: 3 additions & 1 deletion drivers/misc/habanalabs/common/memory_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,16 @@ int hl_mem_mgr_mmap(struct hl_mem_mgr *mmg, struct vm_area_struct *vma,
*
* @dev: owner device pointer
* @mmg: structure to initialize
* @is_kernel_mem_mgr: indicate whether the memory manager is the per-device kernel memory manager
*
* Initialize an instance of unified memory manager
*/
void hl_mem_mgr_init(struct device *dev, struct hl_mem_mgr *mmg)
void hl_mem_mgr_init(struct device *dev, struct hl_mem_mgr *mmg, u8 is_kernel_mem_mgr)
{
mmg->dev = dev;
spin_lock_init(&mmg->lock);
idr_init(&mmg->handles);
mmg->is_kernel_mem_mgr = is_kernel_mem_mgr;
}

/**
Expand Down

0 comments on commit 6003cb4

Please sign in to comment.