Skip to content

Commit 23fef4c

Browse files
committed
Fix for rpmdb with SQLite3 backend
When the daemon is reloading the trustdb, and the rpmdb file is concurrently processed as an object, the file descriptor is closed at the end of evaluation. A close() on the SQLite database file causes the locks to be dropped. As a result, subsequent RPM installations can corrupt the RPM database when fapolicyd is running. Signed-off-by: Radovan Sroka <[email protected]>
1 parent 9df179e commit 23fef4c

File tree

4 files changed

+129
-1
lines changed

4 files changed

+129
-1
lines changed

configure.ac

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ AC_CHECK_LIB(lmdb, mdb_env_create, , [AC_MSG_ERROR([liblmdb not found])], -llmdb
177177

178178
LD_SO_PATH
179179

180+
if test x$use_rpm = xyes ; then
181+
RPMDB_PATH
182+
fi
183+
180184
AC_CONFIG_FILES([Makefile src/Makefile src/tests/Makefile init/Makefile doc/Makefile rules.d/Makefile])
181185
AC_OUTPUT
182186

m4/rpm_path.m4

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
AC_DEFUN([RPMDB_PATH],
2+
[
3+
xpath=`rpm --eval '%_dbpath'`
4+
echo "rpmdb path is.....$xpath"
5+
AC_DEFINE_UNQUOTED(RPM_DB_PATH, ["$xpath"], [rpmdb path])
6+
])

src/library/policy.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,10 +562,15 @@ static int test_info_api(int fd)
562562
}
563563
#endif
564564

565+
#ifdef USE_RPM
566+
int push_fd_to_buffer(int);
567+
extern volatile atomic_bool ongoing_rpm_operation;
568+
extern const char *rpm_dir_path;
569+
extern ssize_t rpm_dir_path_len;
570+
#endif
565571
void reply_event(int fd, const struct fanotify_event_metadata *metadata,
566572
unsigned reply, event_t *e)
567573
{
568-
close(metadata->fd);
569574
#ifdef FAN_AUDIT_RULE_NUM
570575
static int use_new = 2;
571576
if (use_new == 2)
@@ -604,6 +609,24 @@ void reply_event(int fd, const struct fanotify_event_metadata *metadata,
604609
response.fd = metadata->fd;
605610
response.response = reply;
606611
write(fd, &response, sizeof(struct fanotify_response));
612+
613+
#ifdef USE_RPM
614+
if (ongoing_rpm_operation) {
615+
616+
object_attr_t *obj;
617+
char *path = NULL;
618+
if (e && (obj = get_obj_attr(e, PATH))) {
619+
path = obj->o;
620+
}
621+
622+
if (path && !strncmp(path, rpm_dir_path, rpm_dir_path_len)) {
623+
if(push_fd_to_buffer(metadata->fd))
624+
close(metadata->fd);
625+
return; // no close for now
626+
}
627+
}
628+
#endif
629+
close(metadata->fd);
607630
}
608631

609632

src/library/rpm-backend.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323
*/
2424

2525
#include "config.h"
26+
#include <stdatomic.h>
2627
#include <stddef.h>
28+
#include <string.h>
2729
#include <sys/types.h>
30+
#include <sys/resource.h>
31+
#include <unistd.h>
2832
#include <rpm/rpmlib.h>
2933
#include <rpm/rpmts.h>
3034
#include <rpm/rpmmacro.h>
@@ -46,6 +50,8 @@ static int rpm_init_backend(void);
4650
static int rpm_load_list(const conf_t *);
4751
static int rpm_destroy_backend(void);
4852

53+
volatile atomic_bool ongoing_rpm_operation = 0;
54+
4955
backend rpm_backend =
5056
{
5157
"rpmdb",
@@ -56,6 +62,75 @@ backend rpm_backend =
5662
{ 0, 0, NULL },
5763
};
5864

65+
#ifdef RPM_DB_PATH
66+
const char *rpm_dir_path = RPM_DB_PATH;
67+
#else
68+
const char *rpm_dir_path = "/usr/lib/sysimage/rpm";
69+
#endif
70+
ssize_t rpm_dir_path_len = -1;
71+
72+
73+
static size_t fd_buffer_size = 0;
74+
static size_t fd_buffer_pos = 0;
75+
static int *fd_buffer = NULL;
76+
77+
#define MIN_BUFFER_SIZE 512
78+
static int init_fd_buffer(void) {
79+
struct rlimit limit;
80+
getrlimit(RLIMIT_NOFILE, &limit);
81+
82+
fd_buffer_size = limit.rlim_cur / 4;
83+
if (fd_buffer_size < MIN_BUFFER_SIZE)
84+
fd_buffer_size = MIN_BUFFER_SIZE;
85+
86+
fd_buffer = malloc(fd_buffer_size * sizeof(int));
87+
if (!fd_buffer)
88+
return 1;
89+
90+
for(size_t i = 0 ; i < fd_buffer_size; i++)
91+
fd_buffer[i] = -1;
92+
93+
msg(LOG_DEBUG, "FD buffer size set to: %ld", fd_buffer_size);
94+
return 0;
95+
}
96+
97+
int push_fd_to_buffer(int fd) {
98+
99+
if (!fd_buffer) {
100+
msg(LOG_ERR, "FD buffer already freed!");
101+
return 1;
102+
}
103+
if (fd_buffer_pos < fd_buffer_size) {
104+
msg(LOG_DEBUG, "Pushing to FD buffer(%ld), ocupancy: %ld", fd_buffer_size, fd_buffer_pos);
105+
fd_buffer[fd_buffer_pos++] = fd;
106+
return 0;
107+
}
108+
109+
msg(LOG_ERR, "FD buffer full");
110+
return 1;
111+
}
112+
113+
static void close_fds_in_buffer(void) {
114+
if (fd_buffer_pos)
115+
msg(LOG_DEBUG, "Closing FDs from buffer, size: %ld", fd_buffer_pos);
116+
for (size_t i = 0 ; i < fd_buffer_pos ; i++) {
117+
close(fd_buffer[i]);
118+
fd_buffer[i] = -1;
119+
}
120+
121+
fd_buffer_pos = 0;
122+
}
123+
124+
static void destroy_fd_buffer(void) {
125+
126+
if (!fd_buffer)
127+
return;
128+
129+
free(fd_buffer);
130+
fd_buffer = NULL;
131+
fd_buffer_size = -1;
132+
}
133+
59134
static rpmts ts = NULL;
60135
static rpmdbMatchIterator mi = NULL;
61136

@@ -196,6 +271,8 @@ static int rpm_load_list(const conf_t *conf)
196271
// hash table
197272
struct _hash_record *hashtable = NULL;
198273

274+
ongoing_rpm_operation = 1;
275+
199276
msg(LOG_INFO, "Loading rpmdb backend");
200277
if ((rc = init_rpm())) {
201278
msg(LOG_ERR, "init_rpm() failed (%d)", rc);
@@ -285,6 +362,9 @@ static int rpm_load_list(const conf_t *conf)
285362

286363
close_rpm();
287364

365+
ongoing_rpm_operation = 0;
366+
close_fds_in_buffer();
367+
288368
// cleaning up
289369
struct _hash_record *item, *tmp;
290370
HASH_ITER( hh, hashtable, item, tmp) {
@@ -298,6 +378,15 @@ static int rpm_load_list(const conf_t *conf)
298378

299379
static int rpm_init_backend(void)
300380
{
381+
if (rpm_dir_path_len == -1) {
382+
rpm_dir_path_len = strlen(rpm_dir_path);
383+
384+
if(init_fd_buffer()) {
385+
386+
return 1;
387+
}
388+
}
389+
301390
if (filter_init())
302391
return 1;
303392

@@ -312,9 +401,15 @@ static int rpm_init_backend(void)
312401
return 0;
313402
}
314403

404+
405+
extern volatile atomic_bool stop;
315406
static int rpm_destroy_backend(void)
316407
{
317408
filter_destroy();
318409
list_empty(&rpm_backend.list);
410+
// for sure
411+
close_fds_in_buffer();
412+
if (stop)
413+
destroy_fd_buffer();
319414
return 0;
320415
}

0 commit comments

Comments
 (0)