[bug report] fsi: Add cfam char devices

Benjamin Herrenschmidt benh at kernel.crashing.org
Thu Oct 12 15:22:42 AEDT 2023


On Tue, 2023-10-10 at 16:35 +0300, Dan Carpenter wrote:
> Hello Benjamin Herrenschmidt,
> 
> The patch d1dcd6782576: "fsi: Add cfam char devices" from Jun 21,
> 2018, leads to the following Smatch static checker warning:
> 
>         drivers/fsi/fsi-core.c:717 cfam_write()
>         error: check that 'write_len' is capped
> 
> drivers/fsi/fsi-core.c
>     696 static ssize_t cfam_write(struct file *filep, const char __user *buf,
>     697                           size_t count, loff_t *offset)
>     698 {
>     699         struct fsi_slave *slave = filep->private_data;
>     700         size_t total_len, write_len;
>     701         loff_t off = *offset;
>     702         ssize_t rc;
>     703 
>     704 
>     705         if (off < 0)
>     706                 return -EINVAL;
>     707 
>     708         if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
>     709                 return -EINVAL;
>     710 
>     711         for (total_len = 0; total_len < count; total_len += write_len) {
>     712                 __be32 data;
>     713 
>     714                 write_len = min_t(size_t, count, 4);
>     715                 write_len -= off & 0x3;
> 
> This offset calculation is strange.  Assume we are writing 2 bytes to
> offset 3.  That means that write_len is set to 2 - 3 which is -1.

Right, that's kind of bogus. From my vague memories (I've long moved on
and don't work for IBM anymore), the goal here was to have a limit of
writing 2 bytes if the offset is 2 bytes into the word, and 1 byte of
it's 3 byte into the word (etc...).

But the test didn't take into account an attempt to write an unaligned
quantity that is smaller than the word. Ouch.

It should probably be

           write_len = min_t(size_t, count, 4 - (off & 3));

Don't you think ?

I'll let Eddie (or others) handle this ...

Cheers,
Ben.


>     716 
> --> 717                 rc = copy_from_user(&data, buf + total_len, write_len);
> 
> In olden days that would have been a really easy to exploit buffer
> overflow but now copy_from_user() will just trigger a WARN_ON() for
> negatives.
> 
>     718                 if (rc) {
>     719                         rc = -EFAULT;
>     720                         goto fail;
>     721                 }
>     722                 rc = fsi_slave_write(slave, off, &data, write_len);
>     723                 if (rc)
>     724                         goto fail;
>     725                 off += write_len;
>     726         }
>     727         rc = count;
>     728  fail:
>     729         *offset = off;
>     730         return rc;
>     731 }
> 
> regards,
> dan carpenter



More information about the linux-fsi mailing list