diff options
author | Mark Johnston <markj@FreeBSD.org> | 2018-02-16 15:41:03 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2018-02-16 15:41:03 +0000 |
commit | 16759360d44b416be38238fb2d5a51bb0934bbf6 (patch) | |
tree | e767c12a340c04dc1f4e9c623612687b414de4fc /sys/geom | |
parent | 3f060b60b12a5ad3fe7d33f69957ea4a69e9e6e9 (diff) | |
download | src-16759360d44b416be38238fb2d5a51bb0934bbf6.tar.gz src-16759360d44b416be38238fb2d5a51bb0934bbf6.zip |
Fix a memory leak introduced in r328426.
ffs_sbget() may return a superblock buffer even if it fails, so the
caller must be prepared to free it in this case. Moreover, when tasting
alternate superblock locations in a loop, ffs_sbget()'s readfunc
callback must free the previously allocated buffer.
Reported and tested by: pho
Reviewed by: kib (previous version)
Differential Revision: https://reviews.freebsd.org/D14390
Notes
Notes:
svn path=/head/; revision=329375
Diffstat (limited to 'sys/geom')
-rw-r--r-- | sys/geom/geom_io.c | 2 | ||||
-rw-r--r-- | sys/geom/journal/g_journal_ufs.c | 3 | ||||
-rw-r--r-- | sys/geom/label/g_label_ufs.c | 7 |
3 files changed, 11 insertions, 1 deletions
diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c index bab0041a244c..0f63b1ff31ec 100644 --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -966,6 +966,8 @@ g_use_g_read_data(void *devfd, off_t loc, void **bufp, int size) */ if (loc % cp->provider->sectorsize != 0) return (ENOENT); + if (*bufp != NULL) + g_free(*bufp); *bufp = g_read_data(cp, loc, size, NULL); if (*bufp == NULL) return (ENOENT); diff --git a/sys/geom/journal/g_journal_ufs.c b/sys/geom/journal/g_journal_ufs.c index ec25750c38ac..6672cceb8cb4 100644 --- a/sys/geom/journal/g_journal_ufs.c +++ b/sys/geom/journal/g_journal_ufs.c @@ -70,10 +70,13 @@ g_journal_ufs_dirty(struct g_consumer *cp) struct fs *fs; int error; + fs = NULL; if (SBLOCKSIZE % cp->provider->sectorsize != 0 || ffs_sbget(cp, &fs, -1, NULL, g_use_g_read_data) != 0) { GJ_DEBUG(0, "Cannot find superblock to mark file system %s " "as dirty.", cp->provider->name); + if (fs != NULL) + g_free(fs); return; } GJ_DEBUG(0, "clean=%d flags=0x%x", fs->fs_clean, fs->fs_flags); diff --git a/sys/geom/label/g_label_ufs.c b/sys/geom/label/g_label_ufs.c index 8ba49841b359..f32ec4d55c19 100644 --- a/sys/geom/label/g_label_ufs.c +++ b/sys/geom/label/g_label_ufs.c @@ -75,9 +75,14 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int wh pp = cp->provider; label[0] = '\0'; + fs = NULL; if (SBLOCKSIZE % pp->sectorsize != 0 || - ffs_sbget(cp, &fs, -1, NULL, g_use_g_read_data) != 0) + ffs_sbget(cp, &fs, -1, NULL, g_use_g_read_data) != 0) { + if (fs != NULL) + g_free(fs); return; + } + /* * Check for magic. We also need to check if file system size * is almost equal to providers size, because sysinstall(8) |