Skip to content

Commit 2e41f27

Browse files
mitaakpm00
authored andcommitted
libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value
Patch series "fix error when writing negative value to simple attribute files". The simple attribute files do not accept a negative value since the commit 488dac0 ("libfs: fix error cast of negative value in simple_attr_write()"), but some attribute files want to accept a negative value. This patch (of 3): The simple attribute files do not accept a negative value since the commit 488dac0 ("libfs: fix error cast of negative value in simple_attr_write()"), so we have to use a 64-bit value to write a negative value. This adds DEFINE_SIMPLE_ATTRIBUTE_SIGNED for a signed value. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: 488dac0 ("libfs: fix error cast of negative value in simple_attr_write()") Signed-off-by: Akinobu Mita <[email protected]> Reported-by: Zhao Gongyi <[email protected]> Reviewed-by: David Hildenbrand <[email protected]> Reviewed-by: Greg Kroah-Hartman <[email protected]> Cc: Alexander Viro <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Rafael J. Wysocki <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Wei Yongjun <[email protected]> Cc: Yicong Yang <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7b9cbc7 commit 2e41f27

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

fs/libfs.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -995,8 +995,8 @@ ssize_t simple_attr_read(struct file *file, char __user *buf,
995995
EXPORT_SYMBOL_GPL(simple_attr_read);
996996

997997
/* interpret the buffer as a number to call the set function with */
998-
ssize_t simple_attr_write(struct file *file, const char __user *buf,
999-
size_t len, loff_t *ppos)
998+
static ssize_t simple_attr_write_xsigned(struct file *file, const char __user *buf,
999+
size_t len, loff_t *ppos, bool is_signed)
10001000
{
10011001
struct simple_attr *attr;
10021002
unsigned long long val;
@@ -1017,7 +1017,10 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
10171017
goto out;
10181018

10191019
attr->set_buf[size] = '\0';
1020-
ret = kstrtoull(attr->set_buf, 0, &val);
1020+
if (is_signed)
1021+
ret = kstrtoll(attr->set_buf, 0, &val);
1022+
else
1023+
ret = kstrtoull(attr->set_buf, 0, &val);
10211024
if (ret)
10221025
goto out;
10231026
ret = attr->set(attr->data, val);
@@ -1027,8 +1030,21 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
10271030
mutex_unlock(&attr->mutex);
10281031
return ret;
10291032
}
1033+
1034+
ssize_t simple_attr_write(struct file *file, const char __user *buf,
1035+
size_t len, loff_t *ppos)
1036+
{
1037+
return simple_attr_write_xsigned(file, buf, len, ppos, false);
1038+
}
10301039
EXPORT_SYMBOL_GPL(simple_attr_write);
10311040

1041+
ssize_t simple_attr_write_signed(struct file *file, const char __user *buf,
1042+
size_t len, loff_t *ppos)
1043+
{
1044+
return simple_attr_write_xsigned(file, buf, len, ppos, true);
1045+
}
1046+
EXPORT_SYMBOL_GPL(simple_attr_write_signed);
1047+
10321048
/**
10331049
* generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
10341050
* @sb: filesystem to do the file handle conversion on

include/linux/fs.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3485,7 +3485,7 @@ void simple_transaction_set(struct file *file, size_t n);
34853485
* All attributes contain a text representation of a numeric value
34863486
* that are accessed with the get() and set() functions.
34873487
*/
3488-
#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
3488+
#define DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, __is_signed) \
34893489
static int __fops ## _open(struct inode *inode, struct file *file) \
34903490
{ \
34913491
__simple_attr_check_format(__fmt, 0ull); \
@@ -3496,10 +3496,16 @@ static const struct file_operations __fops = { \
34963496
.open = __fops ## _open, \
34973497
.release = simple_attr_release, \
34983498
.read = simple_attr_read, \
3499-
.write = simple_attr_write, \
3499+
.write = (__is_signed) ? simple_attr_write_signed : simple_attr_write, \
35003500
.llseek = generic_file_llseek, \
35013501
}
35023502

3503+
#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
3504+
DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, false)
3505+
3506+
#define DEFINE_SIMPLE_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) \
3507+
DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, true)
3508+
35033509
static inline __printf(1, 2)
35043510
void __simple_attr_check_format(const char *fmt, ...)
35053511
{
@@ -3514,6 +3520,8 @@ ssize_t simple_attr_read(struct file *file, char __user *buf,
35143520
size_t len, loff_t *ppos);
35153521
ssize_t simple_attr_write(struct file *file, const char __user *buf,
35163522
size_t len, loff_t *ppos);
3523+
ssize_t simple_attr_write_signed(struct file *file, const char __user *buf,
3524+
size_t len, loff_t *ppos);
35173525

35183526
struct ctl_table;
35193527
int __init list_bdev_fs_names(char *buf, size_t size);

0 commit comments

Comments
 (0)