IB/mlx5: fix uaccess beyond "count" in debugfs read/write handlers
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 the read handlers check that *pos is zero (meaning that at least sys_splice() can't trigger kernel memory corruption). Because of the root requirement, this is not a security fix, but rather a cleanup. For the read handlers, fix it by using simple_read_from_buffer() instead of custom logic. Add min() calls to the write handlers. Fixes:4a2da0b8c0
("IB/mlx5: Add debug control parameters for congestion control") Fixes:e126ba97db
("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: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
222c7b1fd4
commit
60e6627f12
@ -359,9 +359,6 @@ static ssize_t get_param(struct file *filp, char __user *buf, size_t count,
|
||||
int ret;
|
||||
char lbuf[11];
|
||||
|
||||
if (*pos)
|
||||
return 0;
|
||||
|
||||
ret = mlx5_ib_get_cc_params(param->dev, param->port_num, offset, &var);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -370,11 +367,7 @@ static ssize_t get_param(struct file *filp, char __user *buf, size_t count,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (copy_to_user(buf, lbuf, ret))
|
||||
return -EFAULT;
|
||||
|
||||
*pos += ret;
|
||||
return ret;
|
||||
return simple_read_from_buffer(buf, count, pos, lbuf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations dbg_cc_fops = {
|
||||
|
@ -271,16 +271,16 @@ static ssize_t size_write(struct file *filp, const char __user *buf,
|
||||
{
|
||||
struct mlx5_cache_ent *ent = filp->private_data;
|
||||
struct mlx5_ib_dev *dev = ent->dev;
|
||||
char lbuf[20];
|
||||
char lbuf[20] = {0};
|
||||
u32 var;
|
||||
int err;
|
||||
int c;
|
||||
|
||||
if (copy_from_user(lbuf, buf, sizeof(lbuf)))
|
||||
count = min(count, sizeof(lbuf) - 1);
|
||||
if (copy_from_user(lbuf, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
c = order2idx(dev, ent->order);
|
||||
lbuf[sizeof(lbuf) - 1] = 0;
|
||||
|
||||
if (sscanf(lbuf, "%u", &var) != 1)
|
||||
return -EINVAL;
|
||||
@ -310,19 +310,11 @@ static ssize_t size_read(struct file *filp, char __user *buf, size_t count,
|
||||
char lbuf[20];
|
||||
int err;
|
||||
|
||||
if (*pos)
|
||||
return 0;
|
||||
|
||||
err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (copy_to_user(buf, lbuf, err))
|
||||
return -EFAULT;
|
||||
|
||||
*pos += err;
|
||||
|
||||
return err;
|
||||
return simple_read_from_buffer(buf, count, pos, lbuf, err);
|
||||
}
|
||||
|
||||
static const struct file_operations size_fops = {
|
||||
@ -337,16 +329,16 @@ static ssize_t limit_write(struct file *filp, const char __user *buf,
|
||||
{
|
||||
struct mlx5_cache_ent *ent = filp->private_data;
|
||||
struct mlx5_ib_dev *dev = ent->dev;
|
||||
char lbuf[20];
|
||||
char lbuf[20] = {0};
|
||||
u32 var;
|
||||
int err;
|
||||
int c;
|
||||
|
||||
if (copy_from_user(lbuf, buf, sizeof(lbuf)))
|
||||
count = min(count, sizeof(lbuf) - 1);
|
||||
if (copy_from_user(lbuf, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
c = order2idx(dev, ent->order);
|
||||
lbuf[sizeof(lbuf) - 1] = 0;
|
||||
|
||||
if (sscanf(lbuf, "%u", &var) != 1)
|
||||
return -EINVAL;
|
||||
@ -372,19 +364,11 @@ static ssize_t limit_read(struct file *filp, char __user *buf, size_t count,
|
||||
char lbuf[20];
|
||||
int err;
|
||||
|
||||
if (*pos)
|
||||
return 0;
|
||||
|
||||
err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->limit);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (copy_to_user(buf, lbuf, err))
|
||||
return -EFAULT;
|
||||
|
||||
*pos += err;
|
||||
|
||||
return err;
|
||||
return simple_read_from_buffer(buf, count, pos, lbuf, err);
|
||||
}
|
||||
|
||||
static const struct file_operations limit_fops = {
|
||||
|
Loading…
Reference in New Issue
Block a user