[gparted] Prevent crash in the LVM2 PV information cache (#160787)



commit 3fbdb8055f449d53834ed4a08b0dadd43b88f07c
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sat Feb 11 14:09:22 2012 +0000

    Prevent crash in the LVM2 PV information cache (#160787)
    
    GParted would crash if there were any embeded spaces in the output from
    the command used to query LVM2 PVs.  There aren't normally any embeded
    spaces, but they can occur in certain degrated situations.  For example
    if one of the PVs in a VG spanning two PVs is lost the PV is displayed
    as "unknown device" rather than its actual device name:
    
        # lvm pvs --nosuffix --units b --separator , -o pv_name,pv_free,vg_name,lv_name,lv_attr
          Couldn't find device with uuid DMEi8r-9Vvy-w0Ok-CSSn-oLmY-YrY3-1PBznz.
          PV,PFree,VG,LV,Attr
          /dev/sda11,2143289344,GParted-VG1,,
          unknown device,1619001344,GParted-VG1,lvol0,-wi---
          unknown device,1619001344,GParted-VG1,,
    
    This was loaded into the cache as:
    
        ["/dev/sda11,2143289344,GParted-VG1,,",
         "unknown",
         "device,1619001344,GParted-VG1,lvol0,-wi---",
         "unknown",
         "device,1619001344,GParted-VG1,,"]
    
    The crash would happen when trying to access the VG name or LV flags on
    a line without enough comma separated fields.
    
    Improve parsing of the output from "lvm pvs" so that lines are not split
    on embeded spaces.  Don't crash on lines without without enough comma
    separated fields.
    
    Bug #160787 - lvm support

 include/LVM2_PV_Info.h |    3 ++-
 src/LVM2_PV_Info.cc    |   38 ++++++++++++++++++++++++++++----------
 2 files changed, 30 insertions(+), 11 deletions(-)
---
diff --git a/include/LVM2_PV_Info.h b/include/LVM2_PV_Info.h
index c0039bb..45315da 100644
--- a/include/LVM2_PV_Info.h
+++ b/include/LVM2_PV_Info.h
@@ -46,7 +46,8 @@ private:
 	void initialize_if_required() ;
 	void set_command_found() ;
 	void load_lvm2_pv_info_cache() ;
-	Glib::ustring get_pv_attr( const Glib::ustring & path, unsigned int entry ) ;
+	Glib::ustring get_pv_attr_by_path( const Glib::ustring & path, unsigned int entry ) ;
+	Glib::ustring get_pv_attr_by_row( unsigned int row, unsigned int entry ) ;
 	static bool lvm2_pv_info_cache_initialized ;
 	static bool lvm_found ;
 	static std::vector<Glib::ustring> lvm2_pv_cache ;
diff --git a/src/LVM2_PV_Info.cc b/src/LVM2_PV_Info.cc
index 6497ad4..91e5cc7 100644
--- a/src/LVM2_PV_Info.cc
+++ b/src/LVM2_PV_Info.cc
@@ -83,7 +83,7 @@ bool LVM2_PV_Info::is_lvm2_pv_supported()
 Glib::ustring LVM2_PV_Info::get_vg_name( const Glib::ustring & path )
 {
 	initialize_if_required() ;
-	return get_pv_attr( path, PVATTR_VG_NAME ) ;
+	return get_pv_attr_by_path( path, PVATTR_VG_NAME ) ;
 }
 
 //Return number of free bytes in the PV, or -1 for error.
@@ -91,7 +91,7 @@ Byte_Value LVM2_PV_Info::get_free_bytes( const Glib::ustring & path )
 {
 	initialize_if_required() ;
 	Byte_Value free_bytes = -1 ;
-	Glib::ustring fb_str = get_pv_attr( path, PVATTR_PV_FREE ) ;
+	Glib::ustring fb_str = get_pv_attr_by_path( path, PVATTR_PV_FREE ) ;
 	if ( fb_str != "" )
 	{
 		gchar * suffix ;
@@ -107,7 +107,7 @@ Byte_Value LVM2_PV_Info::get_free_bytes( const Glib::ustring & path )
 bool LVM2_PV_Info::has_active_lvs( const Glib::ustring & path )
 {
 	initialize_if_required() ;
-	Glib::ustring vgname = get_pv_attr( path, PVATTR_VG_NAME ) ;
+	Glib::ustring vgname = get_pv_attr_by_path( path, PVATTR_VG_NAME ) ;
 	if ( vgname == "" )
 		//PV not yet included in any VG
 		return false ;
@@ -116,13 +116,13 @@ bool LVM2_PV_Info::has_active_lvs( const Glib::ustring & path )
 	{
 		std::vector<Glib::ustring> pv_attrs ;
 		Utils::split( lvm2_pv_cache [i], pv_attrs, "," ) ;
-		if ( vgname == pv_attrs [PVATTR_VG_NAME] )
+		if ( vgname == get_pv_attr_by_row( i, PVATTR_VG_NAME ) )
 		{
+			Glib::ustring lv_bits = get_pv_attr_by_row( i, PVATTR_LV_BITS ) ;
 			//5th "bit" is active status.  E.g.
 			//  "-wi---" inactive, "-wi-a-" active, ...
 			//  Treat any non-hyphen character as active.
-			if (    pv_attrs [PVATTR_LV_BITS] .length() >= 5
-			     && pv_attrs [PVATTR_LV_BITS] [4] != '-'     )
+			if ( lv_bits .length() >= 5 && lv_bits [4] != '-' )
 				//LV in VG is active
 				return true ;
 		}
@@ -173,7 +173,11 @@ void LVM2_PV_Info::load_lvm2_pv_info_cache()
 		if ( ! Utils::execute_command( cmd, output, error, true ) )
 		{
 			if ( output != "" )
-				Utils::tokenize( output, lvm2_pv_cache, " \n" ) ;
+			{
+				Utils::tokenize( output, lvm2_pv_cache, "\n" ) ;
+				for ( unsigned int i = 0 ; i < lvm2_pv_cache .size() ; i ++ )
+					lvm2_pv_cache [i] = Utils::trim( lvm2_pv_cache [i] ) ;
+			}
 		}
 		else
 		{
@@ -185,7 +189,7 @@ void LVM2_PV_Info::load_lvm2_pv_info_cache()
 			Glib::ustring temp ;
 			temp = _("An error occurred reading LVM2 configuration!") ;
 			temp += "\n" ;
-			temp += _("Some or all of the details may be missing or incorrect.") ;
+			temp += _("Some or all of the details might be missing or incorrect.") ;
 			temp += "\n" ;
 			temp += _("You should NOT modify any LVM2 PV partitions.") ;
 			temp += "\n" ;
@@ -197,13 +201,13 @@ void LVM2_PV_Info::load_lvm2_pv_info_cache()
 //Return PV's nth attribute.  Performs linear search of the cache and
 //  uses the first matching PV entry.  Attributes are numbered 0 upward
 //  using PV_ATTRIBUTE enumeration.
-Glib::ustring LVM2_PV_Info::get_pv_attr( const Glib::ustring & path, unsigned int entry )
+Glib::ustring LVM2_PV_Info::get_pv_attr_by_path( const Glib::ustring & path, unsigned int entry )
 {
 	for ( unsigned int i = 0 ; i < lvm2_pv_cache .size() ; i ++ )
 	{
 		std::vector<Glib::ustring> pv_attrs ;
 		Utils::split( lvm2_pv_cache [i], pv_attrs, "," ) ;
-		if ( path == pv_attrs [PVATTR_PV_NAME] )
+		if ( PVATTR_PV_NAME < pv_attrs .size() && path == pv_attrs [PVATTR_PV_NAME] )
 		{
 			if ( entry < pv_attrs .size() )
 				return pv_attrs [entry] ;
@@ -215,4 +219,18 @@ Glib::ustring LVM2_PV_Info::get_pv_attr( const Glib::ustring & path, unsigned in
 	return "" ;
 }
 
+//Return PV's nth attribute from specified cache row.  Row is numbered
+//  0 upwards and attributes are numbers numbered 0 upwards using
+//  PV_ATTRIBUTE enumeration.
+Glib::ustring LVM2_PV_Info::get_pv_attr_by_row( unsigned int row, unsigned int entry )
+{
+	if ( row >= lvm2_pv_cache .size() )
+		return "" ;
+	std::vector<Glib::ustring> pv_attrs ;
+	Utils::split( lvm2_pv_cache [row], pv_attrs, "," ) ;
+	if ( entry < pv_attrs .size() )
+		return pv_attrs [entry] ;
+	return "" ;
+}
+
 }//GParted



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]