Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

media: v4l2-core: Introduce v4l2-isp.c

Add to the V4L2 framework helper functions to support drivers when
validating a buffer of V4L2 ISP parameters.

Driver shall use v4l2_isp_params_validate_buffer_size() to verify the
size correctness of the data received from userspace, and after having
copied the data to a kernel-only memory location, complete the
validation by calling v4l2_isp_params_validate_buffer().

Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Michael Riesch <michael.riesch@collabora.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Jacopo Mondi and committed by
Hans Verkuil
3cb6de6f 8923679c

+230
+2
MAINTAINERS
··· 26890 26890 L: linux-media@vger.kernel.org 26891 26891 S: Maintained 26892 26892 F: Documentation/userspace-api/media/v4l/v4l2-isp.rst 26893 + F: drivers/media/v4l2-core/v4l2-isp.c 26894 + F: include/media/v4l2-isp.h 26893 26895 F: include/uapi/linux/media/v4l2-isp.h 26894 26896 26895 26897 VF610 NAND DRIVER
+4
drivers/media/v4l2-core/Kconfig
··· 82 82 depends on I2C 83 83 select REGMAP_I2C 84 84 select V4L2_CCI 85 + 86 + config V4L2_ISP 87 + tristate 88 + depends on VIDEOBUF2_CORE
+1
drivers/media/v4l2-core/Makefile
··· 29 29 obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o 30 30 obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o 31 31 obj-$(CONFIG_V4L2_H264) += v4l2-h264.o 32 + obj-$(CONFIG_V4L2_ISP) += v4l2-isp.o 32 33 obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o 33 34 obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o 34 35 obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o
+132
drivers/media/v4l2-core/v4l2-isp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Video4Linux2 generic ISP parameters and statistics support 4 + * 5 + * Copyright (C) 2025 Ideas On Board Oy 6 + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com> 7 + */ 8 + 9 + #include <media/v4l2-isp.h> 10 + 11 + #include <linux/bitops.h> 12 + #include <linux/device.h> 13 + 14 + #include <media/videobuf2-core.h> 15 + 16 + int v4l2_isp_params_validate_buffer_size(struct device *dev, 17 + struct vb2_buffer *vb, 18 + size_t max_size) 19 + { 20 + size_t header_size = offsetof(struct v4l2_isp_params_buffer, data); 21 + size_t payload_size = vb2_get_plane_payload(vb, 0); 22 + 23 + /* Payload size can't be greater than the destination buffer size */ 24 + if (payload_size > max_size) { 25 + dev_dbg(dev, "Payload size is too large: %zu\n", payload_size); 26 + return -EINVAL; 27 + } 28 + 29 + /* Payload size can't be smaller than the header size */ 30 + if (payload_size < header_size) { 31 + dev_dbg(dev, "Payload size is too small: %zu\n", payload_size); 32 + return -EINVAL; 33 + } 34 + 35 + return 0; 36 + } 37 + EXPORT_SYMBOL_GPL(v4l2_isp_params_validate_buffer_size); 38 + 39 + int v4l2_isp_params_validate_buffer(struct device *dev, struct vb2_buffer *vb, 40 + const struct v4l2_isp_params_buffer *buffer, 41 + const struct v4l2_isp_params_block_info *info, 42 + size_t num_blocks) 43 + { 44 + size_t header_size = offsetof(struct v4l2_isp_params_buffer, data); 45 + size_t payload_size = vb2_get_plane_payload(vb, 0); 46 + size_t block_offset = 0; 47 + size_t buffer_size; 48 + 49 + /* 50 + * Currently only the first version of the V4L2 ISP parameters format is 51 + * supported. We accept both V0 and V1 to support existing drivers 52 + * compatible with V4L2 ISP that use either 0 or 1 as their "first 53 + * version" identifiers. 54 + */ 55 + if (buffer->version != V4L2_ISP_PARAMS_VERSION_V0 && 56 + buffer->version != V4L2_ISP_PARAMS_VERSION_V1) { 57 + dev_dbg(dev, 58 + "Unsupported V4L2 ISP parameters format version: %u\n", 59 + buffer->version); 60 + return -EINVAL; 61 + } 62 + 63 + /* Validate the size reported in the header */ 64 + buffer_size = header_size + buffer->data_size; 65 + if (buffer_size != payload_size) { 66 + dev_dbg(dev, "Data size %zu and payload size %zu are different\n", 67 + buffer_size, payload_size); 68 + return -EINVAL; 69 + } 70 + 71 + /* Walk the list of ISP configuration blocks and validate them. */ 72 + buffer_size = buffer->data_size; 73 + while (buffer_size >= sizeof(struct v4l2_isp_params_block_header)) { 74 + const struct v4l2_isp_params_block_info *block_info; 75 + const struct v4l2_isp_params_block_header *block; 76 + 77 + block = (const struct v4l2_isp_params_block_header *) 78 + (buffer->data + block_offset); 79 + 80 + if (block->type >= num_blocks) { 81 + dev_dbg(dev, 82 + "Invalid block type %u at offset %zu\n", 83 + block->type, block_offset); 84 + return -EINVAL; 85 + } 86 + 87 + if (block->size > buffer_size) { 88 + dev_dbg(dev, "Premature end of parameters data\n"); 89 + return -EINVAL; 90 + } 91 + 92 + /* It's invalid to specify both ENABLE and DISABLE. */ 93 + if ((block->flags & (V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | 94 + V4L2_ISP_PARAMS_FL_BLOCK_DISABLE)) == 95 + (V4L2_ISP_PARAMS_FL_BLOCK_ENABLE | 96 + V4L2_ISP_PARAMS_FL_BLOCK_DISABLE)) { 97 + dev_dbg(dev, "Invalid block flags %x at offset %zu\n", 98 + block->flags, block_offset); 99 + return -EINVAL; 100 + } 101 + 102 + /* 103 + * Match the block reported size against the info provided 104 + * one, but allow the block to only contain the header in 105 + * case it is going to be disabled. 106 + */ 107 + block_info = &info[block->type]; 108 + if (block->size != block_info->size && 109 + (!(block->flags & V4L2_ISP_PARAMS_FL_BLOCK_DISABLE) || 110 + block->size != sizeof(*block))) { 111 + dev_dbg(dev, 112 + "Invalid block size %u (expected %zu) at offset %zu\n", 113 + block->size, block_info->size, block_offset); 114 + return -EINVAL; 115 + } 116 + 117 + block_offset += block->size; 118 + buffer_size -= block->size; 119 + } 120 + 121 + if (buffer_size) { 122 + dev_dbg(dev, "Unexpected data after the parameters buffer end\n"); 123 + return -EINVAL; 124 + } 125 + 126 + return 0; 127 + } 128 + EXPORT_SYMBOL_GPL(v4l2_isp_params_validate_buffer); 129 + 130 + MODULE_LICENSE("GPL"); 131 + MODULE_AUTHOR("Jacopo Mondi <jacopo.mondi@ideasonboard.com"); 132 + MODULE_DESCRIPTION("V4L2 generic ISP parameters and statistics helpers");
+91
include/media/v4l2-isp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Video4Linux2 generic ISP parameters and statistics support 4 + * 5 + * Copyright (C) 2025 Ideas On Board Oy 6 + * Author: Jacopo Mondi <jacopo.mondi@ideasonboard.com> 7 + */ 8 + 9 + #ifndef _V4L2_ISP_H_ 10 + #define _V4L2_ISP_H_ 11 + 12 + #include <linux/media/v4l2-isp.h> 13 + 14 + struct device; 15 + struct vb2_buffer; 16 + 17 + /** 18 + * v4l2_isp_params_buffer_size - Calculate size of v4l2_isp_params_buffer 19 + * @max_params_size: The total size of the ISP configuration blocks 20 + * 21 + * Users of the v4l2 extensible parameters will have differing sized data arrays 22 + * depending on their specific parameter buffers. Drivers and userspace will 23 + * need to be able to calculate the appropriate size of the struct to 24 + * accommodate all ISP configuration blocks provided by the platform. 25 + * This macro provides a convenient tool for the calculation. 26 + */ 27 + #define v4l2_isp_params_buffer_size(max_params_size) \ 28 + (offsetof(struct v4l2_isp_params_buffer, data) + (max_params_size)) 29 + 30 + /** 31 + * v4l2_isp_params_validate_buffer_size - Validate a V4L2 ISP buffer sizes 32 + * @dev: the driver's device pointer 33 + * @vb: the videobuf2 buffer 34 + * @max_size: the maximum allowed buffer size 35 + * 36 + * This function performs validation of the size of a V4L2 ISP parameters buffer 37 + * before the driver can access the actual data buffer content. 38 + * 39 + * After the sizes validation, drivers should copy the buffer content to a 40 + * kernel-only memory area to prevent userspace from modifying it, 41 + * before completing validation using v4l2_isp_params_validate_buffer(). 42 + * 43 + * The @vb buffer as received from the vb2 .buf_prepare() operation is checked 44 + * against @max_size and it's validated to be large enough to accommodate at 45 + * least one ISP configuration block. 46 + */ 47 + int v4l2_isp_params_validate_buffer_size(struct device *dev, 48 + struct vb2_buffer *vb, 49 + size_t max_size); 50 + 51 + /** 52 + * struct v4l2_isp_params_block_info - V4L2 ISP per-block info 53 + * @size: the block expected size 54 + * 55 + * The v4l2_isp_params_block_info collects information of the ISP configuration 56 + * blocks for validation purposes. It currently only contains the expected 57 + * block size. 58 + * 59 + * Drivers shall prepare a list of block info, indexed by block type, one for 60 + * each supported ISP block and correctly populate them with the expected block 61 + * size. 62 + */ 63 + struct v4l2_isp_params_block_info { 64 + size_t size; 65 + }; 66 + 67 + /** 68 + * v4l2_isp_params_validate_buffer - Validate a V4L2 ISP parameters buffer 69 + * @dev: the driver's device pointer 70 + * @vb: the videobuf2 buffer 71 + * @buffer: the V4L2 ISP parameters buffer 72 + * @info: the list of per-block validation info 73 + * @num_blocks: the number of blocks 74 + * 75 + * This function completes the validation of a V4L2 ISP parameters buffer, 76 + * verifying each configuration block correctness before the driver can use 77 + * them to program the hardware. 78 + * 79 + * Drivers should use this function after having validated the correctness of 80 + * the vb2 buffer sizes by using the v4l2_isp_params_validate_buffer_size() 81 + * helper first. Once the buffer size has been validated, drivers should 82 + * perform a copy of the user provided buffer into a kernel-only memory buffer 83 + * to prevent userspace from modifying its content after it has been submitted 84 + * to the driver, and then call this function to complete validation. 85 + */ 86 + int v4l2_isp_params_validate_buffer(struct device *dev, struct vb2_buffer *vb, 87 + const struct v4l2_isp_params_buffer *buffer, 88 + const struct v4l2_isp_params_block_info *info, 89 + size_t num_blocks); 90 + 91 + #endif /* _V4L2_ISP_H_ */