Автоматическое разрешение для текущего процесса

This commit is contained in:
Alexander Zhirov 2025-10-03 15:56:38 +03:00
parent 5bedfc20b9
commit 281c783066
Signed by: alexander
GPG key ID: C8D8BE544A27C511
4 changed files with 71 additions and 42 deletions

View file

@ -25,9 +25,6 @@
}, },
{ {
"path": "/etc" "path": "/etc"
},
{
"path": "/usr"
} }
] ]
} }

View file

@ -18,6 +18,7 @@ import core.stdc.stdlib : EXIT_SUCCESS, exit;
import std.array : array; import std.array : array;
import std.file : FileException, readLink, readText; import std.file : FileException, readLink, readText;
import std.format : format; import std.format : format;
import std.process : thisProcessID;
import std.stdio : writeln, writefln; import std.stdio : writeln, writefln;
@ -60,7 +61,7 @@ private {
writefln("⚠️ Файл имеет актуальное состояние снимка\n\t%s", session.filePathOpen); writefln("⚠️ Файл имеет актуальное состояние снимка\n\t%s", session.filePathOpen);
} }
} catch (Exception e) { } catch (Exception e) {
writeln(e.msg); writeln("❗️ ", e.msg);
} }
} }
); );
@ -91,6 +92,7 @@ private:
Session[DevIno] _gMap; Session[DevIno] _gMap;
Tid _tid; Tid _tid;
pollfd[1] _pds; pollfd[1] _pds;
int _pid;
// Для маркировки путей в fanotify // Для маркировки путей в fanotify
string[] _mountPoints; string[] _mountPoints;
@ -99,6 +101,7 @@ private:
public: public:
this(const DWConfig config, bool global) { this(const DWConfig config, bool global) {
_database = config.database; _database = config.database;
_pid = thisProcessID();
// _fanFD = fanotify_init(FAN_CLOEXEC | FAN_CLASS_PRE_CONTENT | FAN_REPORT_TID | FAN_UNLIMITED_QUEUE, // _fanFD = fanotify_init(FAN_CLOEXEC | FAN_CLASS_PRE_CONTENT | FAN_REPORT_TID | FAN_UNLIMITED_QUEUE,
// O_RDONLY | O_LARGEFILE | O_CLOEXEC); // O_RDONLY | O_LARGEFILE | O_CLOEXEC);
@ -156,8 +159,8 @@ public:
_mountPoints = tempMountPoints.array; _mountPoints = tempMountPoints.array;
_flags = FAN_MARK_ADD | FAN_MARK_FILESYSTEM; _flags = FAN_MARK_ADD | FAN_MARK_FILESYSTEM;
// _mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE; _mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE;
_mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE; // _mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE;
} }
// В обычном режиме монтируются конечные пути отслеживания из файла конфигурации // В обычном режиме монтируются конечные пути отслеживания из файла конфигурации
else { else {
@ -171,8 +174,8 @@ public:
} }
_flags = FAN_MARK_ADD | FAN_MARK_ONLYDIR; _flags = FAN_MARK_ADD | FAN_MARK_ONLYDIR;
// _mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE | FAN_EVENT_ON_CHILD; _mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE | FAN_EVENT_ON_CHILD;
_mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE | FAN_EVENT_ON_CHILD; // _mask = FAN_OPEN_PERM | FAN_CLOSE_WRITE | FAN_EVENT_ON_CHILD;
} }
} }
@ -180,7 +183,8 @@ public:
signal(SIGINT, &handleSignal); signal(SIGINT, &handleSignal);
signal(SIGTERM, &handleSignal); signal(SIGTERM, &handleSignal);
_tid = spawn(&worker, thisTid(), _database); writeln("⚙️ Текущий процесс: ", _pid);
_pds = [ pollfd(_fanFD, POLLIN, 0) ]; _pds = [ pollfd(_fanFD, POLLIN, 0) ];
// Маркировка путей сразу инициирует наполнение очереди событий, // Маркировка путей сразу инициирует наполнение очереди событий,
@ -192,8 +196,12 @@ public:
)) { )) {
throw new DWException(e.msg); throw new DWException(e.msg);
} }
writeln("❇️ Отслеживание добавлено на ", mountPoint);
} }
// Запуск дочернего потока с обработкой данных для создания снимков
_tid = spawn(&worker, thisTid(), _database);
// Основной цикл для чтения маркированных событий // Основной цикл для чтения маркированных событий
while (atomicLoad(gRunning)) { while (atomicLoad(gRunning)) {
auto rc = poll(_pds.ptr, 1, 100); auto rc = poll(_pds.ptr, 1, 100);
@ -211,54 +219,59 @@ public:
metadata.event_len <= remaining) metadata.event_len <= remaining)
{ {
if (metadata.mask & FAN_OPEN_PERM) { if (metadata.mask & FAN_OPEN_PERM) {
string typeFile = fromStringz(magic_descriptor(_magic, metadata.fd)); // Если текущий процесс демона - то пропустить обработку события
string link = "/proc/self/fd/%d".format(metadata.fd); if (metadata.pid != _pid) {
string path; string typeFile = fromStringz(magic_descriptor(_magic, metadata.fd));
collectException!FileException(path = link.readLink()); string link = "/proc/self/fd/%d".format(metadata.fd);
string path;
collectException!FileException(path = link.readLink());
if (typeFile == "binary") { if (typeFile == "binary") {
// writeln("⛔️ Бинарный файл пропускаем\n\t", path); writeln("⛔️ Бинарный файл пропускаем\n\t", path);
} else { } else {
string childPath; string childPath;
string[] rules; string[] rules;
foreach (Watch watch; _watch) { foreach (Watch watch; _watch) {
if (path.startsWith(watch.path)) { if (path.startsWith(watch.path)) {
childPath = path[watch.path.length .. $]; childPath = path[watch.path.length .. $];
rules = watch.rules; rules = watch.rules;
break; break;
}
} }
}
if (childPath.length > 0 && rules.shouldMatch(childPath)) { if (childPath.length > 0 && rules.shouldMatch(childPath)) {
// string link = "/proc/self/fd/%d".format(metadata.fd); // string link = "/proc/self/fd/%d".format(metadata.fd);
// string path; // string path;
// collectException!FileException(path = link.readLink()); // collectException!FileException(path = link.readLink());
DevIno key; DevIno key;
// Получение информации о процессе (паспорт процесса) // Получение информации о процессе (паспорт процесса)
// key как out объект, получение данных из функции // key как out объект, получение данных из функции
if (getDevIno(metadata.fd, key, metadata.pid)) { if (getDevIno(metadata.fd, key, metadata.pid)) {
if (key !in _gMap) { if (key !in _gMap) {
// Получение имени процесса // Получение имени процесса
auto procName = readProcComm(metadata.pid); auto procName = readProcComm(metadata.pid);
// Получение идентификаторов пользователя // Получение идентификаторов пользователя
auto ids = readProcIds(metadata.pid); auto ids = readProcIds(metadata.pid);
// Добавление текущей сессии (редактор + юзер + файл) в список для отслеживания // Добавление текущей сессии (редактор + юзер + файл) в список для отслеживания
_gMap[key] = Session(procName, ids.ruid, ids.uid, path); _gMap[key] = Session(procName, ids.ruid, ids.uid, path);
// writefln("📄 [%s] Добавлен новый файл для отслеживания:\n\t%s", typeFile, path); // writefln("📄 [%s] Добавлен новый файл для отслеживания:\n\t%s", typeFile, path);
writefln("📄 [%d] Файл добавлен в список для отслеживания:\n\t%s", _gMap.length, path);
}
} }
} }
} }
} }
// По умолчанию разрешить доступ всем событиям
FanotifyResponse response; FanotifyResponse response;
response.fd = metadata.fd; response.fd = metadata.fd;
response.response = FAN_ALLOW; response.response = FAN_ALLOW;
write(_fanFD, &response, response.sizeof); write(_fanFD, &response, response.sizeof);
} }
// if (metadata.mask & FAN_CLOSE_WRITE || metadata.mask & FAN_CLOSE_NOWRITE) { // Отправка данных для записи в БД
if (metadata.mask & FAN_CLOSE_WRITE) { if (metadata.mask & FAN_CLOSE_WRITE) {
DevIno key; DevIno key;
if (getDevIno(metadata.fd, key, metadata.pid)) { if (getDevIno(metadata.fd, key, metadata.pid)) {
@ -266,7 +279,19 @@ public:
ps.data = readAllFromFd(metadata.fd).dup; ps.data = readAllFromFd(metadata.fd).dup;
send(_tid, *ps); send(_tid, *ps);
_gMap.remove(key); _gMap.remove(key);
// writefln("✉️ Отправлен файл для создания снимка:\n\t%s", ps.filePathOpen); writefln("✉️ [%d] Файл передан для создания снимка:\n\t%s",
_gMap.length, ps.filePathOpen);
}
}
}
// Удаление всех ложных добавлений из карты отслеживания
if (metadata.mask & FAN_CLOSE_NOWRITE) {
DevIno key;
if (getDevIno(metadata.fd, key, metadata.pid)) {
if (Session* ps = key in _gMap) {
_gMap.remove(key);
writefln("🗑 [%d] Файл удален из списка для отслеживания:\n\t%s",
_gMap.length, ps.filePathOpen);
} }
} }
} }

View file

@ -12,15 +12,21 @@ enum FAN_UNLIMITED_QUEUE = 0x0000_0010; // неограниченная очер
enum FAN_NONBLOCK = 0x0000_0002; // неблокирующие read() enum FAN_NONBLOCK = 0x0000_0002; // неблокирующие read()
enum FAN_MARK_ADD = 0x0000_0001; // добавить/обновить метку enum FAN_MARK_ADD = 0x0000_0001; // добавить/обновить метку
enum FAN_MARK_REMOVE = 0x0000_0002; // удалить метку
enum FAN_MARK_MOUNT = 0x0000_0010; // навесить на точку монтирования enum FAN_MARK_MOUNT = 0x0000_0010; // навесить на точку монтирования
enum FAN_MARK_FILESYSTEM = 0x0000_0100; // навесить на всю ФС enum FAN_MARK_FILESYSTEM = 0x0000_0100; // навесить на всю ФС
enum FAN_MARK_ONLYDIR = 0x0000_0008; // path должен быть каталогом enum FAN_MARK_ONLYDIR = 0x0000_0008; // path должен быть каталогом
enum FAN_MARK_IGNORE = 0x0000_0400; // игнорировать (взаимоисключающе с IGNORED_MASK, новое)
enum FAN_MARK_IGNORED_SURV_MODIFY = 0x0000_0040; // игнор сохраняется при модификации
enum FAN_ACCESS_PERM = 0x0002_0000; // запрос на доступ к содержимому (исправлено имя/значение)
enum FAN_OPEN_EXEC_PERM = 0x0004_0000; // запрос на open(O_EXEC)
enum FAN_OPEN_PERM = 0x0001_0000; // запрос на open() (исправлено имя/значение) enum FAN_OPEN_PERM = 0x0001_0000; // запрос на open() (исправлено имя/значение)
enum FAN_CLOSE_WRITE = 0x0000_0008; // закрыт после записи enum FAN_CLOSE_WRITE = 0x0000_0008; // закрыт после записи
enum FAN_MODIFY = 0x0000_0002; // запись/изменение enum FAN_MODIFY = 0x0000_0002; // запись/изменение
enum FAN_CLOSE_NOWRITE = 0x0000_0010; // закрыт без записи enum FAN_CLOSE_NOWRITE = 0x0000_0010; // закрыт без записи
enum FAN_EVENT_ON_CHILD = 0x0800_0000; // события на дочерние объекты каталога enum FAN_EVENT_ON_CHILD = 0x0800_0000; // события на дочерние объекты каталога
enum FAN_ONDIR = 0x4000_0000; // событие относится к каталогу
int fanotify_init( int fanotify_init(
uint flags, // Битовая маска, определяющая класс уведомлений и другие поведения uint flags, // Битовая маска, определяющая класс уведомлений и другие поведения

1
test.md Normal file
View file

@ -0,0 +1 @@
sd