Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP5:Update
lsvpd
vpdupdate-Use-locking-to-prevent-update-race.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File vpdupdate-Use-locking-to-prevent-update-race.patch of Package lsvpd
From 1a2bf23ef7e78d86f5bbad9af89c7b3004c1b145 Mon Sep 17 00:00:00 2001 From: Michal Suchanek <msuchanek@suse.de> Date: Mon, 20 Sep 2021 14:51:00 +0200 Subject: [PATCH] vpdupdate: Use locking to prevent update race. Patch-mainline: v1.7.14 Git-commit: 1a2bf23ef7e78d86f5bbad9af89c7b3004c1b145 There are udev rules that may run vpdupdate multiple times in parallel. With a number of processes reading/updating/archiving the database the readers may see an inconsistent state. Lock the database file during archival. Signed-off-by: Michal Suchanek <msuchanek@suse.de> --- src/internal/updater.cpp | 52 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/internal/updater.cpp b/src/internal/updater.cpp index 391a6e6..d509cce 100644 --- a/src/internal/updater.cpp +++ b/src/internal/updater.cpp @@ -62,9 +62,9 @@ int storeComponents( System* root, VpdDbEnv& db ); int storeComponents( Component* root, VpdDbEnv& db ); void printUsage( ); void printVersion( ); -int ensureEnv( const string& env ); +int ensureEnv( const string& env, const string& file ); void archiveDB( const string& fullPath ); -int __lsvpdInit(string env, string file); +int __lsvpdInit( VpdDbEnv::UpdateLock *lock ); void __lsvpdFini(void); void lsvpdSighandler(int sig); @@ -74,6 +74,7 @@ const string BASE( "/sys/bus" ); bool isRoot(void); VpdDbEnv *db; +VpdDbEnv::UpdateLock *dblock; string env = DB_DIR, file = DB_FILENAME; @@ -83,6 +84,7 @@ int main( int argc, char** argv ) bool done = false; int index = 0, rc = 1; bool limitSCSISize = false; + VpdDbEnv::UpdateLock *lock; string platform = PlatformCollector::get_platform_name(); switch (PlatformCollector::platform_type) { @@ -127,7 +129,9 @@ int main( int argc, char** argv ) return 0; case 'a': + lock = new VpdDbEnv::UpdateLock(env, file, false); archiveDB( env + '/' + file ); + delete lock; return 0; case -1: @@ -151,12 +155,9 @@ int main( int argc, char** argv ) l.log( "vpdupdate: Constructing full devices database", LOG_NOTICE ); rc = initializeDB( limitSCSISize ); - if (rc) { - __lsvpdFini(); - return rc; - } __lsvpdFini(); + return rc; } bool isRoot() @@ -325,23 +326,28 @@ ZDONE:; */ int initializeDB( bool limitSCSI ) { + VpdDbEnv::UpdateLock *lock; System * root; int ret; - if( ensureEnv( env ) != 0 ) + if( ensureEnv( env, file ) != 0 ) return -1; string fullPath = env + "/" + file; + lock = new VpdDbEnv::UpdateLock(env, file, false); removeOldArchiveDB( ); archiveDB( fullPath ); + /* The db is now archived so when signal handler runs it should remove + * any db it finds */ + dblock = lock; Gatherer info( limitSCSI ); - ret = __lsvpdInit(env, file); + ret = __lsvpdInit(lock); if ( ret != 0 ) { Logger l; - l.log( " Could not allocate memory for the VPD database.", LOG_ERR); + l.log( "Could not allocate memory for the VPD database.", LOG_ERR); return ret; } @@ -358,11 +364,10 @@ int initializeDB( bool limitSCSI ) { Logger l; l.log( "Saving components to database failed.", LOG_ERR ); - return ret; } delete root; - return 0; + return ret; } /** @@ -409,7 +414,7 @@ int storeComponents( System* root, VpdDbEnv& db ) return 0; } -int ensureEnv( const string& env ) +int ensureEnv( const string& env, const string& file ) { struct stat info; int ret = -1; @@ -418,14 +423,14 @@ int ensureEnv( const string& env ) if( stat( env.c_str( ), &info ) == 0 ) { if (!S_ISDIR(info.st_mode & S_IFMT)) { - logger.log("/var/lib/lsvpd is not a directory\n", LOG_ERR); + logger.log(env + " is not a directory\n", LOG_ERR); return ret; } if ( ((info.st_mode & S_IRWXU) != S_IRWXU) || ((info.st_mode & S_IRGRP) != S_IRGRP) || ((info.st_mode & S_IROTH) != S_IROTH) ) { - logger.log("Failed to create vpd.db, no valid " + logger.log("Failed to create " + file + ", no valid " "permission\n", LOG_ERR); return ret; } @@ -438,7 +443,7 @@ int ensureEnv( const string& env ) return ret; } - if( ( ret = ensureEnv( env.substr( 0, idx ) ) ) != 0 ) + if( ( ret = ensureEnv( env.substr( 0, idx ) , env.substr( idx + 1 ) ) ) != 0 ) { return ret; } @@ -448,7 +453,7 @@ int ensureEnv( const string& env ) S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH ) != 0 ) { - logger.log( "Failed to create directory for vpd db.", LOG_ERR ); + logger.log( "Failed to create directory " + env + " for vpd db.", LOG_ERR ); return -1; } return ret; @@ -458,7 +463,7 @@ int ensureEnv( const string& env ) * @brief initializes data base access, sets up signal handling * to ensure proper cleanup if process if prematurely aborted */ -int __lsvpdInit(string env, string file) +int __lsvpdInit( VpdDbEnv::UpdateLock *lock ) { struct sigaction sigact; @@ -475,7 +480,7 @@ int __lsvpdInit(string env, string file) sigaction(SIGQUIT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); - db = new VpdDbEnv( env, file, false ); + db = new VpdDbEnv( *lock ); if ( db == NULL ) return -1; else @@ -491,6 +496,7 @@ void __lsvpdFini() if (db != NULL) { try { delete db; + dblock = NULL; } catch (VpdException & ve) { } } /* if */ @@ -499,7 +505,6 @@ void __lsvpdFini() void lsvpdSighandler(int sig) { - int fp; struct sigaction sigact; switch (sig) { @@ -516,12 +521,9 @@ void lsvpdSighandler(int sig) sigemptyset(&sigact.sa_mask); sigaction(sig, &sigact, NULL); - /* Remove temporary file */ - unlink((env + "/" + file).c_str()); - fp = open(env.c_str(), O_RDWR); - if (fp >= 0) { - fsync(fp); - close(fp); + if (dblock != NULL) { + /* Remove temporary file */ + unlink((env + "/" + file).c_str()); } __lsvpdFini(); -- 2.37.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor