From: Kees Cook <keescook@chromium.org>
To: Chris Mason <clm@fb.com>
Cc: Kees Cook <keescook@chromium.org>,
Josef Bacik <josef@toxicpanda.com>,
David Sterba <dsterba@suse.com>,
linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-hardening@vger.kernel.org
Subject: [PATCH] btrfs: sysfs: Handle NULL return values
Date: Sat, 4 Feb 2023 10:35:10 -0800 [thread overview]
Message-ID: <20230204183510.never.909-kees@kernel.org> (raw)
Each of to_fs_info(), discard_to_fs_info(), and to_space_info() can
return NULL values. Check for these so it's not possible to perform
calculations against NULL pointers. Fixes many warnings seen with GCC 13
like:
In function 'btrfs_show_u64',
inlined from 'btrfs_space_info_show_flags' at ../fs/btrfs/sysfs.c:827:1:
../fs/btrfs/sysfs.c:636:13: warning: array subscript -50 is outside array bounds of 'struct kobject[36028797018963967]' [-Warray-bounds=]
636 | val = *value_ptr;
| ~~~~^~~~~~~~~~~~
Cc: Chris Mason <clm@fb.com>
Cc: Josef Bacik <josef@toxicpanda.com>
Cc: David Sterba <dsterba@suse.com>
Cc: linux-btrfs@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
fs/btrfs/sysfs.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 75 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 108aa3876186..01e0f439d8e6 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -444,6 +444,8 @@ static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%lld\n",
atomic64_read(&fs_info->discard_ctl.discardable_bytes));
}
@@ -455,6 +457,8 @@ static ssize_t btrfs_discardable_extents_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%d\n",
atomic_read(&fs_info->discard_ctl.discardable_extents));
}
@@ -466,6 +470,8 @@ static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%llu\n",
fs_info->discard_ctl.discard_bitmap_bytes);
}
@@ -477,6 +483,8 @@ static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%lld\n",
atomic64_read(&fs_info->discard_ctl.discard_bytes_saved));
}
@@ -488,6 +496,8 @@ static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%llu\n",
fs_info->discard_ctl.discard_extent_bytes);
}
@@ -499,6 +509,8 @@ static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%u\n",
READ_ONCE(fs_info->discard_ctl.iops_limit));
}
@@ -512,6 +524,8 @@ static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj,
u32 iops_limit;
int ret;
+ if (!fs_info)
+ return -EINVAL;
ret = kstrtou32(buf, 10, &iops_limit);
if (ret)
return -EINVAL;
@@ -530,6 +544,8 @@ static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%u\n",
READ_ONCE(fs_info->discard_ctl.kbps_limit));
}
@@ -543,6 +559,9 @@ static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj,
u32 kbps_limit;
int ret;
+ if (!fs_info)
+ return -EINVAL;
+
ret = kstrtou32(buf, 10, &kbps_limit);
if (ret)
return -EINVAL;
@@ -560,6 +579,8 @@ static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%llu\n",
READ_ONCE(fs_info->discard_ctl.max_discard_size));
}
@@ -573,6 +594,8 @@ static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj,
u64 max_discard_size;
int ret;
+ if (!fs_info)
+ return -EINVAL;
ret = kstrtou64(buf, 10, &max_discard_size);
if (ret)
return -EINVAL;
@@ -644,6 +667,9 @@ static ssize_t global_rsv_size_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
+
+ if (!fs_info)
+ return -EINVAL;
return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf);
}
BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show);
@@ -653,6 +679,9 @@ static ssize_t global_rsv_reserved_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
+
+ if (!fs_info)
+ return -EINVAL;
return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf);
}
BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show);
@@ -714,6 +743,9 @@ static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \
char *buf) \
{ \
struct btrfs_space_info *sinfo = to_space_info(kobj); \
+ \
+ if (!sinfo) \
+ return -EINVAL; \
return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \
} \
BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field)
@@ -723,6 +755,8 @@ static ssize_t btrfs_chunk_size_show(struct kobject *kobj,
{
struct btrfs_space_info *sinfo = to_space_info(kobj);
+ if (!sinfo)
+ return -EINVAL;
return sysfs_emit(buf, "%llu\n", READ_ONCE(sinfo->chunk_size));
}
@@ -745,6 +779,9 @@ static ssize_t btrfs_chunk_size_store(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!space_info || !fs_info)
+ return -EINVAL;
+
if (!fs_info->fs_devices)
return -EINVAL;
@@ -795,6 +832,9 @@ static ssize_t btrfs_force_chunk_alloc_store(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!space_info || !fs_info)
+ return -EINVAL;
+
if (sb_rdonly(fs_info->sb))
return -EROFS;
@@ -842,6 +882,8 @@ static ssize_t btrfs_sinfo_bg_reclaim_threshold_show(struct kobject *kobj,
{
struct btrfs_space_info *space_info = to_space_info(kobj);
+ if (!space_info)
+ return -EINVAL;
return sysfs_emit(buf, "%d\n", READ_ONCE(space_info->bg_reclaim_threshold));
}
@@ -853,6 +895,9 @@ static ssize_t btrfs_sinfo_bg_reclaim_threshold_store(struct kobject *kobj,
int thresh;
int ret;
+ if (!space_info)
+ return -EINVAL;
+
ret = kstrtoint(buf, 10, &thresh);
if (ret)
return ret;
@@ -924,6 +969,9 @@ static ssize_t btrfs_label_show(struct kobject *kobj,
char *label = fs_info->super_copy->label;
ssize_t ret;
+ if (!fs_info)
+ return -EINVAL;
+
spin_lock(&fs_info->super_lock);
ret = sysfs_emit(buf, label[0] ? "%s\n" : "%s", label);
spin_unlock(&fs_info->super_lock);
@@ -973,6 +1021,8 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize);
}
@@ -983,6 +1033,8 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize);
}
@@ -993,6 +1045,8 @@ static ssize_t btrfs_commit_stats_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf,
"commits %llu\n"
"last_commit_ms %llu\n"
@@ -1035,6 +1089,8 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize);
}
@@ -1046,6 +1102,8 @@ static ssize_t quota_override_show(struct kobject *kobj,
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
int quota_override;
+ if (!fs_info)
+ return -EINVAL;
quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags);
return sysfs_emit(buf, "%d\n", quota_override);
}
@@ -1085,6 +1143,8 @@ static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%pU\n", fs_info->fs_devices->metadata_uuid);
}
@@ -1094,8 +1154,11 @@ static ssize_t btrfs_checksum_show(struct kobject *kobj,
struct kobj_attribute *a, char *buf)
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
- u16 csum_type = btrfs_super_csum_type(fs_info->super_copy);
+ u16 csum_type;
+ if (!fs_info)
+ return -EINVAL;
+ csum_type = btrfs_super_csum_type(fs_info->super_copy);
return sysfs_emit(buf, "%s (%s)\n",
btrfs_super_csum_name(csum_type),
crypto_shash_driver_name(fs_info->csum_shash));
@@ -1109,6 +1172,8 @@ static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj,
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
const char *str;
+ if (!fs_info)
+ return -EINVAL;
switch (READ_ONCE(fs_info->exclusive_operation)) {
case BTRFS_EXCLOP_NONE:
str = "none\n";
@@ -1147,6 +1212,8 @@ static ssize_t btrfs_generation_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%llu\n", fs_info->generation);
}
BTRFS_ATTR(, generation, btrfs_generation_show);
@@ -1205,6 +1272,8 @@ static ssize_t btrfs_bg_reclaim_threshold_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ if (!fs_info)
+ return -EINVAL;
return sysfs_emit(buf, "%d\n", READ_ONCE(fs_info->bg_reclaim_threshold));
}
@@ -1216,6 +1285,9 @@ static ssize_t btrfs_bg_reclaim_threshold_store(struct kobject *kobj,
int thresh;
int ret;
+ if (!fs_info)
+ return -EINVAL;
+
ret = kstrtoint(buf, 10, &thresh);
if (ret)
return ret;
@@ -1273,6 +1345,8 @@ static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj)
static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
{
+ if (!kobj)
+ return NULL;
if (kobj->ktype != &btrfs_ktype)
return NULL;
return to_fs_devs(kobj)->fs_info;
--
2.34.1
next reply other threads:[~2023-02-04 18:35 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-04 18:35 Kees Cook [this message]
2023-02-05 7:13 ` [PATCH] btrfs: sysfs: Handle NULL return values Greg KH
2023-02-06 18:33 ` David Sterba
2023-02-06 18:37 ` Kees Cook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230204183510.never.909-kees@kernel.org \
--to=keescook@chromium.org \
--cc=clm@fb.com \
--cc=dsterba@suse.com \
--cc=josef@toxicpanda.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.