Merge tag 'LA.UM.9.12.1.r1-11000-SMxx50.QSSI12.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/camera-kernel into android13-4.19-kona
"LA.UM.9.12.1.r1-11000-SMxx50.QSSI12.0" * tag 'LA.UM.9.12.1.r1-11000-SMxx50.QSSI12.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/camera-kernel: msm: camera: isp: Copy the userdata in kernel to avoid TOCTOU Change-Id: I668492b6e074ef57366828c941256bd12911d6e1
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@@ -5663,7 +5663,9 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
break;
|
break;
|
||||||
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
|
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
|
||||||
struct cam_isp_bw_config *bw_config;
|
struct cam_isp_bw_config *bw_config;
|
||||||
|
struct cam_isp_bw_config *bw_config_u;
|
||||||
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
|
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
|
||||||
|
size_t bw_config_size;
|
||||||
|
|
||||||
CAM_WARN_RATE_LIMIT_CUSTOM(CAM_PERF, 300, 1,
|
CAM_WARN_RATE_LIMIT_CUSTOM(CAM_PERF, 300, 1,
|
||||||
"Deprecated Blob TYPE_BW_CONFIG");
|
"Deprecated Blob TYPE_BW_CONFIG");
|
||||||
@@ -5672,11 +5674,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bw_config = (struct cam_isp_bw_config *)blob_data;
|
bw_config_u = (struct cam_isp_bw_config *)blob_data;
|
||||||
|
|
||||||
if (bw_config->num_rdi > CAM_IFE_RDI_NUM_MAX) {
|
if (bw_config_u->num_rdi > CAM_IFE_RDI_NUM_MAX || !bw_config_u->num_rdi) {
|
||||||
CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config",
|
CAM_ERR(CAM_ISP, "Invalid num_rdi %u in bw config, ctx_idx: %u",
|
||||||
|
bw_config_u->num_rdi, ife_mgr_ctx->ctx_index);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bw_config_size = sizeof(struct cam_isp_bw_config) + ((bw_config_u->num_rdi-1)*
|
||||||
|
sizeof(struct cam_isp_bw_vote));
|
||||||
|
|
||||||
|
rc = cam_common_mem_kdup((void **)&bw_config, bw_config_u, bw_config_size);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_ISP, "Alloc and copy request bw_config failed");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (bw_config_u->num_rdi != bw_config->num_rdi) {
|
||||||
|
CAM_ERR(CAM_ISP, "num_rdi changed,userspace:%d, kernel:%d", bw_config_u->num_rdi,
|
||||||
bw_config->num_rdi);
|
bw_config->num_rdi);
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5689,6 +5706,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
"Max size exceeded in bw config num_rdi:%u size per port:%lu",
|
"Max size exceeded in bw config num_rdi:%u size per port:%lu",
|
||||||
bw_config->num_rdi,
|
bw_config->num_rdi,
|
||||||
sizeof(struct cam_isp_bw_vote));
|
sizeof(struct cam_isp_bw_vote));
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5701,12 +5719,14 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
blob_size, sizeof(struct cam_isp_bw_config) +
|
blob_size, sizeof(struct cam_isp_bw_config) +
|
||||||
(bw_config->num_rdi - 1) *
|
(bw_config->num_rdi - 1) *
|
||||||
sizeof(struct cam_isp_bw_vote));
|
sizeof(struct cam_isp_bw_vote));
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prepare || !prepare->priv ||
|
if (!prepare || !prepare->priv ||
|
||||||
(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
|
(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
|
||||||
CAM_ERR(CAM_ISP, "Invalid inputs");
|
CAM_ERR(CAM_ISP, "Invalid inputs");
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5717,11 +5737,13 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
bw_config, sizeof(prepare_hw_data->bw_config[0]));
|
bw_config, sizeof(prepare_hw_data->bw_config[0]));
|
||||||
prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V1;
|
prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V1;
|
||||||
prepare_hw_data->bw_config_valid[bw_config->usage_type] = true;
|
prepare_hw_data->bw_config_valid[bw_config->usage_type] = true;
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2: {
|
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2: {
|
||||||
size_t bw_config_size = 0;
|
size_t bw_config_size = 0;
|
||||||
struct cam_isp_bw_config_v2 *bw_config;
|
struct cam_isp_bw_config_v2 *bw_config;
|
||||||
|
struct cam_isp_bw_config_v2 *bw_config_u;
|
||||||
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
|
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
|
||||||
|
|
||||||
if (blob_size < sizeof(struct cam_isp_bw_config_v2)) {
|
if (blob_size < sizeof(struct cam_isp_bw_config_v2)) {
|
||||||
@@ -5729,12 +5751,28 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bw_config = (struct cam_isp_bw_config_v2 *)blob_data;
|
bw_config_u = (struct cam_isp_bw_config_v2 *)blob_data;
|
||||||
|
|
||||||
if ((bw_config->num_paths > CAM_ISP_MAX_PER_PATH_VOTES) ||
|
if (bw_config_u->num_paths > CAM_ISP_MAX_PER_PATH_VOTES ||
|
||||||
!bw_config->num_paths) {
|
!bw_config_u->num_paths) {
|
||||||
CAM_ERR(CAM_ISP, "Invalid num paths %d",
|
CAM_ERR(CAM_ISP, "Invalid num paths %d ctx_idx: %u",
|
||||||
|
bw_config_u->num_paths, ife_mgr_ctx->ctx_index);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bw_config_size = sizeof(struct cam_isp_bw_config_v2) + ((bw_config_u->num_paths-1)*
|
||||||
|
sizeof(struct cam_axi_per_path_bw_vote));
|
||||||
|
|
||||||
|
rc = cam_common_mem_kdup((void **)&bw_config, bw_config_u, bw_config_size);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_ISP, "Alloc and copy request bw_config failed");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bw_config_u->num_paths != bw_config->num_paths) {
|
||||||
|
CAM_ERR(CAM_ISP, "num_paths changed,userspace:%d, kernel:%d", bw_config_u->num_paths,
|
||||||
bw_config->num_paths);
|
bw_config->num_paths);
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5749,6 +5787,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
bw_config->num_paths - 1,
|
bw_config->num_paths - 1,
|
||||||
sizeof(
|
sizeof(
|
||||||
struct cam_axi_per_path_bw_vote));
|
struct cam_axi_per_path_bw_vote));
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5762,12 +5801,14 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
blob_size, bw_config->num_paths,
|
blob_size, bw_config->num_paths,
|
||||||
sizeof(struct cam_isp_bw_config_v2),
|
sizeof(struct cam_isp_bw_config_v2),
|
||||||
sizeof(struct cam_axi_per_path_bw_vote));
|
sizeof(struct cam_axi_per_path_bw_vote));
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prepare || !prepare->priv ||
|
if (!prepare || !prepare->priv ||
|
||||||
(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
|
(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
|
||||||
CAM_ERR(CAM_ISP, "Invalid inputs");
|
CAM_ERR(CAM_ISP, "Invalid inputs");
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5785,6 +5826,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
|
|
||||||
prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V2;
|
prepare_hw_data->bw_config_version = CAM_ISP_BW_CONFIG_V2;
|
||||||
prepare_hw_data->bw_config_valid[bw_config->usage_type] = true;
|
prepare_hw_data->bw_config_valid[bw_config->usage_type] = true;
|
||||||
|
cam_common_mem_free(bw_config);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG: {
|
case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG: {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
|
||||||
#include "cam_common_util.h"
|
#include "cam_common_util.h"
|
||||||
#include "cam_debug_util.h"
|
#include "cam_debug_util.h"
|
||||||
@@ -48,3 +50,36 @@ uint32_t cam_common_util_remove_duplicate_arr(int32_t *arr, uint32_t num)
|
|||||||
|
|
||||||
return wr_idx;
|
return wr_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cam_common_mem_kdup(void **dst,
|
||||||
|
void *src, size_t size)
|
||||||
|
{
|
||||||
|
gfp_t flag = GFP_KERNEL;
|
||||||
|
|
||||||
|
if (!src || !dst || !size) {
|
||||||
|
CAM_ERR(CAM_UTIL, "Invalid params src: %pK dst: %pK size: %u",
|
||||||
|
src, dst, size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_task())
|
||||||
|
flag = GFP_ATOMIC;
|
||||||
|
|
||||||
|
*dst = kvzalloc(size, flag);
|
||||||
|
if (!*dst) {
|
||||||
|
CAM_ERR(CAM_UTIL, "Failed to allocate memory with size: %u", size);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(*dst, src, size);
|
||||||
|
CAM_DBG(CAM_UTIL, "Allocate and copy memory with size: %u", size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cam_common_mem_kdup);
|
||||||
|
|
||||||
|
void cam_common_mem_free(void *memory)
|
||||||
|
{
|
||||||
|
kvfree(memory);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cam_common_mem_free);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CAM_COMMON_UTIL_H_
|
#ifndef _CAM_COMMON_UTIL_H_
|
||||||
@@ -64,4 +65,22 @@ int cam_common_util_get_string_index(const char **strings,
|
|||||||
uint32_t cam_common_util_remove_duplicate_arr(int32_t *array,
|
uint32_t cam_common_util_remove_duplicate_arr(int32_t *array,
|
||||||
uint32_t num);
|
uint32_t num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief: Memory alloc and copy
|
||||||
|
*
|
||||||
|
* @dst: Address of destination address of memory
|
||||||
|
* @src: Source address of memory
|
||||||
|
* @size: Length of memory
|
||||||
|
*
|
||||||
|
* @return 0 if success in register non-zero if failes
|
||||||
|
*/
|
||||||
|
int cam_common_mem_kdup(void **dst, void *src, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief: Free the memory
|
||||||
|
*
|
||||||
|
* @memory: Address of memory
|
||||||
|
*/
|
||||||
|
void cam_common_mem_free(void *memory);
|
||||||
|
|
||||||
#endif /* _CAM_COMMON_UTIL_H_ */
|
#endif /* _CAM_COMMON_UTIL_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user