Author: markj
Date: Fri Feb 16 15:41:03 2018
New Revision: 329375
URL: https://svnweb.freebsd.org/changeset/base/329375

Log:
  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

Modified:
  head/lib/libufs/sblock.c
  head/stand/libsa/ufs.c
  head/sys/geom/geom_io.c
  head/sys/geom/journal/g_journal_ufs.c
  head/sys/geom/label/g_label_ufs.c
  head/sys/ufs/ffs/ffs_subr.c
  head/sys/ufs/ffs/ffs_vfsops.c

Modified: head/lib/libufs/sblock.c
==============================================================================
--- head/lib/libufs/sblock.c    Fri Feb 16 15:38:22 2018        (r329374)
+++ head/lib/libufs/sblock.c    Fri Feb 16 15:41:03 2018        (r329375)
@@ -150,6 +150,7 @@ use_pread(void *devfd, off_t loc, void **bufp, int siz
        int fd;
 
        fd = *(int *)devfd;
+       free(*bufp);
        if ((*bufp = malloc(size)) == NULL)
                return (ENOSPC);
        if (pread(fd, *bufp, size, loc) != size)

Modified: head/stand/libsa/ufs.c
==============================================================================
--- head/stand/libsa/ufs.c      Fri Feb 16 15:38:22 2018        (r329374)
+++ head/stand/libsa/ufs.c      Fri Feb 16 15:41:03 2018        (r329375)
@@ -687,6 +687,7 @@ ufs_use_sa_read(void *devfd, off_t loc, void **bufp, i
        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,

Modified: head/sys/geom/geom_io.c
==============================================================================
--- head/sys/geom/geom_io.c     Fri Feb 16 15:38:22 2018        (r329374)
+++ head/sys/geom/geom_io.c     Fri Feb 16 15:41:03 2018        (r329375)
@@ -966,6 +966,8 @@ g_use_g_read_data(void *devfd, off_t loc, void **bufp,
         */
        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);

Modified: head/sys/geom/journal/g_journal_ufs.c
==============================================================================
--- head/sys/geom/journal/g_journal_ufs.c       Fri Feb 16 15:38:22 2018        
(r329374)
+++ head/sys/geom/journal/g_journal_ufs.c       Fri Feb 16 15:41:03 2018        
(r329375)
@@ -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);

Modified: head/sys/geom/label/g_label_ufs.c
==============================================================================
--- head/sys/geom/label/g_label_ufs.c   Fri Feb 16 15:38:22 2018        
(r329374)
+++ head/sys/geom/label/g_label_ufs.c   Fri Feb 16 15:41:03 2018        
(r329375)
@@ -75,9 +75,14 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *
        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)

Modified: head/sys/ufs/ffs/ffs_subr.c
==============================================================================
--- head/sys/ufs/ffs/ffs_subr.c Fri Feb 16 15:38:22 2018        (r329374)
+++ head/sys/ufs/ffs/ffs_subr.c Fri Feb 16 15:41:03 2018        (r329375)
@@ -172,6 +172,7 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsuper
        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 altsuper
                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);

Modified: head/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vfsops.c       Fri Feb 16 15:38:22 2018        
(r329374)
+++ head/sys/ufs/ffs/ffs_vfsops.c       Fri Feb 16 15:41:03 2018        
(r329375)
@@ -1075,6 +1075,7 @@ ffs_use_bread(void *devfd, off_t loc, void **bufp, int
        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) {
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to