Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Kirjanov <dkirjanov@suse.com>2019-03-20 15:31:58 +0100
committerDenis Kirjanov <dkirjanov@suse.com>2019-03-21 09:59:18 +0100
commit2a80c1f4a49e62636ea47575a067289739001aa1 (patch)
tree8540cd1093c3044c02010006bfdd0f7071a0a573
parentf02276aa24db0bf171c5accdae7e463b60b1ef6d (diff)
net/mlx5: fix uaccess beyond "count" in debugfs read/write handlers (git-fixes).
-rw-r--r--patches.fixes/0001-net-mlx5-fix-uaccess-beyond-count-in-debugfs-read-wr.patch143
-rw-r--r--series.conf1
2 files changed, 144 insertions, 0 deletions
diff --git a/patches.fixes/0001-net-mlx5-fix-uaccess-beyond-count-in-debugfs-read-wr.patch b/patches.fixes/0001-net-mlx5-fix-uaccess-beyond-count-in-debugfs-read-wr.patch
new file mode 100644
index 0000000000..78cf74756d
--- /dev/null
+++ b/patches.fixes/0001-net-mlx5-fix-uaccess-beyond-count-in-debugfs-read-wr.patch
@@ -0,0 +1,143 @@
+From: Jann Horn <jannh@google.com>
+Subject: net/mlx5: fix uaccess beyond "count" in debugfs read/write handlers
+Patch-mainline: v4.19-rc1
+Git-commit: 31e33a5b41bb158f27c30e13b12d6e5e6513ea05
+References: git-fixes
+
+In general, accessing userspace memory beyond the length of the supplied
+buffer in VFS read/write handlers can lead to both kernel memory corruption
+(via kernel_read()/kernel_write(), which can e.g. be triggered via
+sys_splice()) and privilege escalation inside userspace.
+
+In this case, the affected files are in debugfs (and should therefore only
+be accessible to root) and check that *pos is zero (which prevents the
+sys_splice() trick). Therefore, this is not a security fix, but rather a
+small cleanup.
+
+For the read handlers, fix it by using simple_read_from_buffer() instead of
+custom logic.
+For the write handler, add a check.
+
+changed in v2:
+ - also fix dbg_write()
+
+Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters")
+Signed-off-by: Jann Horn <jannh@google.com>
+Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
+Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
+Acked-by: Denis Kirjanov <dkirjanov@suse.com>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 28 +++++-----------------
+ drivers/net/ethernet/mellanox/mlx5/core/debugfs.c | 21 +---------------
+ 2 files changed, 9 insertions(+), 40 deletions(-)
+
+--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+@@ -1020,7 +1020,10 @@ static ssize_t dbg_write(struct file *fi
+ if (!dbg->in_msg || !dbg->out_msg)
+ return -ENOMEM;
+
+- if (copy_from_user(lbuf, buf, sizeof(lbuf)))
++ if (count < sizeof(lbuf) - 1)
++ return -EINVAL;
++
++ if (copy_from_user(lbuf, buf, sizeof(lbuf) - 1))
+ return -EFAULT;
+
+ lbuf[sizeof(lbuf) - 1] = 0;
+@@ -1224,21 +1227,12 @@ static ssize_t data_read(struct file *fi
+ {
+ struct mlx5_core_dev *dev = filp->private_data;
+ struct mlx5_cmd_debug *dbg = &dev->cmd.dbg;
+- int copy;
+-
+- if (*pos)
+- return 0;
+
+ if (!dbg->out_msg)
+ return -ENOMEM;
+
+- copy = min_t(int, count, dbg->outlen);
+- if (copy_to_user(buf, dbg->out_msg, copy))
+- return -EFAULT;
+-
+- *pos += copy;
+-
+- return copy;
++ return simple_read_from_buffer(buf, count, pos, dbg->out_msg,
++ dbg->outlen);
+ }
+
+ static const struct file_operations dfops = {
+@@ -1256,19 +1250,11 @@ static ssize_t outlen_read(struct file *
+ char outlen[8];
+ int err;
+
+- if (*pos)
+- return 0;
+-
+ err = snprintf(outlen, sizeof(outlen), "%d", dbg->outlen);
+ if (err < 0)
+ return err;
+
+- if (copy_to_user(buf, &outlen, err))
+- return -EFAULT;
+-
+- *pos += err;
+-
+- return err;
++ return simple_read_from_buffer(buf, count, pos, outlen, err);
+ }
+
+ static ssize_t outlen_write(struct file *filp, const char __user *buf,
+--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
+@@ -150,22 +150,14 @@ static ssize_t average_read(struct file
+ int ret;
+ char tbuf[22];
+
+- if (*pos)
+- return 0;
+-
+ stats = filp->private_data;
+ spin_lock_irq(&stats->lock);
+ if (stats->n)
+ field = div64_u64(stats->sum, stats->n);
+ spin_unlock_irq(&stats->lock);
+ ret = snprintf(tbuf, sizeof(tbuf), "%llu\n", field);
+- if (ret > 0) {
+- if (copy_to_user(buf, tbuf, ret))
+- return -EFAULT;
+- }
+
+- *pos += ret;
+- return ret;
++ return simple_read_from_buffer(buf, count, pos, tbuf, ret);
+ }
+
+ static ssize_t average_write(struct file *filp, const char __user *buf,
+@@ -442,9 +434,6 @@ static ssize_t dbg_read(struct file *fil
+ u64 field;
+ int ret;
+
+- if (*pos)
+- return 0;
+-
+ desc = filp->private_data;
+ d = (void *)(desc - desc->i) - sizeof(*d);
+ switch (d->type) {
+@@ -470,13 +459,7 @@ static ssize_t dbg_read(struct file *fil
+ else
+ ret = snprintf(tbuf, sizeof(tbuf), "0x%llx\n", field);
+
+- if (ret > 0) {
+- if (copy_to_user(buf, tbuf, ret))
+- return -EFAULT;
+- }
+-
+- *pos += ret;
+- return ret;
++ return simple_read_from_buffer(buf, count, pos, tbuf, ret);
+ }
+
+ static const struct file_operations fops = {
diff --git a/series.conf b/series.conf
index 9d89764d8c..d336e75833 100644
--- a/series.conf
+++ b/series.conf
@@ -18086,6 +18086,7 @@
patches.drivers/net-hns3-Standardize-the-handle-of-return-value.patch
patches.fixes/xen-netfront-fix-queue-name-setting.patch
patches.fixes/wan-fsl_ucc_hdlc-use-IS_ERR_VALUE-to-check-return-va.patch
+ patches.fixes/0001-net-mlx5-fix-uaccess-beyond-count-in-debugfs-read-wr.patch
patches.drivers/brcmsmac-fix-wrap-around-in-conversion-from-constant
patches.drivers/rndis_wlan-potential-buffer-overflow-in-rndis_wlan_a
patches.drivers/libertas-fix-suspend-and-resume-for-SDIO-connected-c