mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
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
This commit is contained in:
parent
3f060b60b1
commit
16759360d4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329375
|
@ -150,6 +150,7 @@ use_pread(void *devfd, off_t loc, void **bufp, int size)
|
|||
int fd;
|
||||
|
||||
fd = *(int *)devfd;
|
||||
free(*bufp);
|
||||
if ((*bufp = malloc(size)) == NULL)
|
||||
return (ENOSPC);
|
||||
if (pread(fd, *bufp, size, loc) != size)
|
||||
|
|
|
@ -687,6 +687,7 @@ ufs_use_sa_read(void *devfd, off_t loc, void **bufp, int size)
|
|||
int error;
|
||||
|
||||
f = (struct open_file *)devfd;
|
||||
free(*bufp);
|
||||
if ((*bufp = malloc(size)) == NULL)
|
||||
return (ENOSPC);
|
||||
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, loc / DEV_BSIZE,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -172,6 +172,7 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsuperblock,
|
|||
int32_t *lp;
|
||||
char *buf;
|
||||
|
||||
*fsp = NULL;
|
||||
if (altsuperblock != -1) {
|
||||
if ((ret = readsuper(devfd, fsp, altsuperblock, readfunc)) != 0)
|
||||
return (ret);
|
||||
|
@ -209,9 +210,11 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsuperblock,
|
|||
size = fs->fs_bsize;
|
||||
if (i + fs->fs_frag > blks)
|
||||
size = (blks - i) * fs->fs_fsize;
|
||||
buf = NULL;
|
||||
ret = (*readfunc)(devfd,
|
||||
dbtob(fsbtodb(fs, fs->fs_csaddr + i)), (void **)&buf, size);
|
||||
if (ret) {
|
||||
UFS_FREE(buf, filltype);
|
||||
UFS_FREE(fs->fs_csp, filltype);
|
||||
fs->fs_csp = NULL;
|
||||
return (ret);
|
||||
|
|
|
@ -1075,6 +1075,7 @@ ffs_use_bread(void *devfd, off_t loc, void **bufp, int size)
|
|||
struct buf *bp;
|
||||
int error;
|
||||
|
||||
free(*bufp, M_UFSMNT);
|
||||
*bufp = malloc(size, M_UFSMNT, M_WAITOK);
|
||||
if ((error = bread((struct vnode *)devfd, btodb(loc), size, NOCRED,
|
||||
&bp)) != 0) {
|
||||
|
|
Loading…
Reference in a new issue