From: Dan Carpenter <dan.carpenter@oracle.com>
To: "Czerwacki, Eial" <eial.czerwacki@sap.com>
Cc: "linux-staging@lists.linux.dev" <linux-staging@lists.linux.dev>,
SAP vSMP Linux Maintainer <linux.vsmp@sap.com>
Subject: Re: [RFC V2] drivers/virt/vSMP: new driver
Date: Mon, 25 Apr 2022 16:22:09 +0300 [thread overview]
Message-ID: <20220425132209.GO2462@kadam> (raw)
In-Reply-To: <PAXPR02MB7310EA802697DCDE90EF187581F99@PAXPR02MB7310.eurprd02.prod.outlook.com>
On Sun, Apr 24, 2022 at 11:44:33AM +0000, Czerwacki, Eial wrote:
> +u64 vsmp_read_reg_from_cfg(u64 reg, enum reg_size_type type)
> +{
> + u64 ret_val;
> +
> + switch (type) {
> + case VSMP_CTL_REG_SIZE_8BIT:
> + ret_val = readb(cfg_addr + reg);
> + break;
> +
> + case VSMP_CTL_REG_SIZE_16BIT:
> + ret_val = readw(cfg_addr + reg);
> + break;
> +
> + case VSMP_CTL_REG_SIZE_32BIT:
> + ret_val = readl(cfg_addr + reg);
> + break;
> +
> + case VSMP_CTL_REG_SIZE_64BIT:
> + ret_val = readq(cfg_addr + reg);
> + break;
> +
> + default:
> + printk(KERN_ERR "unsupported reg size type %d.\n", type);
> + ret_val = (u64) -EINVAL;
This error code gets truncated to a u16 or whatever so it doesn't work.
It's dead code anyway, right? Just return zero.
> + }
> +
> + dev_dbg(&vsmp_dev_obj->dev, "%s: read 0x%llx from reg 0x%llx of %d bits\n",
> + __func__, ret_val, reg, (type + 1) * 8);
> + return ret_val;
> +}
> +EXPORT_SYMBOL_GPL(vsmp_read_reg_from_cfg);
[ snip ]
> +
> +/*
> + * deregister the vSMP sysfs object for user space interaction
> + */
> +void vsmp_deregister_sysfs_group(const struct bin_attribute *bin_attr)
> +{
> + if (vsmp_sysfs_kobj && bin_attr)
> + sysfs_remove_bin_file(vsmp_sysfs_kobj, bin_attr);
> +}
> +EXPORT_SYMBOL_GPL(vsmp_deregister_sysfs_group);
> +
> +/*
> + * generic function to read from the bar
> + */
> +ssize_t vsmp_generic_buff_read(struct fw_ops *op, u8 bar, u64 reg,
> + char *buf, loff_t off, ssize_t count)
> +{
> + ssize_t ret_val = 0;
> +
> + if (op->buff_offset >= op->hwi_block_size) { // perform H/W op
> + vsmp_reset_op(op);
> +
> + ret_val = vsmp_read_buff_from_bar(bar, reg, op->buff, op->hwi_block_size, false);
> + if (ret_val) {
> + printk(KERN_ERR "%s operation failed\n",
> + (op->action == FW_READ) ? "read" : "write");
This read vs write is weird. We're in a read function. Also it's
always read.
> + }
> + op->buff_offset = 0;
> + }
> +
> + if (ret_val)
> + return ret_val;
> +
> + return memory_read_from_buffer(buf, count, &op->buff_offset, op->buff, op->hwi_block_size);;
> +}
> +EXPORT_SYMBOL_GPL(vsmp_generic_buff_read);
[ snip ]
> +
> +/*
> + * init the common module
> + */
> +static int __init vsmp_common_info_init(void)
> +{
> + int ret_val = -0, i;
^^
Negative zero?
> +
> + for (i = 0; (i < ARRAY_SIZE(cbs_arr) && !ret_val); i++) {
> + ret_val = cbs_arr[i].reg_cb();
> + if (ret_val) {
> + printk(KERN_ERR "failed to init sysfs entry %d (%d), exiting.\n",
> + i, ret_val);
> + }
> + }
> +
> + return ret_val;
> +}
[ snip ]
> +
> +/*
> + * this is the maximal possible length of the version which is a text string
> + * the real len is usually much smaller, thus the driver uses this once to read
> + * the version string and record it's actual len.
> + * from that point and on, the actual len will be used in each call.
> + */
> +#define VERSION_MAX_LEN (1 << 19)
> +
> +static struct fw_ops op;
Greg already complained about globals, but this one is particularly bad
because there is no locking so it will lead to corruption.
> +
> +static ssize_t version_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr,
> + char *buf, loff_t off, size_t count)
> +{
> + s64 reg_val = vsmp_read_reg32_from_cfg(VSMP_VERSION_REG);
> + ssize_t ret_val;
> +
> + if (reg_val < 0) {
> + printk(KERN_ERR "failed to value of reg 0x%x\n", VSMP_VERSION_REG);
> + return 0;
> + }
> +
> + ret_val = vsmp_generic_buff_read(&op, 0, reg_val, buf, off, count);
> + if (ret_val < 0) {
> + printk(KERN_ERR "failed to read version (%ld)\n", ret_val);
> + return 0;
> + }
> +
> + buf[ret_val++] = '\n';
You need to consider "count" before you print the newline. #corruption.
> +
> + return ret_val;
> +}
> +
> +struct bin_attribute version_raw_attr = __BIN_ATTR(version, FILE_PREM, version_read, NULL, VERSION_MAX_LEN);
> +
> +/*
> + * retreive str in order to determine the proper length.
> + * this is the best way to maintain backwards compatibility with all
> + * vSMP versions.
> + */
> +static ssize_t get_version_len(void)
> +{
> + ssize_t ret_val = 0;
This assignment is never used. It just disables static analysis for
uninitialized variables and invites bugs.
> + u64 reg_val;
> + char *version_str = kzalloc(VERSION_MAX_LEN, GFP_ATOMIC | __GFP_NOWARN);
> +
> + if (!version_str) {
> + printk(KERN_ERR "failed to allocate buffer\n");
> + return -ENOMEM;
> + }
> +
> + reg_val = vsmp_read_reg32_from_cfg(VSMP_VERSION_REG);
> + if (reg_val < 0) {
> + printk(KERN_ERR "failed to value of reg 0x%x\n", VSMP_VERSION_REG);
> + return 0;
> + }
> +
> + memset(version_str, 0, VERSION_MAX_LEN);
> + ret_val = vsmp_read_buff_from_bar(0, reg_val, version_str, VERSION_MAX_LEN, true);
> + if (ret_val) {
> + kfree(version_str);
> + printk(KERN_ERR "failed to read buffer from bar\n");
> + return ret_val;
> + }
> + kfree(version_str);
^^^^^^^^^^^^^^^^^^
> +
> + return strlen(version_str);
^^^^^^^^^^^^^^^^^^^
Use after free. Try running Smatch against your code to detect these
bugs.
https://staticthinking.wordpress.com/2022/04/25/how-to-run-smatch-on-your-code/
> +}
> +
> +/*
> + * register the version sysfs entry
> + */
> +int sysfs_register_version_cb(void)
> +{
> + ssize_t len = get_version_len();
> + int ret_val;
> +
> + if (len < 1) {
> + printk(KERN_ERR "failed to init vSMP version module\n");
> + return len;
What if len is zero? (Please return a proper error code).
> + }
> + version_raw_attr.size = len;
> +
> + if (vsmp_init_op(&op, version_raw_attr.size, FW_READ)) {
> + printk(KERN_ERR "failed to init vSMP version op\n");
> + return -ENODEV;
> + }
> +
> + ret_val = vsmp_register_sysfs_group(&version_raw_attr);
> + if (ret_val) {
> + printk(KERN_ERR "failed to init vSMP version support\n");
> + vsmp_release_op(&op);
> + }
> +
> + return ret_val;
> +}
> +
[ snip ]
> +
> +/* module functions */
> +static ssize_t active_log_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr,
> + char *buf, loff_t off, size_t count)
> +{
> + ssize_t ret_val = 0;
> +
> + if (!op.in_progress) {
> + ret_val = mutex_lock_interruptible(&active_log_mutex);
> + if (ret_val) {
> + printk(KERN_ERR
> + "error in atemmpt to lock mutex (%lx)\n",
> + ret_val);
> + return 0;
> + }
> +
> + vsmp_write_reg16_to_cfg(VSMP_LOGS_CTRL_REG,
> + vsmp_read_reg16_from_cfg
> + (VSMP_LOGS_CTRL_REG) | LOGS_MASK);
> + op.in_progress = true;
> + vsmp_write_reg64_to_cfg(VSMP_LOGS_STATUS_REG, 0);
> + }
> +
> + if (vsmp_op_buffer_depleted(&op)) {
> + if (!(vsmp_read_reg16_from_cfg(VSMP_LOGS_CTRL_REG) & LOGS_MASK)) {
> + vsmp_reset_op(&op);
> + op.in_progress = 0;
> + mutex_unlock(&active_log_mutex);
> + return ret_val;
> + }
> + }
> +
> + ret_val = vsmp_generic_buff_read(&op, 1, active_log_start, buf, off, count);
> + if (ret_val < 0) {
> + printk(KERN_ERR "error reading from buffer\n");
> + mutex_unlock(&active_log_mutex);
> + return 0;
return ret_val;
> + }
> +
> + if (vsmp_op_buffer_depleted(&op)) {
> + vsmp_write_reg64_to_cfg(VSMP_LOGS_STATUS_REG,
> + ~0LL & ~(1LL << 0));
> + }
> +
> + return count;
This isn't correct necessarily. It should be something like
return min(count, ret_val);
> +}
regards,
dan carpenter
next prev parent reply other threads:[~2022-04-25 13:22 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-24 11:44 [RFC V2] drivers/virt/vSMP: new driver Czerwacki, Eial
2022-04-24 13:40 ` Greg KH
2022-04-24 14:16 ` Czerwacki, Eial
2022-04-26 11:58 ` Czerwacki, Eial
2022-04-26 12:09 ` Greg KH
2022-04-26 12:25 ` Czerwacki, Eial
2022-04-25 13:22 ` Dan Carpenter [this message]
2022-04-25 13:56 ` Czerwacki, Eial
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220425132209.GO2462@kadam \
--to=dan.carpenter@oracle.com \
--cc=eial.czerwacki@sap.com \
--cc=linux-staging@lists.linux.dev \
--cc=linux.vsmp@sap.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox