Implement ->proc_write_buf() for allow_dio and def_reserved_size so
procfs copies in what is written before it pins the entry, and parse
the number from that copy.

kstrtoul_from_user() looked at the first 66 bytes of whatever was
written. Now the whole write is parsed, and anything larger than
PAGE_SIZE - 1 bytes fails with -EINVAL from procfs before the
capability check.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 drivers/scsi/sg.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index c7386fbe5580..87569e302f26 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2287,18 +2287,18 @@ sg_get_dev(int dev)
 #ifdef CONFIG_SCSI_PROC_FS
 static int sg_proc_seq_show_int(struct seq_file *s, void *v);
 
-static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer,
+static ssize_t sg_proc_write_adio(struct file *filp, char *buffer,
                                  size_t count, loff_t *off);
 static const struct proc_ops adio_proc_ops = {
        .proc_show      = sg_proc_seq_show_int,
-       .proc_write     = sg_proc_write_adio,
+       .proc_write_buf = sg_proc_write_adio,
 };
 
 static ssize_t sg_proc_write_dressz(struct file *filp, 
-               const char __user *buffer, size_t count, loff_t *off);
+               char *buffer, size_t count, loff_t *off);
 static const struct proc_ops dressz_proc_ops = {
        .proc_show      = sg_proc_seq_show_int,
-       .proc_write     = sg_proc_write_dressz,
+       .proc_write_buf = sg_proc_write_dressz,
 };
 
 static int sg_proc_seq_show_version(struct seq_file *s, void *v);
@@ -2359,7 +2359,7 @@ static int sg_proc_seq_show_int(struct seq_file *s, void 
*v)
 }
 
 static ssize_t 
-sg_proc_write_adio(struct file *filp, const char __user *buffer,
+sg_proc_write_adio(struct file *filp, char *buffer,
                   size_t count, loff_t *off)
 {
        int err;
@@ -2367,7 +2367,7 @@ sg_proc_write_adio(struct file *filp, const char __user 
*buffer,
 
        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
                return -EACCES;
-       err = kstrtoul_from_user(buffer, count, 0, &num);
+       err = kstrtoul(buffer, 0, &num);
        if (err)
                return err;
        sg_allow_dio = num ? 1 : 0;
@@ -2375,7 +2375,7 @@ sg_proc_write_adio(struct file *filp, const char __user 
*buffer,
 }
 
 static ssize_t 
-sg_proc_write_dressz(struct file *filp, const char __user *buffer,
+sg_proc_write_dressz(struct file *filp, char *buffer,
                     size_t count, loff_t *off)
 {
        int err;
@@ -2384,7 +2384,7 @@ sg_proc_write_dressz(struct file *filp, const char __user 
*buffer,
        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
                return -EACCES;
 
-       err = kstrtoul_from_user(buffer, count, 0, &k);
+       err = kstrtoul(buffer, 0, &k);
        if (err)
                return err;
        if (k <= 1048576) {     /* limit "big buff" to 1 MB */

-- 
2.53.0

Reply via email to