summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColy Li <colyli@suse.de>2019-02-09 07:52:59 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-05 23:33:09 +0300
commit98eddc19f9e9a0c941fa85315bbbd1083b3e0db3 (patch)
treee3f339dee9e3af1c44f83b414ec710a6ecb2a84d
parentb468e0007435222879d5f4b52f7681a9ac2e1640 (diff)
downloadlinux-98eddc19f9e9a0c941fa85315bbbd1083b3e0db3.tar.xz
bcache: improve sysfs_strtoul_clamp()
[ Upstream commit 596b5a5dd1bc2fa019fdaaae522ef331deef927f ] Currently sysfs_strtoul_clamp() is defined as, 82 #define sysfs_strtoul_clamp(file, var, min, max) \ 83 do { \ 84 if (attr == &sysfs_ ## file) \ 85 return strtoul_safe_clamp(buf, var, min, max) \ 86 ?: (ssize_t) size; \ 87 } while (0) The problem is, if bit width of var is less then unsigned long, min and max may not protect var from integer overflow, because overflow happens in strtoul_safe_clamp() before checking min and max. To fix such overflow in sysfs_strtoul_clamp(), to make min and max take effect, this patch adds an unsigned long variable, and uses it to macro strtoul_safe_clamp() to convert an unsigned long value in range defined by [min, max]. Then assign this value to var. By this method, if bit width of var is less than unsigned long, integer overflow won't happen before min and max are checking. Now sysfs_strtoul_clamp() can properly handle smaller data type like unsigned int, of cause min and max should be defined in range of unsigned int too. Signed-off-by: Coly Li <colyli@suse.de> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/md/bcache/sysfs.h13
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/md/bcache/sysfs.h b/drivers/md/bcache/sysfs.h
index 3fe82425859c..0ad2715a884e 100644
--- a/drivers/md/bcache/sysfs.h
+++ b/drivers/md/bcache/sysfs.h
@@ -81,9 +81,16 @@ do { \
#define sysfs_strtoul_clamp(file, var, min, max) \
do { \
- if (attr == &sysfs_ ## file) \
- return strtoul_safe_clamp(buf, var, min, max) \
- ?: (ssize_t) size; \
+ if (attr == &sysfs_ ## file) { \
+ unsigned long v = 0; \
+ ssize_t ret; \
+ ret = strtoul_safe_clamp(buf, v, min, max); \
+ if (!ret) { \
+ var = v; \
+ return size; \
+ } \
+ return ret; \
+ } \
} while (0)
#define strtoul_or_return(cp) \