Implement ->proc_write_buf() so procfs copies in what is written before it pins the entry, and set the label from that copy. Writes larger than PAGE_SIZE - 1 bytes fail with -EINVAL from procfs now. A write that large only ever worked when most of it was trailing newlines or came after a NUL, ntfs_set_label() refused a label that long with -ENAMETOOLONG or -EFBIG.
Signed-off-by: Christian Brauner (Amutable) <[email protected]> --- fs/ntfs3/super.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c index 3d669e957ea4..fca73d2766c0 100644 --- a/fs/ntfs3/super.c +++ b/fs/ntfs3/super.c @@ -536,37 +536,28 @@ static int ntfs3_label_show(struct seq_file *m, void *o) } /* write /proc/fs/ntfs3/<dev>/label */ -static ssize_t ntfs3_label_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) +static ssize_t ntfs3_label_write(struct file *file, char *buf, size_t count, + loff_t *ppos) { int err; struct super_block *sb = pde_data(file_inode(file)); - ssize_t ret = count; - u8 *label; + size_t len = count; if (sb_rdonly(sb)) return -EROFS; - label = memdup_user(buffer, count); - if (IS_ERR(label)) - return PTR_ERR(label); + while (len > 0 && buf[len - 1] == '\n') + len -= 1; - while (ret > 0 && label[ret - 1] == '\n') - ret -= 1; - - err = ntfs_set_label(sb->s_fs_info, label, ret); + err = ntfs_set_label(sb->s_fs_info, (u8 *)buf, len); if (err < 0) { ntfs_err(sb, "failed (%d) to write label", err); - ret = err; - goto out; + return err; } *ppos += count; - ret = count; -out: - kfree(label); - return ret; + return count; } static const struct proc_ops ntfs3_volinfo_fops = { @@ -575,7 +566,7 @@ static const struct proc_ops ntfs3_volinfo_fops = { static const struct proc_ops ntfs3_label_fops = { .proc_show = ntfs3_label_show, - .proc_write = ntfs3_label_write, + .proc_write_buf = ntfs3_label_write, }; static void ntfs_create_procdir(struct super_block *sb) -- 2.53.0
