Blame SOURCES/0406-zfs-Fix-resource-leaks-while-constructing-path.patch

9723a8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
9723a8
From: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>
9723a8
Date: Mon, 14 Dec 2020 18:54:49 -0300
9723a8
Subject: [PATCH] zfs: Fix resource leaks while constructing path
9723a8
9723a8
There are several exit points in dnode_get_path() that are causing possible
9723a8
memory leaks.
9723a8
9723a8
In the while(1) the correct exit mechanism should not be to do a direct return,
9723a8
but to instead break out of the loop, setting err first if it is not already set.
9723a8
9723a8
The reason behind this is that the dnode_path is a linked list, and while doing
9723a8
through this loop, it is being allocated and built up - the only way to
9723a8
correctly unravel it is to traverse it, which is what is being done at the end
9723a8
of the function outside of the loop.
9723a8
9723a8
Several of the existing exit points correctly did a break, but not all so this
9723a8
change makes that more consistent and should resolve the leaking of memory as
9723a8
found by Coverity.
9723a8
9723a8
Fixes: CID 73741
9723a8
9723a8
Signed-off-by: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>
9723a8
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
9723a8
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
9723a8
---
9723a8
 grub-core/fs/zfs/zfs.c | 30 +++++++++++++++++++++---------
9723a8
 1 file changed, 21 insertions(+), 9 deletions(-)
9723a8
9723a8
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
b71686
index 3dfde0807..44d8bde6b 100644
9723a8
--- a/grub-core/fs/zfs/zfs.c
9723a8
+++ b/grub-core/fs/zfs/zfs.c
9723a8
@@ -2836,8 +2836,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
9723a8
 
9723a8
       if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS)
9723a8
 	{
9723a8
-	  grub_free (path_buf);
9723a8
-	  return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
9723a8
+	  err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
9723a8
+	  break;
9723a8
 	}
9723a8
       err = zap_lookup (&(dnode_path->dn), cname, &objnum,
9723a8
 			data, subvol->case_insensitive);
9723a8
@@ -2879,11 +2879,18 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
9723a8
 		       << SPA_MINBLOCKSHIFT);
9723a8
 
9723a8
 	      if (blksz == 0)
9723a8
-		return grub_error(GRUB_ERR_BAD_FS, "0-sized block");
9723a8
+                {
9723a8
+                  err = grub_error (GRUB_ERR_BAD_FS, "0-sized block");
9723a8
+                  break;
9723a8
+                }
9723a8
 
9723a8
 	      sym_value = grub_malloc (sym_sz);
9723a8
 	      if (!sym_value)
9723a8
-		return grub_errno;
9723a8
+		{
9723a8
+		  err = grub_errno;
9723a8
+		  break;
9723a8
+		}
9723a8
+
9723a8
 	      for (block = 0; block < (sym_sz + blksz - 1) / blksz; block++)
9723a8
 		{
9723a8
 		  void *t;
9723a8
@@ -2893,7 +2900,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
9723a8
 		  if (err)
9723a8
 		    {
9723a8
 		      grub_free (sym_value);
9723a8
-		      return err;
9723a8
+		      break;
9723a8
 		    }
9723a8
 
9723a8
 		  movesize = sym_sz - block * blksz;
9723a8
@@ -2903,6 +2910,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
9723a8
 		  grub_memcpy (sym_value + block * blksz, t, movesize);
9723a8
 		  grub_free (t);
9723a8
 		}
9723a8
+		if (err)
9723a8
+		  break;
9723a8
 	      free_symval = 1;
9723a8
 	    }	    
9723a8
 	  path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
9723a8
@@ -2911,7 +2920,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
9723a8
 	      grub_free (oldpathbuf);
9723a8
 	      if (free_symval)
9723a8
 		grub_free (sym_value);
9723a8
-	      return grub_errno;
9723a8
+	      err = grub_errno;
9723a8
+	      break;
9723a8
 	    }
9723a8
 	  grub_memcpy (path, sym_value, sym_sz);
9723a8
 	  if (free_symval)
9723a8
@@ -2949,11 +2959,12 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
9723a8
 	      
9723a8
 	      err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data);
9723a8
 	      if (err)
9723a8
-		return err;
9723a8
+	        break;
9723a8
 	    }
9723a8
 	  else
9723a8
 	    {
9723a8
-	      return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
9723a8
+	      err = grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
9723a8
+	      break;
9723a8
 	    }
9723a8
 
9723a8
 	  hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
9723a8
@@ -2974,7 +2985,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
9723a8
 	      if (!path_buf)
9723a8
 		{
9723a8
 		  grub_free (oldpathbuf);
9723a8
-		  return grub_errno;
9723a8
+		  err = grub_errno;
9723a8
+		  break;
9723a8
 		}
9723a8
 	      grub_memcpy (path, sym_value, sym_sz);
9723a8
 	      path [sym_sz] = 0;