mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 10:38:20 +00:00
ScannedFile: Identify already scanned files by device and inode
Zeek scripts located on separate filesystems, but sharing the same inode number leads to scripts not being loaded. The reason is that a `ScannedFile` is only identified by `st_ino` which is not enough to uniquely identify a file in a system. This problem may be hit when `ZEEKPATH` points to separate filesystems and two script files happen have the same `st_ino` value - definitely not very likely, but possibly very confusing when it happens. The following test case creates two zeek scripts on separate filesystems. As the filesystems are freshly created and of the same type, the files will (tested a few times with xfs/ext4) have the same `st_ino` values. #!/bin/bash ZEEKDIR=${ZEEKDIR:-/home/awelzel/projects/zeek} export ZEEKPATH=.:${ZEEKDIR}/build/scripts:${ZEEKDIR}/scripts cat << EOF > hello.zeek event zeek_init() { print("Hello, once or twice?"); } EOF for i in 1 2 ; do dd if=/dev/urandom of=img${i} count=16 bs=1M 2>/dev/null sudo mkfs.xfs -q ./img${i} mkdir -p mount${i} sudo mount ./img${i} ./mount${i} sudo cp hello.zeek ./mount${i}/hello.zeek done ls ./mount*/*zeek stat -c "%n: device=%d inode=%i" ./mount*/hello.zeek ${ZEEKDIR}/build/src/zeek -b ./mount1/hello.zeek ./mount2/hello.zeek # Cleanup for i in 1 2 ; do sudo umount ./mount${i} rm -rfv ./img${i} ./mount${i} rm -rfv hello.zeek done Before this patch, `Hello, once or twice?` is printed only once, afterwards twice: $ sh testcase.sh [sudo] password for awelzel: ./mount1/hello.zeek ./mount2/hello.zeek ./mount1/hello.zeek: device=1794 inode=6915 ./mount2/hello.zeek: device=1795 inode=6915 Hello, once or twice? Hello, once or twice?
This commit is contained in:
parent
48fba11c51
commit
4b4595f5db
2 changed files with 19 additions and 19 deletions
10
src/Net.h
10
src/Net.h
|
@ -88,18 +88,20 @@ extern iosource::IOSource* current_iosrc;
|
||||||
extern iosource::PktDumper* pkt_dumper; // where to save packets
|
extern iosource::PktDumper* pkt_dumper; // where to save packets
|
||||||
|
|
||||||
// Script file we have already scanned (or are in the process of scanning).
|
// Script file we have already scanned (or are in the process of scanning).
|
||||||
// They are identified by inode number.
|
// They are identified by device and inode number.
|
||||||
struct ScannedFile {
|
struct ScannedFile {
|
||||||
|
dev_t dev;
|
||||||
ino_t inode;
|
ino_t inode;
|
||||||
int include_level;
|
int include_level;
|
||||||
string name;
|
string name;
|
||||||
bool skipped; // This ScannedFile was @unload'd.
|
bool skipped; // This ScannedFile was @unload'd.
|
||||||
bool prefixes_checked; // If loading prefixes for this file has been tried.
|
bool prefixes_checked; // If loading prefixes for this file has been tried.
|
||||||
|
|
||||||
ScannedFile(ino_t arg_inode, int arg_include_level, const string& arg_name,
|
ScannedFile(dev_t arg_dev, ino_t arg_inode, int arg_include_level,
|
||||||
bool arg_skipped = false,
|
const string& arg_name, bool arg_skipped = false,
|
||||||
bool arg_prefixes_checked = false)
|
bool arg_prefixes_checked = false)
|
||||||
: inode(arg_inode), include_level(arg_include_level),
|
: dev(arg_dev), inode(arg_inode),
|
||||||
|
include_level(arg_include_level),
|
||||||
name(arg_name), skipped(arg_skipped),
|
name(arg_name), skipped(arg_skipped),
|
||||||
prefixes_checked(arg_prefixes_checked)
|
prefixes_checked(arg_prefixes_checked)
|
||||||
{ }
|
{ }
|
||||||
|
|
28
src/scan.l
28
src/scan.l
|
@ -91,7 +91,7 @@ static string find_relative_script_file(const string& filename)
|
||||||
return find_script_file(filename, bro_path());
|
return find_script_file(filename, bro_path());
|
||||||
}
|
}
|
||||||
|
|
||||||
static ino_t get_inode_num(FILE* f, const string& path)
|
static std::pair<dev_t, ino_t> get_inode(FILE* f, const string& path)
|
||||||
{
|
{
|
||||||
struct stat b;
|
struct stat b;
|
||||||
|
|
||||||
|
@ -99,20 +99,20 @@ static ino_t get_inode_num(FILE* f, const string& path)
|
||||||
reporter->FatalError("fstat of %s failed: %s\n", path.c_str(),
|
reporter->FatalError("fstat of %s failed: %s\n", path.c_str(),
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
||||||
return b.st_ino;
|
return std::pair<dev_t, ino_t>{b.st_dev, b.st_ino};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ino_t get_inode_num(const string& path)
|
static std::pair<dev_t, ino_t> get_inode(const string& path)
|
||||||
{
|
{
|
||||||
FILE* f = open_file(path);
|
FILE* f = open_file(path);
|
||||||
|
|
||||||
if ( ! f )
|
if ( ! f )
|
||||||
reporter->FatalError("failed to open %s\n", path.c_str());
|
reporter->FatalError("failed to open %s\n", path.c_str());
|
||||||
|
|
||||||
ino_t inum = get_inode_num(f, path);
|
auto inode = get_inode(f, path);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return inum;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileInfo {
|
class FileInfo {
|
||||||
|
@ -420,7 +420,8 @@ when return TOK_WHEN;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// All we have to do is pretend we've already scanned it.
|
// All we have to do is pretend we've already scanned it.
|
||||||
ScannedFile sf(get_inode_num(path), file_stack.length(), path, true);
|
auto i = get_inode(path);
|
||||||
|
ScannedFile sf(i.first, i.second, file_stack.length(), path, true);
|
||||||
files_scanned.push_back(sf);
|
files_scanned.push_back(sf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -587,13 +588,10 @@ YYLTYPE GetCurrentLocation()
|
||||||
return currloc;
|
return currloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool already_scanned(const std::pair<dev_t, ino_t>& i)
|
||||||
static bool already_scanned(ino_t i)
|
|
||||||
{
|
{
|
||||||
list<ScannedFile>::const_iterator it;
|
for ( auto it : files_scanned )
|
||||||
|
if ( it.dev == i.first && it.inode == i.second )
|
||||||
for ( it = files_scanned.begin(); it != files_scanned.end(); ++it )
|
|
||||||
if ( it->inode == i )
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -601,7 +599,7 @@ static bool already_scanned(ino_t i)
|
||||||
|
|
||||||
static bool already_scanned(const string& path)
|
static bool already_scanned(const string& path)
|
||||||
{
|
{
|
||||||
return already_scanned(get_inode_num(path));
|
return already_scanned(get_inode(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_files(const char* orig_file)
|
static int load_files(const char* orig_file)
|
||||||
|
@ -656,7 +654,7 @@ static int load_files(const char* orig_file)
|
||||||
reporter->FatalError("can't open %s", file_path.c_str());
|
reporter->FatalError("can't open %s", file_path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ino_t i = get_inode_num(f, file_path);
|
auto i = get_inode(f, file_path);
|
||||||
|
|
||||||
if ( already_scanned(i) )
|
if ( already_scanned(i) )
|
||||||
{
|
{
|
||||||
|
@ -666,7 +664,7 @@ static int load_files(const char* orig_file)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScannedFile sf(i, file_stack.length(), file_path);
|
ScannedFile sf(i.first, i.second, file_stack.length(), file_path);
|
||||||
files_scanned.push_back(sf);
|
files_scanned.push_back(sf);
|
||||||
|
|
||||||
if ( g_policy_debug && ! file_path.empty() )
|
if ( g_policy_debug && ! file_path.empty() )
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue