Takashi Iwai 678063
From 2e41f274f9aa71cdcc69dc1f26a3f9304a651804 Mon Sep 17 00:00:00 2001
Takashi Iwai 678063
From: Akinobu Mita <akinobu.mita@gmail.com>
Takashi Iwai 678063
Date: Tue, 20 Sep 2022 02:24:16 +0900
Takashi Iwai 678063
Subject: [PATCH] libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value
Takashi Iwai 678063
Git-commit: 2e41f274f9aa71cdcc69dc1f26a3f9304a651804
Takashi Iwai 678063
Patch-mainline: v6.2-rc1
Takashi Iwai 678063
References: git-fixes
Takashi Iwai 678063
Takashi Iwai 678063
Patch series "fix error when writing negative value to simple attribute
Takashi Iwai 678063
files".
Takashi Iwai 678063
Takashi Iwai 678063
The simple attribute files do not accept a negative value since the commit
Takashi Iwai 678063
488dac0c9237 ("libfs: fix error cast of negative value in
Takashi Iwai 678063
simple_attr_write()"), but some attribute files want to accept a negative
Takashi Iwai 678063
value.
Takashi Iwai 678063
Takashi Iwai 678063
Takashi Iwai 678063
This patch (of 3):
Takashi Iwai 678063
Takashi Iwai 678063
The simple attribute files do not accept a negative value since the commit
Takashi Iwai 678063
488dac0c9237 ("libfs: fix error cast of negative value in
Takashi Iwai 678063
simple_attr_write()"), so we have to use a 64-bit value to write a
Takashi Iwai 678063
negative value.
Takashi Iwai 678063
Takashi Iwai 678063
This adds DEFINE_SIMPLE_ATTRIBUTE_SIGNED for a signed value.
Takashi Iwai 678063
Takashi Iwai 678063
Link: https://lkml.kernel.org/r/20220919172418.45257-1-akinobu.mita@gmail.com
Takashi Iwai 678063
Link: https://lkml.kernel.org/r/20220919172418.45257-2-akinobu.mita@gmail.com
Takashi Iwai 678063
Fixes: 488dac0c9237 ("libfs: fix error cast of negative value in simple_attr_write()")
Takashi Iwai 678063
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Takashi Iwai 678063
Reported-by: Zhao Gongyi <zhaogongyi@huawei.com>
Takashi Iwai 678063
Reviewed-by: David Hildenbrand <david@redhat.com>
Takashi Iwai 678063
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Takashi Iwai 678063
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Takashi Iwai 678063
Cc: Jonathan Corbet <corbet@lwn.net>
Takashi Iwai 678063
Cc: Oscar Salvador <osalvador@suse.de>
Takashi Iwai 678063
Cc: Rafael J. Wysocki <rafael@kernel.org>
Takashi Iwai 678063
Cc: Shuah Khan <shuah@kernel.org>
Takashi Iwai 678063
Cc: Wei Yongjun <weiyongjun1@huawei.com>
Takashi Iwai 678063
Cc: Yicong Yang <yangyicong@hisilicon.com>
Takashi Iwai 678063
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Takashi Iwai 678063
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 678063
Takashi Iwai 678063
---
Takashi Iwai 678063
 fs/libfs.c         |   22 +++++++++++++++++++---
Takashi Iwai 678063
 include/linux/fs.h |   12 ++++++++++--
Takashi Iwai 678063
 2 files changed, 29 insertions(+), 5 deletions(-)
Takashi Iwai 678063
Takashi Iwai 678063
--- a/fs/libfs.c
Takashi Iwai 678063
+++ b/fs/libfs.c
Takashi Iwai 678063
@@ -967,8 +967,8 @@ out:
Takashi Iwai 678063
 EXPORT_SYMBOL_GPL(simple_attr_read);
Takashi Iwai 678063
 
Takashi Iwai 678063
 /* interpret the buffer as a number to call the set function with */
Takashi Iwai 678063
-ssize_t simple_attr_write(struct file *file, const char __user *buf,
Takashi Iwai 678063
-			  size_t len, loff_t *ppos)
Takashi Iwai 678063
+static ssize_t simple_attr_write_xsigned(struct file *file, const char __user *buf,
Takashi Iwai 678063
+			  size_t len, loff_t *ppos, bool is_signed)
Takashi Iwai 678063
 {
Takashi Iwai 678063
 	struct simple_attr *attr;
Takashi Iwai 678063
 	unsigned long long val;
Takashi Iwai 678063
@@ -989,7 +989,10 @@ ssize_t simple_attr_write(struct file *f
Takashi Iwai 678063
 		goto out;
Takashi Iwai 678063
 
Takashi Iwai 678063
 	attr->set_buf[size] = '\0';
Takashi Iwai 678063
-	ret = kstrtoull(attr->set_buf, 0, &val;;
Takashi Iwai 678063
+	if (is_signed)
Takashi Iwai 678063
+		ret = kstrtoll(attr->set_buf, 0, &val;;
Takashi Iwai 678063
+	else
Takashi Iwai 678063
+		ret = kstrtoull(attr->set_buf, 0, &val;;
Takashi Iwai 678063
 	if (ret)
Takashi Iwai 678063
 		goto out;
Takashi Iwai 678063
 	ret = attr->set(attr->data, val);
Takashi Iwai 678063
@@ -999,8 +1002,21 @@ out:
Takashi Iwai 678063
 	mutex_unlock(&attr->mutex);
Takashi Iwai 678063
 	return ret;
Takashi Iwai 678063
 }
Takashi Iwai 678063
+
Takashi Iwai 678063
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
Takashi Iwai 678063
+			  size_t len, loff_t *ppos)
Takashi Iwai 678063
+{
Takashi Iwai 678063
+	return simple_attr_write_xsigned(file, buf, len, ppos, false);
Takashi Iwai 678063
+}
Takashi Iwai 678063
 EXPORT_SYMBOL_GPL(simple_attr_write);
Takashi Iwai 678063
 
Takashi Iwai 678063
+ssize_t simple_attr_write_signed(struct file *file, const char __user *buf,
Takashi Iwai 678063
+			  size_t len, loff_t *ppos)
Takashi Iwai 678063
+{
Takashi Iwai 678063
+	return simple_attr_write_xsigned(file, buf, len, ppos, true);
Takashi Iwai 678063
+}
Takashi Iwai 678063
+EXPORT_SYMBOL_GPL(simple_attr_write_signed);
Takashi Iwai 678063
+
Takashi Iwai 678063
 /**
Takashi Iwai 678063
  * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
Takashi Iwai 678063
  * @sb:		filesystem to do the file handle conversion on
Takashi Iwai 678063
--- a/include/linux/fs.h
Takashi Iwai 678063
+++ b/include/linux/fs.h
Takashi Iwai 678063
@@ -3631,7 +3631,7 @@ void simple_transaction_set(struct file
Takashi Iwai 678063
  * All attributes contain a text representation of a numeric value
Takashi Iwai 678063
  * that are accessed with the get() and set() functions.
Takashi Iwai 678063
  */
Takashi Iwai 678063
-#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)		\
Takashi Iwai 678063
+#define DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, __is_signed)	\
Takashi Iwai 678063
 static int __fops ## _open(struct inode *inode, struct file *file)	\
Takashi Iwai 678063
 {									\
Takashi Iwai 678063
 	__simple_attr_check_format(__fmt, 0ull);			\
Takashi Iwai 678063
@@ -3642,10 +3642,16 @@ static const struct file_operations __fo
Takashi Iwai 678063
 	.open	 = __fops ## _open,					\
Takashi Iwai 678063
 	.release = simple_attr_release,					\
Takashi Iwai 678063
 	.read	 = simple_attr_read,					\
Takashi Iwai 678063
-	.write	 = simple_attr_write,					\
Takashi Iwai 678063
+	.write	 = (__is_signed) ? simple_attr_write_signed : simple_attr_write,	\
Takashi Iwai 678063
 	.llseek	 = generic_file_llseek,					\
Takashi Iwai 678063
 }
Takashi Iwai 678063
 
Takashi Iwai 678063
+#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)		\
Takashi Iwai 678063
+	DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, false)
Takashi Iwai 678063
+
Takashi Iwai 678063
+#define DEFINE_SIMPLE_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt)	\
Takashi Iwai 678063
+	DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, true)
Takashi Iwai 678063
+
Takashi Iwai 678063
 static inline __printf(1, 2)
Takashi Iwai 678063
 void __simple_attr_check_format(const char *fmt, ...)
Takashi Iwai 678063
 {
Takashi Iwai 678063
@@ -3660,6 +3666,8 @@ ssize_t simple_attr_read(struct file *fi
Takashi Iwai 678063
 			 size_t len, loff_t *ppos);
Takashi Iwai 678063
 ssize_t simple_attr_write(struct file *file, const char __user *buf,
Takashi Iwai 678063
 			  size_t len, loff_t *ppos);
Takashi Iwai 678063
+ssize_t simple_attr_write_signed(struct file *file, const char __user *buf,
Takashi Iwai 678063
+				 size_t len, loff_t *ppos);
Takashi Iwai 678063
 
Takashi Iwai 678063
 struct ctl_table;
Takashi Iwai 678063
 int proc_nr_files(struct ctl_table *table, int write,