Module Name:    src
Committed By:   msaitoh
Date:           Mon Sep  8 18:57:58 UTC 2014

Modified Files:
        src/sys/ufs/chfs [netbsd-7]: chfs_gc.c chfs_readinode.c chfs_scan.c
            chfs_vnode.c ebh.c

Log Message:
Pull up following revision(s) (requested by he in ticket #74):
        sys/ufs/chfs/chfs_vnode.c: revision 1.11
        sys/ufs/chfs/chfs_readinode.c: revision 1.9
        sys/ufs/chfs/chfs_scan.c: revision 1.5
        sys/ufs/chfs/chfs_gc.c: revision 1.6
        sys/ufs/chfs/ebh.c: revision 1.4
Plug leak in chfs_scan_eraseblock() of the allocated buffer.
Make sure to release it both on success and failure returns.
OK'ed by ttoth@
Plug memory leak in a corner case in chfs_get_data_nodes().
Plug memory leaks in error returns in chfs_readvnode().
Plug memory leak in error returns and normal operation in
chfs_gcollect_pristine().
Plug memory leak in add_peb_to_free() and add_peb_to_in_use()
in case there's a duplicate in the tree.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.5.4.1 src/sys/ufs/chfs/chfs_gc.c
cvs rdiff -u -r1.8 -r1.8.4.1 src/sys/ufs/chfs/chfs_readinode.c
cvs rdiff -u -r1.4 -r1.4.12.1 src/sys/ufs/chfs/chfs_scan.c
cvs rdiff -u -r1.10 -r1.10.4.1 src/sys/ufs/chfs/chfs_vnode.c
cvs rdiff -u -r1.3 -r1.3.14.1 src/sys/ufs/chfs/ebh.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/chfs/chfs_gc.c
diff -u src/sys/ufs/chfs/chfs_gc.c:1.5 src/sys/ufs/chfs/chfs_gc.c:1.5.4.1
--- src/sys/ufs/chfs/chfs_gc.c:1.5	Sun Oct 20 17:18:38 2013
+++ src/sys/ufs/chfs/chfs_gc.c	Mon Sep  8 18:57:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_gc.c,v 1.5 2013/10/20 17:18:38 christos Exp $	*/
+/*	$NetBSD: chfs_gc.c,v 1.5.4.1 2014/09/08 18:57:58 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -726,23 +726,26 @@ chfs_gcollect_pristine(struct chfs_mount
 	ret = chfs_read_leb(chmp, nref->nref_lnr, data, ofs, totlen, &retlen);
 	if (ret) {
 		dbg_gc("reading error\n");
-		return ret;
+		goto err_out;
 	}
 	if (retlen != totlen) {
 		dbg_gc("read size error\n");
-		return EIO;
+		ret = EIO;
+		goto err_out;
 	}
 	nhdr = (struct chfs_flash_node_hdr *)data;
 
 	/* Check the header. */
 	if (le16toh(nhdr->magic) != CHFS_FS_MAGIC_BITMASK) {
 		dbg_gc("node header magic number error\n");
-		return EBADF;
+		ret = EBADF;
+		goto err_out;
 	}
 	crc = crc32(0, (uint8_t *)nhdr, CHFS_NODE_HDR_SIZE - 4);
 	if (crc != le32toh(nhdr->hdr_crc)) {
 		dbg_gc("node header crc error\n");
-		return EBADF;
+		ret = EBADF;
+		goto err_out;
 	}
 
 	/* Read the remaining parts. */
@@ -753,7 +756,8 @@ chfs_gcollect_pristine(struct chfs_mount
 	        crc = crc32(0, (uint8_t *)fvnode, sizeof(struct chfs_flash_vnode) - 4);
 	        if (crc != le32toh(fvnode->node_crc)) {
 				dbg_gc("vnode crc error\n");
-				return EBADF;
+				ret = EBADF;
+				goto err_out;
 			}
 			break;
         case CHFS_NODETYPE_DIRENT:
@@ -762,12 +766,14 @@ chfs_gcollect_pristine(struct chfs_mount
 	        crc = crc32(0, (uint8_t *)fdirent, sizeof(struct chfs_flash_dirent_node) - 4);
 	        if (crc != le32toh(fdirent->node_crc)) {
 				dbg_gc("dirent crc error\n");
-				return EBADF;
+				ret = EBADF;
+				goto err_out;
 			}
 	        crc = crc32(0, fdirent->name, fdirent->nsize);
 	        if (crc != le32toh(fdirent->name_crc)) {
 				dbg_gc("dirent name crc error\n");
-				return EBADF;
+				ret = EBADF;
+				goto err_out;
 			}
 			break;
         case CHFS_NODETYPE_DATA:
@@ -776,25 +782,29 @@ chfs_gcollect_pristine(struct chfs_mount
 	        crc = crc32(0, (uint8_t *)fdata, sizeof(struct chfs_flash_data_node) - 4);
 	        if (crc != le32toh(fdata->node_crc)) {
 				dbg_gc("data node crc error\n");
-				return EBADF;
+				ret = EBADF;
+				goto err_out;
 			}
 			break;
         default:
 		/* unknown node */
 			if (chvc) {
 				dbg_gc("unknown node have vnode cache\n");
-				return EBADF;
+				ret = EBADF;
+				goto err_out;
 			}
 	}
 	/* CRC's OK, write node to its new place */
 retry:
 	ret = chfs_reserve_space_gc(chmp, totlen);
 	if (ret)
-		return ret;
+		goto err_out;
 
 	newnref = chfs_alloc_node_ref(chmp->chm_nextblock);
-	if (!newnref)
-		return ENOMEM;
+	if (!newnref) {
+		ret = ENOMEM;
+		goto err_out;
+	}
 
 	ofs = chmp->chm_ebh->eb_size - chmp->chm_nextblock->free_size;
 	newnref->nref_offset = ofs;
@@ -814,7 +824,8 @@ retry:
 		chfs_change_size_dirty(chmp, chmp->chm_nextblock, totlen);
 		if (retries) {
 			mutex_exit(&chmp->chm_lock_sizes);
-			return EIO;
+			ret = EIO;
+			goto err_out;
 		}
 
 		/* try again */
@@ -829,7 +840,11 @@ retry:
 	mutex_enter(&chmp->chm_lock_vnocache);
 	chfs_add_vnode_ref_to_vc(chmp, chvc, newnref);
 	mutex_exit(&chmp->chm_lock_vnocache);
-	return 0;
+	ret = 0;
+	/* FALLTHROUGH */
+err_out:
+	kmem_free(data, totlen);
+	return ret;
 }
 
 

Index: src/sys/ufs/chfs/chfs_readinode.c
diff -u src/sys/ufs/chfs/chfs_readinode.c:1.8 src/sys/ufs/chfs/chfs_readinode.c:1.8.4.1
--- src/sys/ufs/chfs/chfs_readinode.c:1.8	Sun Oct 20 17:18:38 2013
+++ src/sys/ufs/chfs/chfs_readinode.c	Mon Sep  8 18:57:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_readinode.c,v 1.8 2013/10/20 17:18:38 christos Exp $	*/
+/*	$NetBSD: chfs_readinode.c,v 1.8.4.1 2014/09/08 18:57:58 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -801,8 +801,10 @@ chfs_get_data_nodes(struct chfs_mount *c
 	buf = kmem_alloc(len, KM_SLEEP);
 
 	dnode = kmem_alloc(len, KM_SLEEP);
-	if (!dnode)
+	if (!dnode) {
+		kmem_free(buf, len);
 		return ENOMEM;
+	}
 
 	nref = chfs_first_valid_data_ref(ip->chvc->dnode);
 

Index: src/sys/ufs/chfs/chfs_scan.c
diff -u src/sys/ufs/chfs/chfs_scan.c:1.4 src/sys/ufs/chfs/chfs_scan.c:1.4.12.1
--- src/sys/ufs/chfs/chfs_scan.c:1.4	Fri Oct 19 12:44:39 2012
+++ src/sys/ufs/chfs/chfs_scan.c	Mon Sep  8 18:57:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_scan.c,v 1.4 2012/10/19 12:44:39 ttoth Exp $	*/
+/*	$NetBSD: chfs_scan.c,v 1.4.12.1 2014/09/08 18:57:58 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -443,15 +443,15 @@ chfs_scan_eraseblock(struct chfs_mount *
 		memset(buf, 0 , CHFS_MAX_NODE_SIZE);
 		err = chfs_read_leb(chmp,
 		    lnr, buf, ofs, CHFS_NODE_HDR_SIZE, &retlen);
-		if (err) {
-			return err;
-		}
+		if (err)
+			goto err_return;
 
 		if (retlen != CHFS_NODE_HDR_SIZE) {
 			chfs_err("Error reading node header: "
 			    "read: %zu instead of: %zu\n",
 			    CHFS_NODE_HDR_SIZE, retlen);
-			return EIO;
+			err = EIO;
+			goto err_return;
 		}
 
 		/* first we check if the buffer we read is full with 0xff, if yes maybe
@@ -476,9 +476,8 @@ chfs_scan_eraseblock(struct chfs_mount *
 		if (err) {
 			dbg("node hdr error\n");
 			err = chfs_update_eb_dirty(chmp, cheb, 4);
-			if (err) {
-				return err;
-			}
+			if (err)
+				goto err_return;
 
 			ofs += 4;
 			continue;
@@ -486,7 +485,8 @@ chfs_scan_eraseblock(struct chfs_mount *
 		ofs += CHFS_NODE_HDR_SIZE;
 		if (ofs > chmp->chm_ebh->eb_size) {
 			chfs_err("Second part of node is on the next eraseblock.\n");
-			return EIO;
+			err = EIO;
+			goto err_return;
 		}
 		switch (le16toh(nhdr->type)) {
 		case CHFS_NODETYPE_VNODE:
@@ -496,21 +496,20 @@ chfs_scan_eraseblock(struct chfs_mount *
 			err = chfs_read_leb(chmp,
 			    lnr, buf + CHFS_NODE_HDR_SIZE,
 			    ofs, len,  &retlen);
-			if (err) {
-				return err;
-			}
+			if (err)
+				goto err_return;
 
 			if (retlen != len) {
 				chfs_err("Error reading vnode: read: %zu instead of: %zu\n",
 				    len, retlen);
-				return EIO;
+				err = EIO;
+				goto err_return;
 			}
 			KASSERT(lnr == cheb->lnr);
 			err = chfs_scan_check_vnode(chmp,
 			    cheb, buf, ofs - CHFS_NODE_HDR_SIZE);
-			if (err) {
-				return err;
-			}
+			if (err)
+				goto err_return;
 
 			break;
 		case CHFS_NODETYPE_DIRENT:
@@ -521,23 +520,22 @@ chfs_scan_eraseblock(struct chfs_mount *
 			err = chfs_read_leb(chmp,
 			    lnr, buf + CHFS_NODE_HDR_SIZE,
 			    ofs, len, &retlen);
-			if (err) {
-				return err;
-			}
+			if (err)
+				goto err_return;
 
 			if (retlen != len) {
 				chfs_err("Error reading dirent node: read: %zu "
 				    "instead of: %zu\n", len, retlen);
-				return EIO;
+				err = EIO;
+				goto err_return;
 			}
 
 			KASSERT(lnr == cheb->lnr);
 
 			err = chfs_scan_check_dirent_node(chmp,
 			    cheb, buf, ofs - CHFS_NODE_HDR_SIZE);
-			if (err) {
-				return err;
-			}
+			if (err)
+				goto err_return;
 
 			break;
 		case CHFS_NODETYPE_DATA:
@@ -547,20 +545,20 @@ chfs_scan_eraseblock(struct chfs_mount *
 			err = chfs_read_leb(chmp,
 			    lnr, buf + CHFS_NODE_HDR_SIZE,
 			    ofs, len, &retlen);
-			if (err) {
-				return err;
-			}
+			if (err)
+				goto err_return;
 
 			if (retlen != len) {
 				chfs_err("Error reading data node: read: %zu "
 				    "instead of: %zu\n", len, retlen);
-				return EIO;
+				err = EIO;
+				goto err_return;
 			}
 			KASSERT(lnr == cheb->lnr);
 			err = chfs_scan_check_data_node(chmp,
 			    cheb, buf, ofs - CHFS_NODE_HDR_SIZE);
 			if (err)
-				return err;
+				goto err_return;
 
 			break;
 		case CHFS_NODETYPE_PADDING:
@@ -573,7 +571,7 @@ chfs_scan_eraseblock(struct chfs_mount *
 			err = chfs_update_eb_dirty(chmp, cheb,
 			    le32toh(nhdr->length));
 			if (err)
-				return err;
+				goto err_return;
 
 			break;
 		default:
@@ -581,7 +579,7 @@ chfs_scan_eraseblock(struct chfs_mount *
 			err = chfs_update_eb_dirty(chmp, cheb,
 			    le32toh(nhdr->length));
 			if (err)
-				return err;
+				goto err_return;
 
 			break;
 		}
@@ -591,5 +589,9 @@ chfs_scan_eraseblock(struct chfs_mount *
 	KASSERT(cheb->used_size + cheb->free_size + cheb->dirty_size +
 	    cheb->unchecked_size + cheb->wasted_size == chmp->chm_ebh->eb_size);
 
-	return chfs_scan_classify_cheb(chmp, cheb);
+	err = chfs_scan_classify_cheb(chmp, cheb);
+	/* FALLTHROUGH */
+    err_return:
+	kmem_free(buf, CHFS_MAX_NODE_SIZE);
+	return err;
 }

Index: src/sys/ufs/chfs/chfs_vnode.c
diff -u src/sys/ufs/chfs/chfs_vnode.c:1.10 src/sys/ufs/chfs/chfs_vnode.c:1.10.4.1
--- src/sys/ufs/chfs/chfs_vnode.c:1.10	Thu Jan 23 10:13:57 2014
+++ src/sys/ufs/chfs/chfs_vnode.c	Mon Sep  8 18:57:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_vnode.c,v 1.10 2014/01/23 10:13:57 hannken Exp $	*/
+/*	$NetBSD: chfs_vnode.c,v 1.10.4.1 2014/09/08 18:57:58 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -94,11 +94,14 @@ chfs_readvnode(struct mount *mp, ino_t i
 		buf = kmem_alloc(len, KM_SLEEP);
 		err = chfs_read_leb(chmp, chvc->v->nref_lnr, buf,
 		    CHFS_GET_OFS(chvc->v->nref_offset), len, &retlen);
-		if (err)
+		if (err) {
+			kmem_free(buf, len);
 			return err;
+		}
 		if (retlen != len) {
 			chfs_err("Error reading vnode: read: %zu insted of: %zu\n",
 			    len, retlen);
+			kmem_free(buf, len);
 			return EIO;
 		}
 		chfvn = (struct chfs_flash_vnode*)buf;

Index: src/sys/ufs/chfs/ebh.c
diff -u src/sys/ufs/chfs/ebh.c:1.3 src/sys/ufs/chfs/ebh.c:1.3.14.1
--- src/sys/ufs/chfs/ebh.c:1.3	Fri Aug 10 09:26:58 2012
+++ src/sys/ufs/chfs/ebh.c	Mon Sep  8 18:57:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ebh.c,v 1.3 2012/08/10 09:26:58 ttoth Exp $	*/
+/*	$NetBSD: ebh.c,v 1.3.14.1 2014/09/08 18:57:58 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -828,8 +828,10 @@ add_peb_to_free(struct chfs_ebh *ebh, in
 	peb->erase_cnt = ec;
 	peb->pebnr = pebnr;
 	result = RB_INSERT(peb_free_rbtree, &ebh->free, peb);
-	if (result)
+	if (result) {
+		kmem_free(peb, sizeof(struct chfs_peb));
 		return 1;
+	}
 
 	return 0;
 }
@@ -856,8 +858,10 @@ add_peb_to_in_use(struct chfs_ebh *ebh, 
 	peb->erase_cnt = ec;
 	peb->pebnr = pebnr;
 	result = RB_INSERT(peb_in_use_rbtree, &ebh->in_use, peb);
-	if (result)
+	if (result) {
+		kmem_free(peb, sizeof(struct chfs_peb));
 		return 1;
+	}
 
 	return 0;
 }

Reply via email to