diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2018-10-26 07:44:33 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-10-26 07:44:32 -0700 |
| commit | 5eee6c6d86bc8490ba8dc89ed781a50757812915 (patch) | |
| tree | c9d3cf4e935a524057df852eb0e782f0265bfe7a | |
| parent | e3ef3fd9863ed7dda8271933ac65c6eba8151fbd (diff) | |
| parent | 52ad8f0aff9106ce15cd6c1ff6a029255cb6843a (diff) | |
Merge "ion: remove unsafe function ion_handle_get_by_id()"
| -rw-r--r-- | drivers/staging/android/ion/ion.c | 96 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion_priv.h | 31 | ||||
| -rw-r--r-- | drivers/staging/android/ion/msm/msm_ion.c | 50 |
3 files changed, 132 insertions, 45 deletions
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 65e34250cab2..05fc6a7af8c2 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -3,7 +3,7 @@ * drivers/staging/android/ion/ion.c * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -495,8 +495,8 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, return ERR_PTR(-EINVAL); } -static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, - int id) +struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id) { struct ion_handle *handle; @@ -507,20 +507,7 @@ static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, return ERR_PTR(-EINVAL); } -struct ion_handle *ion_handle_get_by_id(struct ion_client *client, - int id) -{ - struct ion_handle *handle; - - mutex_lock(&client->lock); - handle = ion_handle_get_by_id_nolock(client, id); - mutex_unlock(&client->lock); - - return handle; -} - -static bool ion_handle_validate(struct ion_client *client, - struct ion_handle *handle) +bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) { WARN_ON(!mutex_is_locked(&client->lock)); return idr_find(&client->idr, handle->id) == handle; @@ -674,7 +661,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } EXPORT_SYMBOL(ion_alloc); -static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) +void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) { bool valid_handle; @@ -717,15 +704,17 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_free); -int ion_phys(struct ion_client *client, struct ion_handle *handle, - ion_phys_addr_t *addr, size_t *len) +static int __ion_phys(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len, bool lock_client) { struct ion_buffer *buffer; int ret; - mutex_lock(&client->lock); + if (lock_client) + mutex_lock(&client->lock); if (!ion_handle_validate(client, handle)) { - mutex_unlock(&client->lock); + if (lock_client) + mutex_unlock(&client->lock); return -EINVAL; } @@ -734,15 +723,29 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle, if (!buffer->heap->ops->phys) { pr_err("%s: ion_phys is not implemented by this heap (name=%s, type=%d).\n", __func__, buffer->heap->name, buffer->heap->type); - mutex_unlock(&client->lock); + if (lock_client) + mutex_unlock(&client->lock); return -ENODEV; } - mutex_unlock(&client->lock); + if (lock_client) + mutex_unlock(&client->lock); ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); return ret; } + +int ion_phys(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len) +{ + return __ion_phys(client, handle, addr, len, true); +} EXPORT_SYMBOL(ion_phys); +int ion_phys_nolock(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len) +{ + return __ion_phys(client, handle, addr, len, false); +} + static void *ion_buffer_kmap_get(struct ion_buffer *buffer) { void *vaddr; @@ -1511,7 +1514,8 @@ static int ion_share_dma_buf_fd_nolock(struct ion_client *client, return __ion_share_dma_buf_fd(client, handle, false); } -struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) +static struct ion_handle *__ion_import_dma_buf(struct ion_client *client, + int fd, bool lock_client) { struct dma_buf *dmabuf; struct ion_buffer *buffer; @@ -1531,25 +1535,32 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) } buffer = dmabuf->priv; - mutex_lock(&client->lock); + if (lock_client) + mutex_lock(&client->lock); /* if a handle exists for this buffer just take a reference to it */ handle = ion_handle_lookup(client, buffer); if (!IS_ERR(handle)) { handle = ion_handle_get_check_overflow(handle); - mutex_unlock(&client->lock); + if (lock_client) + mutex_unlock(&client->lock); goto end; } handle = ion_handle_create(client, buffer); if (IS_ERR(handle)) { - mutex_unlock(&client->lock); + if (lock_client) + mutex_unlock(&client->lock); goto end; } ret = ion_handle_add(client, handle); - mutex_unlock(&client->lock); + if (lock_client) + mutex_unlock(&client->lock); if (ret) { - ion_handle_put(handle); + if (lock_client) + ion_handle_put(handle); + else + ion_handle_put_nolock(handle); handle = ERR_PTR(ret); } @@ -1557,8 +1568,18 @@ end: dma_buf_put(dmabuf); return handle; } + +struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) +{ + return __ion_import_dma_buf(client, fd, true); +} EXPORT_SYMBOL(ion_import_dma_buf); +struct ion_handle *ion_import_dma_buf_nolock(struct ion_client *client, int fd) +{ + return __ion_import_dma_buf(client, fd, false); +} + static int ion_sync_for_device(struct ion_client *client, int fd) { struct dma_buf *dmabuf; @@ -2201,3 +2222,18 @@ void __init ion_reserve(struct ion_platform_data *data) data->heaps[i].size); } } + +void lock_client(struct ion_client *client) +{ + mutex_lock(&client->lock); +} + +void unlock_client(struct ion_client *client) +{ + mutex_unlock(&client->lock); +} + +struct ion_buffer *get_buffer(struct ion_handle *handle) +{ + return handle->buffer; +} diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index f2f2ca11c3fa..77bd0f8e4643 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -2,7 +2,7 @@ * drivers/staging/android/ion/ion_priv.h * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -505,9 +505,34 @@ int ion_walk_heaps(struct ion_client *client, int heap_id, enum ion_heap_type type, void *data, int (*f)(struct ion_heap *heap, void *data)); -struct ion_handle *ion_handle_get_by_id(struct ion_client *client, - int id); +struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id); int ion_handle_put(struct ion_handle *handle); +bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle); + +void lock_client(struct ion_client *client); + +void unlock_client(struct ion_client *client); + +struct ion_buffer *get_buffer(struct ion_handle *handle); + +/** + * This function is same as ion_free() except it won't use client->lock. + */ +void ion_free_nolock(struct ion_client *client, struct ion_handle *handle); + +/** + * This function is same as ion_phys() except it won't use client->lock. + */ +int ion_phys_nolock(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len); + +/** + * This function is same as ion_import_dma_buf() except it won't use + * client->lock. + */ +struct ion_handle *ion_import_dma_buf_nolock(struct ion_client *client, int fd); + #endif /* _ION_PRIV_H */ diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 116a6fecaac5..d3069fe4dd78 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -153,7 +153,13 @@ EXPORT_SYMBOL(msm_ion_client_create); int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, void *vaddr, unsigned long len, unsigned int cmd) { - return ion_do_cache_op(client, handle, vaddr, 0, len, cmd); + int ret; + + lock_client(client); + ret = ion_do_cache_op(client, handle, vaddr, 0, len, cmd); + unlock_client(client); + + return ret; } EXPORT_SYMBOL(msm_ion_do_cache_op); @@ -162,7 +168,13 @@ int msm_ion_do_cache_offset_op( void *vaddr, unsigned int offset, unsigned long len, unsigned int cmd) { - return ion_do_cache_op(client, handle, vaddr, offset, len, cmd); + int ret; + + lock_client(client); + ret = ion_do_cache_op(client, handle, vaddr, offset, len, cmd); + unlock_client(client); + + return ret; } EXPORT_SYMBOL(msm_ion_do_cache_offset_op); @@ -179,7 +191,7 @@ static int ion_no_pages_cache_ops(struct ion_client *client, ion_phys_addr_t buff_phys_start = 0; size_t buf_length = 0; - ret = ion_phys(client, handle, &buff_phys_start, &buf_length); + ret = ion_phys_nolock(client, handle, &buff_phys_start, &buf_length); if (ret) return -EINVAL; @@ -293,9 +305,10 @@ static int ion_pages_cache_ops(struct ion_client *client, int i; unsigned int len = 0; void (*op)(const void *, const void *); + struct ion_buffer *buffer; - - table = ion_sg_table(client, handle); + buffer = get_buffer(handle); + table = buffer->sg_table; if (IS_ERR_OR_NULL(table)) return PTR_ERR(table); @@ -344,10 +357,18 @@ int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, unsigned long flags; struct sg_table *table; struct page *page; + struct ion_buffer *buffer; - ret = ion_handle_get_flags(client, handle, &flags); - if (ret) + if (!ion_handle_validate(client, handle)) { + pr_err("%s: invalid handle passed to %s.\n", + __func__, __func__); return -EINVAL; + } + + buffer = get_buffer(handle); + mutex_lock(&buffer->lock); + flags = buffer->flags; + mutex_unlock(&buffer->lock); if (!ION_IS_CACHED(flags)) return 0; @@ -355,7 +376,7 @@ int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, if (get_secure_vmid(flags) > 0) return 0; - table = ion_sg_table(client, handle); + table = buffer->sg_table; if (IS_ERR_OR_NULL(table)) return PTR_ERR(table); @@ -737,19 +758,23 @@ long msm_ion_custom_ioctl(struct ion_client *client, int ret; struct mm_struct *mm = current->active_mm; + lock_client(client); if (data.flush_data.handle > 0) { - handle = ion_handle_get_by_id(client, - (int)data.flush_data.handle); + handle = ion_handle_get_by_id_nolock( + client, (int)data.flush_data.handle); if (IS_ERR(handle)) { pr_info("%s: Could not find handle: %d\n", __func__, (int)data.flush_data.handle); + unlock_client(client); return PTR_ERR(handle); } } else { - handle = ion_import_dma_buf(client, data.flush_data.fd); + handle = ion_import_dma_buf_nolock(client, + data.flush_data.fd); if (IS_ERR(handle)) { pr_info("%s: Could not import handle: %pK\n", __func__, handle); + unlock_client(client); return -EINVAL; } } @@ -772,8 +797,9 @@ long msm_ion_custom_ioctl(struct ion_client *client, } up_read(&mm->mmap_sem); - ion_free(client, handle); + ion_free_nolock(client, handle); + unlock_client(client); if (ret < 0) return ret; break; |
