1*4882a593SmuzhiyunFrom 89bdab965805e8d54d7f75349024e1a11cbe2eb8 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Paulo Flabiano Smorigo <pfsmorigo@canonical.com> 3*4882a593SmuzhiyunDate: Mon, 14 Dec 2020 18:54:49 -0300 4*4882a593SmuzhiyunSubject: [PATCH] zfs: Fix resource leaks while constructing path 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunThere are several exit points in dnode_get_path() that are causing possible 7*4882a593Smuzhiyunmemory leaks. 8*4882a593Smuzhiyun 9*4882a593SmuzhiyunIn the while(1) the correct exit mechanism should not be to do a direct return, 10*4882a593Smuzhiyunbut to instead break out of the loop, setting err first if it is not already set. 11*4882a593Smuzhiyun 12*4882a593SmuzhiyunThe reason behind this is that the dnode_path is a linked list, and while doing 13*4882a593Smuzhiyunthrough this loop, it is being allocated and built up - the only way to 14*4882a593Smuzhiyuncorrectly unravel it is to traverse it, which is what is being done at the end 15*4882a593Smuzhiyunof the function outside of the loop. 16*4882a593Smuzhiyun 17*4882a593SmuzhiyunSeveral of the existing exit points correctly did a break, but not all so this 18*4882a593Smuzhiyunchange makes that more consistent and should resolve the leaking of memory as 19*4882a593Smuzhiyunfound by Coverity. 20*4882a593Smuzhiyun 21*4882a593SmuzhiyunFixes: CID 73741 22*4882a593Smuzhiyun 23*4882a593SmuzhiyunSigned-off-by: Paulo Flabiano Smorigo <pfsmorigo@canonical.com> 24*4882a593SmuzhiyunSigned-off-by: Darren Kenny <darren.kenny@oracle.com> 25*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 26*4882a593SmuzhiyunSigned-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 27*4882a593Smuzhiyun--- 28*4882a593Smuzhiyun grub-core/fs/zfs/zfs.c | 30 +++++++++++++++++++++--------- 29*4882a593Smuzhiyun 1 file changed, 21 insertions(+), 9 deletions(-) 30*4882a593Smuzhiyun 31*4882a593Smuzhiyundiff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c 32*4882a593Smuzhiyunindex 0c42cba..9087a72 100644 33*4882a593Smuzhiyun--- a/grub-core/fs/zfs/zfs.c 34*4882a593Smuzhiyun+++ b/grub-core/fs/zfs/zfs.c 35*4882a593Smuzhiyun@@ -2836,8 +2836,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) 38*4882a593Smuzhiyun { 39*4882a593Smuzhiyun- grub_free (path_buf); 40*4882a593Smuzhiyun- return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); 41*4882a593Smuzhiyun+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); 42*4882a593Smuzhiyun+ break; 43*4882a593Smuzhiyun } 44*4882a593Smuzhiyun err = zap_lookup (&(dnode_path->dn), cname, &objnum, 45*4882a593Smuzhiyun data, subvol->case_insensitive); 46*4882a593Smuzhiyun@@ -2879,11 +2879,18 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, 47*4882a593Smuzhiyun << SPA_MINBLOCKSHIFT); 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun if (blksz == 0) 50*4882a593Smuzhiyun- return grub_error(GRUB_ERR_BAD_FS, "0-sized block"); 51*4882a593Smuzhiyun+ { 52*4882a593Smuzhiyun+ err = grub_error (GRUB_ERR_BAD_FS, "0-sized block"); 53*4882a593Smuzhiyun+ break; 54*4882a593Smuzhiyun+ } 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun sym_value = grub_malloc (sym_sz); 57*4882a593Smuzhiyun if (!sym_value) 58*4882a593Smuzhiyun- return grub_errno; 59*4882a593Smuzhiyun+ { 60*4882a593Smuzhiyun+ err = grub_errno; 61*4882a593Smuzhiyun+ break; 62*4882a593Smuzhiyun+ } 63*4882a593Smuzhiyun+ 64*4882a593Smuzhiyun for (block = 0; block < (sym_sz + blksz - 1) / blksz; block++) 65*4882a593Smuzhiyun { 66*4882a593Smuzhiyun void *t; 67*4882a593Smuzhiyun@@ -2893,7 +2900,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, 68*4882a593Smuzhiyun if (err) 69*4882a593Smuzhiyun { 70*4882a593Smuzhiyun grub_free (sym_value); 71*4882a593Smuzhiyun- return err; 72*4882a593Smuzhiyun+ break; 73*4882a593Smuzhiyun } 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun movesize = sym_sz - block * blksz; 76*4882a593Smuzhiyun@@ -2903,6 +2910,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, 77*4882a593Smuzhiyun grub_memcpy (sym_value + block * blksz, t, movesize); 78*4882a593Smuzhiyun grub_free (t); 79*4882a593Smuzhiyun } 80*4882a593Smuzhiyun+ if (err) 81*4882a593Smuzhiyun+ break; 82*4882a593Smuzhiyun free_symval = 1; 83*4882a593Smuzhiyun } 84*4882a593Smuzhiyun path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); 85*4882a593Smuzhiyun@@ -2911,7 +2920,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, 86*4882a593Smuzhiyun grub_free (oldpathbuf); 87*4882a593Smuzhiyun if (free_symval) 88*4882a593Smuzhiyun grub_free (sym_value); 89*4882a593Smuzhiyun- return grub_errno; 90*4882a593Smuzhiyun+ err = grub_errno; 91*4882a593Smuzhiyun+ break; 92*4882a593Smuzhiyun } 93*4882a593Smuzhiyun grub_memcpy (path, sym_value, sym_sz); 94*4882a593Smuzhiyun if (free_symval) 95*4882a593Smuzhiyun@@ -2949,11 +2959,12 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data); 98*4882a593Smuzhiyun if (err) 99*4882a593Smuzhiyun- return err; 100*4882a593Smuzhiyun+ break; 101*4882a593Smuzhiyun } 102*4882a593Smuzhiyun else 103*4882a593Smuzhiyun { 104*4882a593Smuzhiyun- return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); 105*4882a593Smuzhiyun+ err = grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); 106*4882a593Smuzhiyun+ break; 107*4882a593Smuzhiyun } 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); 110*4882a593Smuzhiyun@@ -2974,7 +2985,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, 111*4882a593Smuzhiyun if (!path_buf) 112*4882a593Smuzhiyun { 113*4882a593Smuzhiyun grub_free (oldpathbuf); 114*4882a593Smuzhiyun- return grub_errno; 115*4882a593Smuzhiyun+ err = grub_errno; 116*4882a593Smuzhiyun+ break; 117*4882a593Smuzhiyun } 118*4882a593Smuzhiyun grub_memcpy (path, sym_value, sym_sz); 119*4882a593Smuzhiyun path [sym_sz] = 0; 120*4882a593Smuzhiyun-- 121*4882a593Smuzhiyun2.14.2 122*4882a593Smuzhiyun 123