diff --git a/configure.ac b/configure.ac index 7279dc78..d0b99f19 100644 --- a/configure.ac +++ b/configure.ac @@ -177,6 +177,10 @@ AC_CHECK_LIB(lmdb, mdb_env_create, , [AC_MSG_ERROR([liblmdb not found])], -llmdb LD_SO_PATH +if test x$use_rpm = xyes ; then +RPMDB_PATH +fi + AC_CONFIG_FILES([Makefile src/Makefile src/tests/Makefile init/Makefile doc/Makefile rules.d/Makefile]) AC_OUTPUT diff --git a/m4/rpm_path.m4 b/m4/rpm_path.m4 new file mode 100644 index 00000000..3ff46625 --- /dev/null +++ b/m4/rpm_path.m4 @@ -0,0 +1,6 @@ +AC_DEFUN([RPMDB_PATH], +[ + xpath=`rpm --eval '%_dbpath'` + echo "rpmdb path is.....$xpath" + AC_DEFINE_UNQUOTED(RPM_DB_PATH, ["$xpath"], [rpmdb path]) +]) diff --git a/src/library/policy.c b/src/library/policy.c index 09433c26..a3515611 100644 --- a/src/library/policy.c +++ b/src/library/policy.c @@ -562,10 +562,15 @@ static int test_info_api(int fd) } #endif +#ifdef USE_RPM +int push_fd_to_buffer(int); +extern volatile atomic_bool ongoing_rpm_operation; +extern const char *rpm_dir_path; +extern ssize_t rpm_dir_path_len; +#endif void reply_event(int fd, const struct fanotify_event_metadata *metadata, unsigned reply, event_t *e) { - close(metadata->fd); #ifdef FAN_AUDIT_RULE_NUM static int use_new = 2; if (use_new == 2) @@ -604,6 +609,24 @@ void reply_event(int fd, const struct fanotify_event_metadata *metadata, response.fd = metadata->fd; response.response = reply; write(fd, &response, sizeof(struct fanotify_response)); + +#ifdef USE_RPM + if (ongoing_rpm_operation) { + + object_attr_t *obj; + char *path = NULL; + if (e && (obj = get_obj_attr(e, PATH))) { + path = obj->o; + } + + if (path && !strncmp(path, rpm_dir_path, rpm_dir_path_len)) { + if(push_fd_to_buffer(metadata->fd)) + close(metadata->fd); + return; // no close for now + } + } +#endif + close(metadata->fd); } diff --git a/src/library/rpm-backend.c b/src/library/rpm-backend.c index 86e6da5d..be2584f9 100644 --- a/src/library/rpm-backend.c +++ b/src/library/rpm-backend.c @@ -23,8 +23,12 @@ */ #include "config.h" +#include #include +#include #include +#include +#include #include #include #include @@ -46,6 +50,8 @@ static int rpm_init_backend(void); static int rpm_load_list(const conf_t *); static int rpm_destroy_backend(void); +volatile atomic_bool ongoing_rpm_operation = 0; + backend rpm_backend = { "rpmdb", @@ -56,6 +62,75 @@ backend rpm_backend = { 0, 0, NULL }, }; +#ifdef RPM_DB_PATH +const char *rpm_dir_path = RPM_DB_PATH; +#else +const char *rpm_dir_path = "/usr/lib/sysimage/rpm"; +#endif +ssize_t rpm_dir_path_len = -1; + + +static size_t fd_buffer_size = 0; +static size_t fd_buffer_pos = 0; +static int *fd_buffer = NULL; + +#define MIN_BUFFER_SIZE 512 +static int init_fd_buffer(void) { + struct rlimit limit; + getrlimit(RLIMIT_NOFILE, &limit); + + fd_buffer_size = limit.rlim_cur / 4; + if (fd_buffer_size < MIN_BUFFER_SIZE) + fd_buffer_size = MIN_BUFFER_SIZE; + + fd_buffer = malloc(fd_buffer_size * sizeof(int)); + if (!fd_buffer) + return 1; + + for(size_t i = 0 ; i < fd_buffer_size; i++) + fd_buffer[i] = -1; + + msg(LOG_DEBUG, "FD buffer size set to: %ld", fd_buffer_size); + return 0; +} + +int push_fd_to_buffer(int fd) { + + if (!fd_buffer) { + msg(LOG_ERR, "FD buffer already freed!"); + return 1; + } + if (fd_buffer_pos < fd_buffer_size) { + msg(LOG_DEBUG, "Pushing to FD buffer(%ld), ocupancy: %ld", fd_buffer_size, fd_buffer_pos); + fd_buffer[fd_buffer_pos++] = fd; + return 0; + } + + msg(LOG_ERR, "FD buffer full"); + return 1; +} + +static void close_fds_in_buffer(void) { + if (fd_buffer_pos) + msg(LOG_DEBUG, "Closing FDs from buffer, size: %ld", fd_buffer_pos); + for (size_t i = 0 ; i < fd_buffer_pos ; i++) { + close(fd_buffer[i]); + fd_buffer[i] = -1; + } + + fd_buffer_pos = 0; +} + +static void destroy_fd_buffer(void) { + + if (!fd_buffer) + return; + + free(fd_buffer); + fd_buffer = NULL; + fd_buffer_size = -1; +} + static rpmts ts = NULL; static rpmdbMatchIterator mi = NULL; @@ -196,6 +271,8 @@ static int rpm_load_list(const conf_t *conf) // hash table struct _hash_record *hashtable = NULL; + ongoing_rpm_operation = 1; + msg(LOG_INFO, "Loading rpmdb backend"); if ((rc = init_rpm())) { msg(LOG_ERR, "init_rpm() failed (%d)", rc); @@ -285,6 +362,9 @@ static int rpm_load_list(const conf_t *conf) close_rpm(); + ongoing_rpm_operation = 0; + close_fds_in_buffer(); + // cleaning up struct _hash_record *item, *tmp; HASH_ITER( hh, hashtable, item, tmp) { @@ -298,6 +378,15 @@ static int rpm_load_list(const conf_t *conf) static int rpm_init_backend(void) { + if (rpm_dir_path_len == -1) { + rpm_dir_path_len = strlen(rpm_dir_path); + + if(init_fd_buffer()) { + + return 1; + } + } + if (filter_init()) return 1; @@ -312,9 +401,15 @@ static int rpm_init_backend(void) return 0; } + +extern volatile atomic_bool stop; static int rpm_destroy_backend(void) { filter_destroy(); list_empty(&rpm_backend.list); + // for sure + close_fds_in_buffer(); + if (stop) + destroy_fd_buffer(); return 0; }