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
