mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-01 00:58:39 +02:00 
			
		
		
		
	overflow: Add struct_size_t() helper
While struct_size() is normally used in situations where the structure
type already has a pointer instance, there are places where no variable
is available. In the past, this has been worked around by using a typed
NULL first argument, but this is a bit ugly. Add a helper to do this,
and replace the handful of instances of the code pattern with it.
Instances were found with this Coccinelle script:
@struct_size_t@
identifier STRUCT, MEMBER;
expression COUNT;
@@
-       struct_size((struct STRUCT *)\(0\|NULL\),
+       struct_size_t(struct STRUCT,
                MEMBER, COUNT)
Suggested-by: Christoph Hellwig <hch@infradead.org>
Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
Cc: Tony Nguyen <anthony.l.nguyen@intel.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: James Smart <james.smart@broadcom.com>
Cc: Keith Busch <kbusch@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Sagi Grimberg <sagi@grimberg.me>
Cc: HighPoint Linux Team <linux@highpoint-tech.com>
Cc: "James E.J. Bottomley" <jejb@linux.ibm.com>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Cc: Kashyap Desai <kashyap.desai@broadcom.com>
Cc: Sumit Saxena <sumit.saxena@broadcom.com>
Cc: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
Cc: Don Brace <don.brace@microchip.com>
Cc: "Darrick J. Wong" <djwong@kernel.org>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: Guo Xuenan <guoxuenan@huawei.com>
Cc: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Daniel Latypov <dlatypov@google.com>
Cc: kernel test robot <lkp@intel.com>
Cc: intel-wired-lan@lists.osuosl.org
Cc: netdev@vger.kernel.org
Cc: linux-nvme@lists.infradead.org
Cc: linux-scsi@vger.kernel.org
Cc: megaraidlinux.pdl@broadcom.com
Cc: storagedev@microchip.com
Cc: linux-xfs@vger.kernel.org
Cc: linux-hardening@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Link: https://lore.kernel.org/r/20230522211810.never.421-kees@kernel.org
			
			
This commit is contained in:
		
							parent
							
								
									7f09a3a09f
								
							
						
					
					
						commit
						d67790ddf0
					
				
					 10 changed files with 40 additions and 25 deletions
				
			
		|  | @ -185,7 +185,7 @@ struct ice_buf_hdr { | ||||||
| 
 | 
 | ||||||
| #define ICE_MAX_ENTRIES_IN_BUF(hd_sz, ent_sz)                                 \ | #define ICE_MAX_ENTRIES_IN_BUF(hd_sz, ent_sz)                                 \ | ||||||
| 	((ICE_PKG_BUF_SIZE -                                                  \ | 	((ICE_PKG_BUF_SIZE -                                                  \ | ||||||
| 	  struct_size((struct ice_buf_hdr *)0, section_entry, 1) - (hd_sz)) / \ | 	  struct_size_t(struct ice_buf_hdr,  section_entry, 1) - (hd_sz)) / \ | ||||||
| 	 (ent_sz)) | 	 (ent_sz)) | ||||||
| 
 | 
 | ||||||
| /* ice package section IDs */ | /* ice package section IDs */ | ||||||
|  | @ -297,7 +297,7 @@ struct ice_label_section { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define ICE_MAX_LABELS_IN_BUF                                             \ | #define ICE_MAX_LABELS_IN_BUF                                             \ | ||||||
| 	ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_label_section *)0, \ | 	ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_label_section,  \ | ||||||
| 					   label, 1) -                    \ | 					   label, 1) -                    \ | ||||||
| 				       sizeof(struct ice_label),          \ | 				       sizeof(struct ice_label),          \ | ||||||
| 			       sizeof(struct ice_label)) | 			       sizeof(struct ice_label)) | ||||||
|  | @ -352,7 +352,7 @@ struct ice_boost_tcam_section { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define ICE_MAX_BST_TCAMS_IN_BUF                                               \ | #define ICE_MAX_BST_TCAMS_IN_BUF                                               \ | ||||||
| 	ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_boost_tcam_section *)0, \ | 	ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_boost_tcam_section,  \ | ||||||
| 					   tcam, 1) -                          \ | 					   tcam, 1) -                          \ | ||||||
| 				       sizeof(struct ice_boost_tcam_entry),    \ | 				       sizeof(struct ice_boost_tcam_entry),    \ | ||||||
| 			       sizeof(struct ice_boost_tcam_entry)) | 			       sizeof(struct ice_boost_tcam_entry)) | ||||||
|  | @ -372,8 +372,7 @@ struct ice_marker_ptype_tcam_section { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define ICE_MAX_MARKER_PTYPE_TCAMS_IN_BUF                                    \ | #define ICE_MAX_MARKER_PTYPE_TCAMS_IN_BUF                                    \ | ||||||
| 	ICE_MAX_ENTRIES_IN_BUF(                                              \ | 	ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_marker_ptype_tcam_section,  tcam, \ | ||||||
| 		struct_size((struct ice_marker_ptype_tcam_section *)0, tcam, \ |  | ||||||
| 			    1) -                                             \ | 			    1) -                                             \ | ||||||
| 			sizeof(struct ice_marker_ptype_tcam_entry),          \ | 			sizeof(struct ice_marker_ptype_tcam_entry),          \ | ||||||
| 		sizeof(struct ice_marker_ptype_tcam_entry)) | 		sizeof(struct ice_marker_ptype_tcam_entry)) | ||||||
|  |  | ||||||
|  | @ -2917,7 +2917,7 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl) | ||||||
| 
 | 
 | ||||||
| 	ret = nvme_alloc_io_tag_set(&ctrl->ctrl, &ctrl->tag_set, | 	ret = nvme_alloc_io_tag_set(&ctrl->ctrl, &ctrl->tag_set, | ||||||
| 			&nvme_fc_mq_ops, 1, | 			&nvme_fc_mq_ops, 1, | ||||||
| 			struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv, | 			struct_size_t(struct nvme_fcp_op_w_sgl, priv, | ||||||
| 				      ctrl->lport->ops->fcprqst_priv_sz)); | 				      ctrl->lport->ops->fcprqst_priv_sz)); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
|  | @ -3536,7 +3536,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, | ||||||
| 
 | 
 | ||||||
| 	ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set, | 	ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set, | ||||||
| 			&nvme_fc_admin_mq_ops, | 			&nvme_fc_admin_mq_ops, | ||||||
| 			struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv, | 			struct_size_t(struct nvme_fcp_op_w_sgl, priv, | ||||||
| 				      ctrl->lport->ops->fcprqst_priv_sz)); | 				      ctrl->lport->ops->fcprqst_priv_sz)); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail_ctrl; | 		goto fail_ctrl; | ||||||
|  |  | ||||||
|  | @ -1394,7 +1394,7 @@ static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id) | ||||||
| 	host->cmd_per_lun = le32_to_cpu(iop_config.max_requests); | 	host->cmd_per_lun = le32_to_cpu(iop_config.max_requests); | ||||||
| 	host->max_cmd_len = 16; | 	host->max_cmd_len = 16; | ||||||
| 
 | 
 | ||||||
| 	req_size = struct_size((struct hpt_iop_request_scsi_command *)0, | 	req_size = struct_size_t(struct hpt_iop_request_scsi_command, | ||||||
| 				 sg_list, hba->max_sg_descriptors); | 				 sg_list, hba->max_sg_descriptors); | ||||||
| 	if ((req_size & 0x1f) != 0) | 	if ((req_size & 0x1f) != 0) | ||||||
| 		req_size = (req_size + 0x1f) & ~0x1f; | 		req_size = (req_size + 0x1f) & ~0x1f; | ||||||
|  |  | ||||||
|  | @ -5153,7 +5153,7 @@ static void megasas_update_ext_vd_details(struct megasas_instance *instance) | ||||||
| 		fusion->max_map_sz = ventura_map_sz; | 		fusion->max_map_sz = ventura_map_sz; | ||||||
| 	} else { | 	} else { | ||||||
| 		fusion->old_map_sz = | 		fusion->old_map_sz = | ||||||
| 			struct_size((struct MR_FW_RAID_MAP *)0, ldSpanMap, | 			struct_size_t(struct MR_FW_RAID_MAP, ldSpanMap, | ||||||
| 				      instance->fw_supported_vd_count); | 				      instance->fw_supported_vd_count); | ||||||
| 		fusion->new_map_sz =  sizeof(struct MR_FW_RAID_MAP_EXT); | 		fusion->new_map_sz =  sizeof(struct MR_FW_RAID_MAP_EXT); | ||||||
| 
 | 
 | ||||||
|  | @ -5789,7 +5789,7 @@ megasas_setup_jbod_map(struct megasas_instance *instance) | ||||||
| 	struct fusion_context *fusion = instance->ctrl_context; | 	struct fusion_context *fusion = instance->ctrl_context; | ||||||
| 	size_t pd_seq_map_sz; | 	size_t pd_seq_map_sz; | ||||||
| 
 | 
 | ||||||
| 	pd_seq_map_sz = struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0, seq, | 	pd_seq_map_sz = struct_size_t(struct MR_PD_CFG_SEQ_NUM_SYNC, seq, | ||||||
| 				      MAX_PHYSICAL_DEVICES); | 				      MAX_PHYSICAL_DEVICES); | ||||||
| 
 | 
 | ||||||
| 	instance->use_seqnum_jbod_fp = | 	instance->use_seqnum_jbod_fp = | ||||||
|  | @ -8033,7 +8033,7 @@ static void megasas_detach_one(struct pci_dev *pdev) | ||||||
| 	if (instance->adapter_type != MFI_SERIES) { | 	if (instance->adapter_type != MFI_SERIES) { | ||||||
| 		megasas_release_fusion(instance); | 		megasas_release_fusion(instance); | ||||||
| 		pd_seq_map_sz = | 		pd_seq_map_sz = | ||||||
| 			struct_size((struct MR_PD_CFG_SEQ_NUM_SYNC *)0, | 			struct_size_t(struct MR_PD_CFG_SEQ_NUM_SYNC, | ||||||
| 				      seq, MAX_PHYSICAL_DEVICES); | 				      seq, MAX_PHYSICAL_DEVICES); | ||||||
| 		for (i = 0; i < 2 ; i++) { | 		for (i = 0; i < 2 ; i++) { | ||||||
| 			if (fusion->ld_map[i]) | 			if (fusion->ld_map[i]) | ||||||
|  |  | ||||||
|  | @ -326,7 +326,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id) | ||||||
| 	else if (instance->supportmax256vd) | 	else if (instance->supportmax256vd) | ||||||
| 		expected_size = sizeof(struct MR_FW_RAID_MAP_EXT); | 		expected_size = sizeof(struct MR_FW_RAID_MAP_EXT); | ||||||
| 	else | 	else | ||||||
| 		expected_size = struct_size((struct MR_FW_RAID_MAP *)0, | 		expected_size = struct_size_t(struct MR_FW_RAID_MAP, | ||||||
| 					      ldSpanMap, | 					      ldSpanMap, | ||||||
| 					      le16_to_cpu(pDrvRaidMap->ldCount)); | 					      le16_to_cpu(pDrvRaidMap->ldCount)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5015,7 +5015,7 @@ static int pqi_create_queues(struct pqi_ctrl_info *ctrl_info) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define PQI_REPORT_EVENT_CONFIG_BUFFER_LENGTH	\ | #define PQI_REPORT_EVENT_CONFIG_BUFFER_LENGTH	\ | ||||||
| 	struct_size((struct pqi_event_config *)0, descriptors, PQI_MAX_EVENT_DESCRIPTORS) | 	struct_size_t(struct pqi_event_config,  descriptors, PQI_MAX_EVENT_DESCRIPTORS) | ||||||
| 
 | 
 | ||||||
| static int pqi_configure_events(struct pqi_ctrl_info *ctrl_info, | static int pqi_configure_events(struct pqi_ctrl_info *ctrl_info, | ||||||
| 	bool enable_events) | 	bool enable_events) | ||||||
|  |  | ||||||
|  | @ -301,7 +301,7 @@ struct xfs_btree_cur | ||||||
| static inline size_t | static inline size_t | ||||||
| xfs_btree_cur_sizeof(unsigned int nlevels) | xfs_btree_cur_sizeof(unsigned int nlevels) | ||||||
| { | { | ||||||
| 	return struct_size((struct xfs_btree_cur *)NULL, bc_levels, nlevels); | 	return struct_size_t(struct xfs_btree_cur, bc_levels, nlevels); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* cursor flags */ | /* cursor flags */ | ||||||
|  |  | ||||||
|  | @ -60,7 +60,7 @@ struct xchk_btree { | ||||||
| static inline size_t | static inline size_t | ||||||
| xchk_btree_sizeof(unsigned int nlevels) | xchk_btree_sizeof(unsigned int nlevels) | ||||||
| { | { | ||||||
| 	return struct_size((struct xchk_btree *)NULL, lastkey, nlevels - 1); | 	return struct_size_t(struct xchk_btree, lastkey, nlevels - 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int xchk_btree(struct xfs_scrub *sc, struct xfs_btree_cur *cur, | int xchk_btree(struct xfs_scrub *sc, struct xfs_btree_cur *cur, | ||||||
|  |  | ||||||
|  | @ -283,7 +283,7 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) | ||||||
|  * @member: Name of the array member. |  * @member: Name of the array member. | ||||||
|  * @count: Number of elements in the array. |  * @count: Number of elements in the array. | ||||||
|  * |  * | ||||||
|  * Calculates size of memory needed for structure @p followed by an |  * Calculates size of memory needed for structure of @p followed by an | ||||||
|  * array of @count number of @member elements. |  * array of @count number of @member elements. | ||||||
|  * |  * | ||||||
|  * Return: number of bytes needed or SIZE_MAX on overflow. |  * Return: number of bytes needed or SIZE_MAX on overflow. | ||||||
|  | @ -293,4 +293,20 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) | ||||||
| 		sizeof(*(p)) + flex_array_size(p, member, count),	\ | 		sizeof(*(p)) + flex_array_size(p, member, count),	\ | ||||||
| 		size_add(sizeof(*(p)), flex_array_size(p, member, count))) | 		size_add(sizeof(*(p)), flex_array_size(p, member, count))) | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct_size_t() - Calculate size of structure with trailing flexible array | ||||||
|  |  * @type: structure type name. | ||||||
|  |  * @member: Name of the array member. | ||||||
|  |  * @count: Number of elements in the array. | ||||||
|  |  * | ||||||
|  |  * Calculates size of memory needed for structure @type followed by an | ||||||
|  |  * array of @count number of @member elements. Prefer using struct_size() | ||||||
|  |  * when possible instead, to keep calculations associated with a specific | ||||||
|  |  * instance variable of type @type. | ||||||
|  |  * | ||||||
|  |  * Return: number of bytes needed or SIZE_MAX on overflow. | ||||||
|  |  */ | ||||||
|  | #define struct_size_t(type, member, count)					\ | ||||||
|  | 	struct_size((type *)NULL, member, count) | ||||||
|  | 
 | ||||||
| #endif /* __LINUX_OVERFLOW_H */ | #endif /* __LINUX_OVERFLOW_H */ | ||||||
|  |  | ||||||
|  | @ -649,7 +649,7 @@ struct __test_flex_array { | ||||||
| static void overflow_size_helpers_test(struct kunit *test) | static void overflow_size_helpers_test(struct kunit *test) | ||||||
| { | { | ||||||
| 	/* Make sure struct_size() can be used in a constant expression. */ | 	/* Make sure struct_size() can be used in a constant expression. */ | ||||||
| 	u8 ce_array[struct_size((struct __test_flex_array *)0, data, 55)]; | 	u8 ce_array[struct_size_t(struct __test_flex_array, data, 55)]; | ||||||
| 	struct __test_flex_array *obj; | 	struct __test_flex_array *obj; | ||||||
| 	int count = 0; | 	int count = 0; | ||||||
| 	int var; | 	int var; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Kees Cook
						Kees Cook