Skip to content

Commit abdd9fe

Browse files
tiwaikdave
authored andcommitted
btrfs: sysfs: Use scnprintf() instead of snprintf()
snprintf() is a hard-to-use function, and it's especially difficult to use it properly for concatenating substrings in a buffer with a limited size. Since snprintf() returns the would-be-output size, not the actual size, the subsequent use of snprintf() may point to the incorrect position easily. Also, returning the value from snprintf() directly to sysfs show function would pass a bogus value that is higher than the actually truncated string. That said, although the current code doesn't actually overflow the buffer with PAGE_SIZE, it's a usage that shouldn't be done. Or it's worse; this gives a wrong confidence as if it were doing safe operations. This patch replaces such snprintf() calls with a safer version, scnprintf(). It returns the actual output size, hence it's more intuitive and the code does what's expected. Signed-off-by: Takashi Iwai <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 39dba87 commit abdd9fe

File tree

1 file changed

+28
-29
lines changed

1 file changed

+28
-29
lines changed

fs/btrfs/sysfs.c

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
155155
} else
156156
val = can_modify_feature(fa);
157157

158-
return snprintf(buf, PAGE_SIZE, "%d\n", val);
158+
return scnprintf(buf, PAGE_SIZE, "%d\n", val);
159159
}
160160

161161
static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
@@ -295,7 +295,7 @@ static const struct attribute_group btrfs_feature_attr_group = {
295295
static ssize_t rmdir_subvol_show(struct kobject *kobj,
296296
struct kobj_attribute *ka, char *buf)
297297
{
298-
return snprintf(buf, PAGE_SIZE, "0\n");
298+
return scnprintf(buf, PAGE_SIZE, "0\n");
299299
}
300300
BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show);
301301

@@ -310,12 +310,12 @@ static ssize_t supported_checksums_show(struct kobject *kobj,
310310
* This "trick" only works as long as 'enum btrfs_csum_type' has
311311
* no holes in it
312312
*/
313-
ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s%s",
313+
ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s",
314314
(i == 0 ? "" : " "), btrfs_super_csum_name(i));
315315

316316
}
317317

318-
ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
318+
ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
319319
return ret;
320320
}
321321
BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show);
@@ -350,7 +350,7 @@ static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj,
350350
{
351351
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
352352

353-
return snprintf(buf, PAGE_SIZE, "%lld\n",
353+
return scnprintf(buf, PAGE_SIZE, "%lld\n",
354354
atomic64_read(&fs_info->discard_ctl.discardable_bytes));
355355
}
356356
BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show);
@@ -361,7 +361,7 @@ static ssize_t btrfs_discardable_extents_show(struct kobject *kobj,
361361
{
362362
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
363363

364-
return snprintf(buf, PAGE_SIZE, "%d\n",
364+
return scnprintf(buf, PAGE_SIZE, "%d\n",
365365
atomic_read(&fs_info->discard_ctl.discardable_extents));
366366
}
367367
BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show);
@@ -372,7 +372,7 @@ static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj,
372372
{
373373
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
374374

375-
return snprintf(buf, PAGE_SIZE, "%lld\n",
375+
return scnprintf(buf, PAGE_SIZE, "%lld\n",
376376
fs_info->discard_ctl.discard_bitmap_bytes);
377377
}
378378
BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show);
@@ -383,7 +383,7 @@ static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj,
383383
{
384384
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
385385

386-
return snprintf(buf, PAGE_SIZE, "%lld\n",
386+
return scnprintf(buf, PAGE_SIZE, "%lld\n",
387387
atomic64_read(&fs_info->discard_ctl.discard_bytes_saved));
388388
}
389389
BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show);
@@ -394,7 +394,7 @@ static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj,
394394
{
395395
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
396396

397-
return snprintf(buf, PAGE_SIZE, "%lld\n",
397+
return scnprintf(buf, PAGE_SIZE, "%lld\n",
398398
fs_info->discard_ctl.discard_extent_bytes);
399399
}
400400
BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show);
@@ -405,7 +405,7 @@ static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj,
405405
{
406406
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
407407

408-
return snprintf(buf, PAGE_SIZE, "%u\n",
408+
return scnprintf(buf, PAGE_SIZE, "%u\n",
409409
READ_ONCE(fs_info->discard_ctl.iops_limit));
410410
}
411411

@@ -435,7 +435,7 @@ static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj,
435435
{
436436
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
437437

438-
return snprintf(buf, PAGE_SIZE, "%u\n",
438+
return scnprintf(buf, PAGE_SIZE, "%u\n",
439439
READ_ONCE(fs_info->discard_ctl.kbps_limit));
440440
}
441441

@@ -465,7 +465,7 @@ static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj,
465465
{
466466
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
467467

468-
return snprintf(buf, PAGE_SIZE, "%llu\n",
468+
return scnprintf(buf, PAGE_SIZE, "%llu\n",
469469
READ_ONCE(fs_info->discard_ctl.max_discard_size));
470470
}
471471

@@ -530,7 +530,7 @@ static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
530530
val = *value_ptr;
531531
if (lock)
532532
spin_unlock(lock);
533-
return snprintf(buf, PAGE_SIZE, "%llu\n", val);
533+
return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
534534
}
535535

536536
static ssize_t global_rsv_size_show(struct kobject *kobj,
@@ -576,7 +576,7 @@ static ssize_t raid_bytes_show(struct kobject *kobj,
576576
val += block_group->used;
577577
}
578578
up_read(&sinfo->groups_sem);
579-
return snprintf(buf, PAGE_SIZE, "%llu\n", val);
579+
return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
580580
}
581581

582582
static struct attribute *raid_attrs[] = {
@@ -613,7 +613,7 @@ static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj,
613613
{
614614
struct btrfs_space_info *sinfo = to_space_info(kobj);
615615
s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned);
616-
return snprintf(buf, PAGE_SIZE, "%lld\n", val);
616+
return scnprintf(buf, PAGE_SIZE, "%lld\n", val);
617617
}
618618

619619
SPACE_INFO_ATTR(flags);
@@ -670,7 +670,7 @@ static ssize_t btrfs_label_show(struct kobject *kobj,
670670
ssize_t ret;
671671

672672
spin_lock(&fs_info->super_lock);
673-
ret = snprintf(buf, PAGE_SIZE, label[0] ? "%s\n" : "%s", label);
673+
ret = scnprintf(buf, PAGE_SIZE, label[0] ? "%s\n" : "%s", label);
674674
spin_unlock(&fs_info->super_lock);
675675

676676
return ret;
@@ -718,7 +718,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj,
718718
{
719719
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
720720

721-
return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize);
721+
return scnprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize);
722722
}
723723

724724
BTRFS_ATTR(, nodesize, btrfs_nodesize_show);
@@ -728,8 +728,8 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
728728
{
729729
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
730730

731-
return snprintf(buf, PAGE_SIZE, "%u\n",
732-
fs_info->super_copy->sectorsize);
731+
return scnprintf(buf, PAGE_SIZE, "%u\n",
732+
fs_info->super_copy->sectorsize);
733733
}
734734

735735
BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show);
@@ -739,8 +739,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
739739
{
740740
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
741741

742-
return snprintf(buf, PAGE_SIZE, "%u\n",
743-
fs_info->super_copy->sectorsize);
742+
return scnprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize);
744743
}
745744

746745
BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show);
@@ -752,7 +751,7 @@ static ssize_t quota_override_show(struct kobject *kobj,
752751
int quota_override;
753752

754753
quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags);
755-
return snprintf(buf, PAGE_SIZE, "%d\n", quota_override);
754+
return scnprintf(buf, PAGE_SIZE, "%d\n", quota_override);
756755
}
757756

758757
static ssize_t quota_override_store(struct kobject *kobj,
@@ -790,7 +789,7 @@ static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj,
790789
{
791790
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
792791

793-
return snprintf(buf, PAGE_SIZE, "%pU\n",
792+
return scnprintf(buf, PAGE_SIZE, "%pU\n",
794793
fs_info->fs_devices->metadata_uuid);
795794
}
796795

@@ -802,7 +801,7 @@ static ssize_t btrfs_checksum_show(struct kobject *kobj,
802801
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
803802
u16 csum_type = btrfs_super_csum_type(fs_info->super_copy);
804803

805-
return snprintf(buf, PAGE_SIZE, "%s (%s)\n",
804+
return scnprintf(buf, PAGE_SIZE, "%s (%s)\n",
806805
btrfs_super_csum_name(csum_type),
807806
crypto_shash_driver_name(fs_info->csum_shash));
808807
}
@@ -992,7 +991,7 @@ char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags)
992991
continue;
993992

994993
name = btrfs_feature_attrs[set][i].kobj_attr.attr.name;
995-
len += snprintf(str + len, bufsize - len, "%s%s",
994+
len += scnprintf(str + len, bufsize - len, "%s%s",
996995
len ? "," : "", name);
997996
}
998997

@@ -1201,7 +1200,7 @@ static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj,
12011200

12021201
val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
12031202

1204-
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1203+
return scnprintf(buf, PAGE_SIZE, "%d\n", val);
12051204
}
12061205
BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show);
12071206

@@ -1214,7 +1213,7 @@ static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj,
12141213

12151214
val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state);
12161215

1217-
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1216+
return scnprintf(buf, PAGE_SIZE, "%d\n", val);
12181217
}
12191218
BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show);
12201219

@@ -1228,7 +1227,7 @@ static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj,
12281227

12291228
val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
12301229

1231-
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1230+
return scnprintf(buf, PAGE_SIZE, "%d\n", val);
12321231
}
12331232
BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show);
12341233

@@ -1241,7 +1240,7 @@ static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj,
12411240

12421241
val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
12431242

1244-
return snprintf(buf, PAGE_SIZE, "%d\n", val);
1243+
return scnprintf(buf, PAGE_SIZE, "%d\n", val);
12451244
}
12461245
BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show);
12471246

0 commit comments

Comments
 (0)