vblk: Fix top25 static analysis violations.

Jira SSV-12834

Change-Id: I9b58305b033cc5dabe9b07ebcf34633b738ae057
Signed-off-by: Sanjith T D <std@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3317746
Reviewed-by: Vipin Kumar <vipink@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Sreenivas Velpula <svelpula@nvidia.com>
This commit is contained in:
Sanjith T D
2025-03-11 18:01:27 +00:00
committed by Jon Hunter
parent f61c2ced6d
commit 010cb686b0
2 changed files with 105 additions and 14 deletions

View File

@@ -41,6 +41,8 @@ int vblk_prep_sg_io(struct vblk_dev *vblkdev,
void *ioctl_buf = NULL;
uint32_t max_sb_len;
uint8_t *cdb;
uint32_t alignment_add;
uint32_t temp_sum;
hp = kmalloc(header_len, GFP_KERNEL);
if (hp == NULL) {
@@ -77,13 +79,37 @@ int vblk_prep_sg_io(struct vblk_dev *vblkdev,
goto free_hp;
}
/* Check for subtraction overflow */
if (check_sub_overflow(vblkdev->config.blk_config.hardblk_size, 1U, &alignment_add)) {
/* True means overflow would occur */
err = -EINVAL;
goto free_hp;
}
/* Check for overflow in alignment calculation */
if (check_add_overflow(data_buf_offset, alignment_add, &temp_sum)) {
/* True means overflow would occur */
err = -EMSGSIZE;
goto free_hp;
}
/* Safe to perform alignment as no overflow detected */
data_buf_offset_aligned = ALIGN(data_buf_offset,
vblkdev->config.blk_config.hardblk_size);
/* Verify alignment result */
if (data_buf_offset_aligned < data_buf_offset) {
err = -EMSGSIZE;
goto free_hp;
}
/* Check for overflow in alignment calculation */
if (check_add_overflow(hp->dxfer_len, alignment_add, &temp_sum)) {
/* True means overflow would occur */
err = -EMSGSIZE;
goto free_hp;
}
data_buf_size_aligned = ALIGN(hp->dxfer_len,
vblkdev->config.blk_config.hardblk_size);
if (data_buf_size_aligned < hp->dxfer_len) {
@@ -207,6 +233,13 @@ int vblk_complete_sg_io(struct vblk_dev *vblkdev,
goto exit;
}
/* Validate ioctl buffer */
if (!ioctl_req->ioctl_buf ||
ioctl_req->ioctl_len < sizeof(struct vblk_sg_io_hdr)) {
err = -EINVAL;
goto exit;
}
hp = kmalloc(header_len, GFP_KERNEL);
if (hp == NULL) {
return -ENOMEM;

View File

@@ -101,6 +101,8 @@ static struct vsc_request *vblk_get_req(struct vblk_dev *vblkdev)
{
struct vsc_request *req = NULL;
unsigned long bit;
unsigned long timeout = 30*HZ;
unsigned long new_jiffies;
if (vblkdev->queue_state != VBLK_QUEUE_ACTIVE)
goto exit;
@@ -111,7 +113,18 @@ static struct vsc_request *vblk_get_req(struct vblk_dev *vblkdev)
req->vs_req.req_id = bit;
set_bit(bit, vblkdev->pending_reqs);
vblkdev->inflight_reqs++;
mod_timer(&req->timer, jiffies + 30*HZ);
if (check_add_overflow(jiffies, timeout, &new_jiffies)) {
/*
* with 64-bit jiffies, the timer will not overflow for a very long time.
* In case it does, Calculate remaining ticks after wraparound and set the timer
* - ULONG_MAX - jiffies is the remaining ticks after wraparound
* - -1 is to count the wraparound point as one tick.
*/
unsigned long remaining = timeout - (ULONG_MAX - jiffies) - 1;
new_jiffies = remaining;
}
mod_timer(&req->timer, new_jiffies);
}
exit:
@@ -203,7 +216,7 @@ static int vblk_send_config_cmd(struct vblk_dev *vblkdev)
}
vs_req = (struct vs_request *)
tegra_hv_ivc_write_get_next_frame(vblkdev->ivck);
if (IS_ERR_OR_NULL(vs_req)) {
if ((vs_req == NULL) || (IS_ERR(vs_req))) {
dev_err(vblkdev->device, "no empty frame for write\n");
return -EIO;
}
@@ -262,11 +275,20 @@ static int vblk_get_configinfo(struct vblk_dev *vblkdev)
static void req_error_handler(struct vblk_dev *vblkdev, struct request *breq)
{
uint64_t pos;
/* Safely multiply using check_mul_overflow */
if (check_mul_overflow(blk_rq_pos(breq), (uint64_t)SECTOR_SIZE, &pos)) {
/* Handle overflow - use max possible value */
pos = U64_MAX;
dev_err(vblkdev->device, "Position calculation overflow!\n");
}
dev_err(vblkdev->device,
"Error for request pos %llx type %llx size %x\n",
(blk_rq_pos(breq) * (uint64_t)SECTOR_SIZE),
(uint64_t)req_op(breq),
blk_rq_bytes(breq));
"Error for request pos %llx type %llx size %x\n",
pos,
(uint64_t)req_op(breq),
blk_rq_bytes(breq));
blk_mq_end_request(breq, BLK_STS_IOERR);
}
@@ -873,10 +895,14 @@ static void vblk_ioctl_release(struct gendisk *disk, fmode_t mode)
#endif
{
struct vblk_dev *vblkdev = disk->private_data;
short val = 1;
spin_lock(&vblkdev->lock);
vblkdev->ioctl_users--;
/* Use check_sub_overflow to safely decrement */
if (check_sub_overflow(vblkdev->ioctl_users, val, &vblkdev->ioctl_users)) {
dev_warn(vblkdev->device, "ioctl_users counter underflow prevented\n");
}
spin_unlock(&vblkdev->lock);
}
@@ -888,10 +914,14 @@ static void vblk_release(struct gendisk *disk, fmode_t mode)
#endif
{
struct vblk_dev *vblkdev = disk->private_data;
short val = 1;
spin_lock(&vblkdev->lock);
vblkdev->users--;
/* Use check_sub_overflow to safely decrement */
if (check_sub_overflow(vblkdev->users, val, &vblkdev->users)) {
dev_warn(vblkdev->device, "users counter underflow prevented\n");
}
spin_unlock(&vblkdev->lock);
}
@@ -1160,7 +1190,7 @@ static void setup_ioctl_device(struct vblk_dev *vblkdev)
vblkdev->ioctl_gd->queue = vblkdev->ioctl_queue;
vblkdev->ioctl_gd->private_data = vblkdev;
#if defined(GENHD_FL_EXT_DEVT) /* Removed in Linux v5.17 */
vblkdev->gd->flags |= GENHD_FL_EXT_DEVT;
vblkdev->ioctl_gd->flags |= GENHD_FL_EXT_DEVT;
#endif
if (snprintf(vblkdev->ioctl_gd->disk_name, 32, "vblkdev%d.ctl",
@@ -1197,9 +1227,13 @@ static void setup_device(struct vblk_dev *vblkdev)
int err;
#endif
vblkdev->size =
vblkdev->config.blk_config.num_blks *
vblkdev->config.blk_config.hardblk_size;
/* Calculate total size safely */
if ((check_mul_overflow(vblkdev->config.blk_config.num_blks,
((uint64_t)vblkdev->config.blk_config.hardblk_size),
&vblkdev->size)) == true) {
dev_err(vblkdev->device, "Size calculation overflow!\n");
return; /* Fail device setup */
}
memset(&vblkdev->tag_set, 0, sizeof(vblkdev->tag_set));
vblkdev->tag_set.ops = &vblk_mq_ops;
@@ -1582,7 +1616,12 @@ static void setup_device(struct vblk_dev *vblkdev)
if (vblkdev->config.phys_dev == VSC_DEV_EMMC) {
vblkdev->epl_id = IP_SDMMC;
vblkdev->epl_reporter_id = HSI_SDMMC4_REPORT_ID;
vblkdev->instance_id = total_instance_id++;
/* Check for overflow before incrementing */
if ((check_add_overflow(total_instance_id, 1U, &total_instance_id)) == true) {
dev_err(vblkdev->device, "Instance ID counter overflow!\n");
return; /* Fail device setup */
}
vblkdev->instance_id = total_instance_id;
}
if (vblkdev->epl_id == IP_SDMMC) {
@@ -1605,6 +1644,7 @@ static void vblk_init_device(struct work_struct *ws)
struct sched_attr attr = {0};
char vblk_comm[VBLK_DEV_THREAD_NAME_LEN];
int ret = 0;
size_t remaining_space;
mutex_lock(&vblkdev->ivc_lock);
if (tegra_hv_ivc_can_read(vblkdev->ivck) && !vblkdev->initialized) {
@@ -1622,7 +1662,25 @@ static void vblk_init_device(struct work_struct *ws)
}
if (vblkdev->schedulable_vcpu_number != num_possible_cpus()) {
strncat(vblk_comm, ":%u", 3);
/* Safely calculate remaining buffer space */
if (check_sub_overflow((size_t)VBLK_DEV_THREAD_NAME_LEN,
strlen(vblk_comm), &remaining_space)) {
dev_err(vblkdev->device,
"String length calculation overflow\n");
mutex_unlock(&vblkdev->ivc_lock);
return;
}
/* Safely append to string using snprintf */
ret = snprintf(vblk_comm + strlen(vblk_comm),
VBLK_DEV_THREAD_NAME_LEN - strlen(vblk_comm),
":%u", vblkdev->schedulable_vcpu_number);
if (ret < 0) {
dev_err(vblkdev->device, "String append failed\n");
mutex_unlock(&vblkdev->ivc_lock);
return;
}
/* create partition specific worker thread */
vblkdev->vblk_kthread = kthread_create_on_cpu(&vblk_request_worker, vblkdev,