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) <brauner@kernel.org>
---
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