@@ -44,6 +44,10 @@ static const int engine_page_size = 0x400;
#define FSI_SLAVE_BASE 0x800
+/* The FSI protocol itself has a maximum 23-bit address space, all addressing
+ * must be inder this size */
+#define FSI_ADDR_SIZE 0x00800000
+
/*
* FSI slave engine control register offsets
*/
@@ -575,6 +579,19 @@ static unsigned long aligned_access_size(size_t offset, size_t count)
return BIT(__builtin_ctzl(offset_unit | count_unit));
}
+static int fsi_validate_range(loff_t off, size_t count)
+{
+ if (off < 0)
+ return -EINVAL;
+ if (off >= FSI_ADDR_SIZE)
+ return -EINVAL;
+ if (count < 0)
+ return -EINVAL;
+ if (count > FSI_ADDR_SIZE - off)
+ return -EINVAL;
+ return 0;
+}
+
static ssize_t fsi_slave_sysfs_raw_read(struct file *file,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
@@ -583,11 +600,9 @@ static ssize_t fsi_slave_sysfs_raw_read(struct file *file,
size_t total_len, read_len;
int rc;
- if (off < 0)
- return -EINVAL;
-
- if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
- return -EINVAL;
+ rc = fsi_validate_range(off, count);
+ if (rc)
+ return rc;
for (total_len = 0; total_len < count; total_len += read_len) {
read_len = aligned_access_size(off, count - total_len);
@@ -610,11 +625,9 @@ static ssize_t fsi_slave_sysfs_raw_write(struct file *file,
size_t total_len, write_len;
int rc;
- if (off < 0)
- return -EINVAL;
-
- if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
- return -EINVAL;
+ rc = fsi_validate_range(off, count);
+ if (rc)
+ return rc;
for (total_len = 0; total_len < count; total_len += write_len) {
write_len = aligned_access_size(off, count - total_len);
@@ -699,11 +712,9 @@ static ssize_t cfam_read(struct file *filep, char __user *buf, size_t count,
loff_t off = *offset;
ssize_t rc;
- if (off < 0)
- return -EINVAL;
-
- if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
- return -EINVAL;
+ rc = fsi_validate_range(off, count);
+ if (rc)
+ return rc;
for (total_len = 0; total_len < count; total_len += read_len) {
__be32 data;
@@ -734,12 +745,9 @@ static ssize_t cfam_write(struct file *filep, const char __user *buf,
loff_t off = *offset;
ssize_t rc;
-
- if (off < 0)
- return -EINVAL;
-
- if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
- return -EINVAL;
+ rc = fsi_validate_range(off, count);
+ if (rc)
+ return rc;
for (total_len = 0; total_len < count; total_len += write_len) {
__be32 data;
Currently, we have some non-obvious checks on the offset and count values for cfam_read, cfam_write, sysfs_raw_read and sysfs_raw_write. This change simplifies these checks into their individual components, and moves them all into a common fsi_validate_range() function, shared between all userspace access functions. Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au> Fixes: d1dcd6782576 ("fsi: Add cfam char devices") Reported-by: Luo Likang <luolikang@nsfocus.com> --- drivers/fsi/fsi-core.c | 50 ++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 21 deletions(-)