Discussion:
[PATCH] libnilfs: set errno when device doesn't contain valid NILFS data
Ryusuke Konishi
2014-08-23 07:12:18 UTC
Permalink
Fix the bug that no error number is set to errno variable if the
specified device doesn't contain a valid nilfs file system, which
causes caller programs to output successful message wrongly. Three
functions, nilfs_open(), nilfs_sb_read() and nilfs_sb_write() have
this flaw.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke-***@public.gmane.org>
---
lib/sb.c | 55 +++++++++++++++++++++++++++++++++----------------------
1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/lib/sb.c b/lib/sb.c
index 94bccaf..44453bb 100644
--- a/lib/sb.c
+++ b/lib/sb.c
@@ -97,10 +97,20 @@ static int nilfs_sb_is_valid(struct nilfs_super_block *sbp, int check_crc)
return crc == le32_to_cpu(sbp->s_sum);
}

+static int nilfs_sb2_offset_is_too_small(struct nilfs_super_block *sbp,
+ __u64 sb2_offset)
+{
+ return sb2_offset < ((le64_to_cpu(sbp->s_nsegments) *
+ le32_to_cpu(sbp->s_blocks_per_segment)) <<
+ (le32_to_cpu(sbp->s_log_block_size) +
+ NILFS_SB_BLOCK_SIZE_SHIFT));
+}
+
static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
__u64 *offsets)
{
__u64 devsize, sb2_offset;
+ int invalid_fs = 0;

sbp[0] = malloc(NILFS_MAX_SB_SIZE);
sbp[1] = malloc(NILFS_MAX_SB_SIZE);
@@ -110,34 +120,40 @@ static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
if (ioctl(devfd, BLKGETSIZE64, &devsize) != 0)
goto failed;

- if (lseek(devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 ||
- read(devfd, sbp[0], NILFS_MAX_SB_SIZE) < 0 ||
- !nilfs_sb_is_valid(sbp[0], 0)) {
- free(sbp[0]);
- sbp[0] = NULL;
+ if (lseek(devfd, NILFS_SB_OFFSET_BYTES, SEEK_SET) >= 0 &&
+ read(devfd, sbp[0], NILFS_MAX_SB_SIZE) >= 0) {
+ if (nilfs_sb_is_valid(sbp[0], 0))
+ goto sb1_ok;
+ invalid_fs = 1;
}

+ free(sbp[0]);
+ sbp[0] = NULL;
+sb1_ok:
+
sb2_offset = NILFS_SB2_OFFSET_BYTES(devsize);
if (offsets) {
offsets[0] = NILFS_SB_OFFSET_BYTES;
offsets[1] = sb2_offset;
}

- if (lseek(devfd, sb2_offset, SEEK_SET) < 0 ||
- read(devfd, sbp[1], NILFS_MAX_SB_SIZE) < 0 ||
- !nilfs_sb_is_valid(sbp[1], 0))
- goto sb2_failed;
+ if (lseek(devfd, sb2_offset, SEEK_SET) >= 0 &&
+ read(devfd, sbp[1], NILFS_MAX_SB_SIZE) >= 0) {
+ if (nilfs_sb_is_valid(sbp[1], 0) &&
+ !nilfs_sb2_offset_is_too_small(sbp[1], sb2_offset))
+ goto sb2_ok;
+ invalid_fs = 1;
+ }

- if (sb2_offset <
- (le64_to_cpu(sbp[1]->s_nsegments) *
- le32_to_cpu(sbp[1]->s_blocks_per_segment)) <<
- (le32_to_cpu(sbp[1]->s_log_block_size) +
- NILFS_SB_BLOCK_SIZE_SHIFT))
- goto sb2_failed;
+ free(sbp[1]);
+ sbp[1] = NULL;
+sb2_ok:

- sb2_done:
- if (!sbp[0] && !sbp[1])
+ if (!sbp[0] && !sbp[1]) {
+ if (invalid_fs)
+ errno = EINVAL;
goto failed;
+ }

return 0;

@@ -145,11 +161,6 @@ static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
free(sbp[0]); /* free(NULL) is just ignored */
free(sbp[1]);
return -1;
-
- sb2_failed:
- free(sbp[1]);
- sbp[1] = NULL;
- goto sb2_done;
}

struct nilfs_super_block *nilfs_sb_read(int devfd)
--
1.7.9.4

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Loading...