diff options
author | Shyam Sundar S K <Shyam-sundar.S-k@amd.com> | 2023-10-10 16:50:01 +0200 |
---|---|---|
committer | Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> | 2023-10-12 15:40:09 +0200 |
commit | d9f421da6b9287000f8253628d54cf89b0c14da5 (patch) | |
tree | b4eb58c21dff4e5dc37f82cc3500688b1670c811 /drivers/platform/x86/amd/pmc | |
parent | platform/x86: asus-wireless: Replace open coded acpi_match_acpi_device() (diff) | |
download | linux-d9f421da6b9287000f8253628d54cf89b0c14da5.tar.xz linux-d9f421da6b9287000f8253628d54cf89b0c14da5.zip |
platform/x86/amd/pmc: Use flex array when calling amd_pmc_stb_debugfs_open_v2()
Currently in amd_pmc_stb_debugfs_open_v2() the buffer size is assumed to
be fixed and a second call to amd_pmc_stb_debugfs_open_v2() may race with
a process holding open another fd. This could change "fsize" to a
bigger size causing an out of bounds read.
Instead create a struct with a flexarray to solve this.
Suggested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Link: https://lore.kernel.org/r/20231010145003.139932-1-Shyam-sundar.S-k@amd.com
[ij: renamed flex_arr -> stb_data_arr]
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Diffstat (limited to 'drivers/platform/x86/amd/pmc')
-rw-r--r-- | drivers/platform/x86/amd/pmc/pmc.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c index 922932a71233..77dca9a1f00f 100644 --- a/drivers/platform/x86/amd/pmc/pmc.c +++ b/drivers/platform/x86/amd/pmc/pmc.c @@ -52,7 +52,7 @@ #define AMD_S2D_REGISTER_ARGUMENT 0xA88 /* STB Spill to DRAM Parameters */ -#define S2D_TELEMETRY_BYTES_MAX 0x100000 +#define S2D_TELEMETRY_BYTES_MAX 0x100000U #define S2D_TELEMETRY_DRAMBYTES_MAX 0x1000000 /* STB Spill to DRAM Message Definition */ @@ -122,6 +122,11 @@ enum s2d_arg { S2D_DRAM_SIZE, }; +struct amd_pmc_stb_v2_data { + size_t size; + u8 data[] __counted_by(size); +}; + struct amd_pmc_bit_map { const char *name; u32 bit_mask; @@ -239,7 +244,8 @@ static const struct file_operations amd_pmc_stb_debugfs_fops = { static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) { struct amd_pmc_dev *dev = filp->f_inode->i_private; - u32 *buf, fsize, num_samples, val, stb_rdptr_offset = 0; + u32 fsize, num_samples, val, stb_rdptr_offset = 0; + struct amd_pmc_stb_v2_data *stb_data_arr; int ret; /* Write dummy postcode while reading the STB buffer */ @@ -247,10 +253,6 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) if (ret) dev_err(dev->dev, "error writing to STB: %d\n", ret); - buf = kzalloc(S2D_TELEMETRY_BYTES_MAX, GFP_KERNEL); - if (!buf) - return -ENOMEM; - /* Spill to DRAM num_samples uses separate SMU message port */ dev->msg_port = 1; @@ -264,10 +266,16 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) dev->msg_port = 0; if (ret) { dev_err(dev->dev, "error: S2D_NUM_SAMPLES not supported : %d\n", ret); - kfree(buf); return ret; } + fsize = min(num_samples, S2D_TELEMETRY_BYTES_MAX); + stb_data_arr = kmalloc(struct_size(stb_data_arr, data, fsize), GFP_KERNEL); + if (!stb_data_arr) + return -ENOMEM; + + stb_data_arr->size = fsize; + /* Start capturing data from the last push location */ if (num_samples > S2D_TELEMETRY_BYTES_MAX) { fsize = S2D_TELEMETRY_BYTES_MAX; @@ -277,8 +285,8 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) stb_rdptr_offset = 0; } - memcpy_fromio(buf, dev->stb_virt_addr + stb_rdptr_offset, fsize); - filp->private_data = buf; + memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr + stb_rdptr_offset, fsize); + filp->private_data = stb_data_arr; return 0; } @@ -286,11 +294,9 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) static ssize_t amd_pmc_stb_debugfs_read_v2(struct file *filp, char __user *buf, size_t size, loff_t *pos) { - if (!filp->private_data) - return -EINVAL; + struct amd_pmc_stb_v2_data *data = filp->private_data; - return simple_read_from_buffer(buf, size, pos, filp->private_data, - S2D_TELEMETRY_BYTES_MAX); + return simple_read_from_buffer(buf, size, pos, data->data, data->size); } static int amd_pmc_stb_debugfs_release_v2(struct inode *inode, struct file *filp) |