14#include <unordered_set>
27#include <zypp-core/base/InputStream>
34#undef ZYPP_BASE_LOGGER_LOGGROUP
35#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::misc"
54 using CacheEntry = std::pair<std::string, std::unordered_set<std::string>>;
62 struct FilterRunsInContainer
77 Type in_our_root(
const Pathname &path )
const {
79 const PathInfo procInfoStat( path );
82 if ( procInfoStat.error() )
return IGNORE;
85 if ( procInfoStat.nlink() == 0 )
90 if ( linkTarget.empty() )
return IGNORE;
94 if ( linkTarget.relative() )
return IGNORE;
97 const PathInfo linkStat( linkTarget );
100 if ( !linkStat.isExist() )
104 if ( linkStat.ino() != procInfoStat.ino())
108 if ( linkStat.dev() != procInfoStat.dev() )
120 bool operator()(
const pid_t pid )
const {
123 const Pathname pidDir = Pathname(
"/proc") /
asString(pid);
124 const Pathname exeFile = pidDir /
"exe";
126 auto res = in_our_root( exeFile );
128 return res == CONTAINER;
134 std::unordered_set<std::string> tested;
137 filesystem::dirForEach( pidDir /
"map_files", [
this, &tested, &res ](
const Pathname & dir_r,
const char *
const & name_r ){
140 constexpr bool contloop =
true;
141 constexpr bool stoploop =
false;
143 const Pathname entryName = dir_r / name_r;
147 if ( linkTarget.empty() || !tested.insert( linkTarget.asString() ).second )
return contloop;
150 const auto mappedFileType = in_our_root( entryName );
153 if ( mappedFileType > IGNORE ) {
154 res = mappedFileType;
164 return res == CONTAINER;
167 FilterRunsInContainer() {}
178 using target::rpm::librpmDb;
183 : _wasBlocked( librpmDb::isBlocked() )
184 {
if ( _wasBlocked ) librpmDb::unblockAccess(); }
185 TmpUnblock(
const TmpUnblock &) =
delete;
186 TmpUnblock(TmpUnblock &&) =
delete;
187 TmpUnblock &operator=(
const TmpUnblock &) =
delete;
188 TmpUnblock &operator=(TmpUnblock &&) =
delete;
191 librpmDb::blockAccess();
198 librpmDb::db_const_iterator it;
199 return( it.findPackage(
"lsof" ) && it->tag_edition() < Edition(
"4.90") && !it->tag_provides().count( Capability(
"backported-option-Ki") ) );
210 bool addDataIf(
const CacheEntry & cache_r, std::vector<std::string> *debMap =
nullptr );
211 void addCacheIf( CacheEntry & cache_r,
const std::string & line_r, std::vector<std::string> *debMap =
nullptr );
216 std::vector<CheckAccessDeleted::ProcInfo>
_data;
236 const auto & filelist( cache_r.second );
238 if ( filelist.empty() )
244 pinfo.
files.insert( pinfo.
files.begin(), filelist.begin(), filelist.end() );
246 const std::string & pline( cache_r.first );
247 std::string commandname;
248 std::ostringstream pLineStr;
249 for_( ch, pline.begin(), pline.end() )
254 pinfo.
pid = &*(ch+1);
256 pLineStr <<&*(ch)<<
'\0';
259 pinfo.
ppid = &*(ch+1);
261 pLineStr <<&*(ch)<<
'\0';
264 pinfo.
puid = &*(ch+1);
266 pLineStr <<&*(ch)<<
'\0';
269 pinfo.
login = &*(ch+1);
271 pLineStr <<&*(ch)<<
'\0';
275 commandname = &*(ch+1);
277 if (!_fromLsofFileMode)
280 pinfo.
command = std::move(commandname);
282 pLineStr <<
'c'<<pinfo.
command<<
'\0';
286 if ( *ch ==
'\n' )
break;
287 do { ++ch; }
while ( *ch !=
'\0' );
293 debMap->front() = pLineStr.str();
312 for_( ch, line_r.c_str(), ch+line_r.size() )
317 if ( *(ch+1) !=
'0' )
330 if ( *ch ==
'\n' )
break;
331 do { ++ch; }
while ( *ch !=
'\0' );
334 if ( !t || !f || !n )
337 if ( !( ( *t ==
'R' && *(t+1) ==
'E' && *(t+2) ==
'G' && *(t+3) ==
'\0' )
338 || ( *t ==
'D' && *(t+1) ==
'E' && *(t+2) ==
'L' && *(t+3) ==
'\0' ) ) )
341 if ( !( ( *f ==
'm' && *(f+1) ==
'e' && *(f+2) ==
'm' && *(f+3) ==
'\0' )
342 || ( *f ==
't' && *(f+1) ==
'x' && *(f+2) ==
't' && *(f+3) ==
'\0' )
343 || ( *f ==
'D' && *(f+1) ==
'E' && *(f+2) ==
'L' && *(f+3) ==
'\0' )
344 || ( *f ==
'l' && *(f+1) ==
't' && *(f+2) ==
'x' && *(f+3) ==
'\0' ) ) )
356 if ( *f ==
'm' || *f ==
'D' )
358 static const char * black[] = {
373 if ( debMap && cache_r.second.find(n) == cache_r.second.end() ) {
374 debMap->push_back(line_r);
376 cache_r.second.insert( n );
382 if ( doCheck_r )
check();
390 FILE *inFile = fopen( lsofOutput_r.
c_str(),
"r" );
405 std::map<pid_t,CacheEntry> cachemap;
410 FilterRunsInContainer runsInLXC;
411 MIL <<
"Silently scanning lsof output..." << endl;
413 for( std::string line = source.
receiveLine( 30 * 1000 ); ! line.empty(); line = source.
receiveLine( 30 * 1000 ) )
416 if ( line[0] ==
'p' )
420 if ( debugEnabled ) {
422 if ( pidMad.empty() )
423 debugMap[cachepid].push_back( line );
427 cachemap[cachepid].first.swap( line );
435 addCacheIf( cachemap[cachepid], line, debugEnabled ? &dbgMap :
nullptr);
443 static const char* argv[] = {
"lsof",
"-n",
"-FpcuLRftkn0",
"-K",
"i", NULL };
451 std::map<pid_t,CacheEntry> cachemap;
461 int ret = prog.
close();
478 std::ofstream debugFileOut;
479 bool debugEnabled =
false;
480 if ( !_debugFile.empty() ) {
481 debugFileOut.open( _debugFile.c_str() );
482 debugEnabled = debugFileOut.is_open();
484 if ( !debugEnabled ) {
485 ERR<<
"Unable to open debug file: "<<_debugFile<<endl;
490 for (
const auto &cached : in )
493 addDataIf( cached.second);
495 std::vector<std::string> *mapPtr =
nullptr;
497 auto dbgInfo = debugMap.find(cached.first);
498 if ( dbgInfo != debugMap.end() )
499 mapPtr = &(dbgInfo->second);
501 if( !addDataIf( cached.second, mapPtr ) )
504 for (
const std::string &dbgLine: dbgInfo->second ) {
505 debugFileOut.write( dbgLine.c_str(), dbgLine.length() );
550 static const str::regex rx(
"(0::|[0-9]+:name=systemd:)/system.slice/(.*/)?(.*).service(/.*)?$" );
554 [&](
int num_r,
const std::string& line_r )->
bool
585 if ( obj.
pid.empty() )
586 return str <<
"<NoProc>";
CheckAccessDeleted::Impl * clone() const
CheckAccessDeleted::size_type createProcInfo(const std::map< pid_t, CacheEntry > &in)
std::map< pid_t, std::vector< std::string > > debugMap
void addCacheIf(CacheEntry &cache_r, const std::string &line_r, std::vector< std::string > *debMap=nullptr)
Add file to cache if it refers to a deleted executable or library file:
std::map< pid_t, CacheEntry > filterInput(externalprogram::ExternalDataSource &source)
bool addDataIf(const CacheEntry &cache_r, std::vector< std::string > *debMap=nullptr)
Add cache to data if the process is accessing deleted files.
std::vector< CheckAccessDeleted::ProcInfo > _data
Check for running processes which access deleted executables or libraries.
size_type check(bool verbose_r=false)
Check for running processes which access deleted executables or libraries.
CheckAccessDeleted(bool doCheck_r=true)
Default ctor performs check immediately.
const_iterator end() const
std::ostream & operator<<(std::ostream &str, const CheckAccessDeleted &obj)
Stream output.
const_iterator begin() const
static std::string findService(pid_t pid_r)
Guess if pid was started by a systemd service script.
std::vector< ProcInfo >::const_iterator const_iterator
void setDebugOutputFile(const Pathname &filename_r)
Writes all filtered process entries that make it into the final set into a file specified by filename...
RWCOW_pointer< Impl > _pimpl
Base class for Exception.
void remember(const Exception &old_r)
Store an other Exception as history.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
int close() override
Wait for the progamm to complete.
bool kill()
Kill the program.
const std::string & execError() const
Some detail telling why the execution failed, if it failed.
Bidirectional stream to external data.
std::string receiveLine()
Read one line from the input stream.
const char * c_str() const
String representation.
bool empty() const
Test for an empty path.
Regular expression match result.
String related utilities and Regular expression matching.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
int simpleParseFile(std::istream &str_r, ParseFlags flags_r, function< bool(int, std::string)> consume_r)
Simple lineparser optionally trimming and skipping comments.
std::string numstring(char n, int w=0)
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
TInt strtonum(const C_Str &str)
Parsing numbers from string.
bool contains(const C_Str &str_r, const C_Str &val_r)
Locate substring case sensitive.
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & dumpRangeLine(std::ostream &str, TIterator begin, TIterator end)
Print range defined by iterators (single line style).
std::ostream & dumpRange(std::ostream &str, TIterator begin, TIterator end, const std::string &intro="{", const std::string &pfx="\n ", const std::string &sep="\n ", const std::string &sfx="\n", const std::string &extro="}")
Print range defined by iterators (multiline style).
std::string asString(const Patch::Category &obj)
Data about one running process accessing deleted files.
std::string service() const
Guess if command was started by a systemd service script.
std::string pid
process ID
std::string login
process login name
std::string puid
process user ID
std::string command
process command name
std::vector< std::string > files
list of deleted executables or libraries accessed
std::string ppid
parent process ID
Exchange LineWriter for the lifetime of this object.
#define arrayBegin(A)
Simple C-array iterator.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.