Skip to content

Commit

Permalink
Make fd_fgets thread safe
Browse files Browse the repository at this point in the history
  • Loading branch information
radosroka committed Apr 24, 2024
1 parent 04c1dc3 commit ca261be
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 49 deletions.
31 changes: 22 additions & 9 deletions src/cli/fapolicyd-cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,20 +603,26 @@ static int check_watch_fs(void)
return 1;
}

fd_fgets_context_t *fd_fgets_context = fd_fgets_init();
if (!fd_fgets_context)
return 1;

// Build the list of mount point types
list_init(&mnt);
do {
if (fd_fgets(buf, sizeof(buf), fd)) {
if (fd_fgets(fd_fgets_context, buf, sizeof(buf), fd)) {
sscanf(buf, "%1024s %4096s %31s %127s %d %d\n",
device,point, type, mntops, &fs_req, &fs_passno);
// Some file systems are not watchable
if (not_watchable(type))
continue;
list_append(&mnt, strdup(type), strdup("0"));
}
} while (!fd_fgets_eof());
} while (!fd_fgets_eof(fd_fgets_context));
fd_fgets_destroy(fd_fgets_context);
close(fd);


// Now search the list we just built
for (list_item_t *lptr = mnt.first; lptr; lptr = lptr->next) {
// See if the file system is watched
Expand Down Expand Up @@ -806,13 +812,18 @@ static int check_path(void)
static int do_status_report(void)
{
const char *reason = "no pid file";

fd_fgets_context_t *fd_fgets_context = fd_fgets_init();
if (!fd_fgets_context)
return 1;

// open pid file
int pidfd = open(pidfile, O_RDONLY);
if (pidfd >= 0) {
char pid_buf[16];

// read contents
if (fd_fgets(pid_buf, sizeof(pid_buf), pidfd)) {
if (fd_fgets(fd_fgets_context, pid_buf, sizeof(pid_buf), pidfd)) {
int rpt_fd;
unsigned int pid, tries = 0;
char exe_buf[64];
Expand Down Expand Up @@ -862,22 +873,24 @@ static int do_status_report(void)
goto err_out;
}
}
fd_fgets_rewind(fd_fgets_context);
do {
char buf[80];
if (fd_fgets(buf, sizeof(buf), rpt_fd))
if (fd_fgets(fd_fgets_context, buf, sizeof(buf), rpt_fd))
write(1, buf, strlen(buf));
} while (!fd_fgets_eof());
} while (!fd_fgets_eof(fd_fgets_context));
close(rpt_fd);
} else
reason = "can't read pid file";
close(pidfd);
return 0;
}
err_out:
if (pidfd >= 0)
close(pidfd);
printf("Can't find fapolicyd: %s\n", reason);
return 1;
fd_fgets_destroy(fd_fgets_context);
if (pidfd >= 0)
close(pidfd);
printf("Can't find fapolicyd: %s\n", reason);
return 1;
}

int main(int argc, char * const argv[])
Expand Down
21 changes: 17 additions & 4 deletions src/daemon/fapolicyd.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,13 @@ static void handle_mounts(int fd)

// Rewind the descriptor
lseek(fd, 0, SEEK_SET);
fd_fgets_rewind();
fd_fgets_context_t * fd_fgets_ctx = fd_fgets_init();
if (!fd_fgets_ctx)
return;

mlist_mark_all_deleted(m);
do {
int rc = fd_fgets(buf, sizeof(buf), fd);
int rc = fd_fgets(fd_fgets_ctx, buf, sizeof(buf), fd);
// Get a line
if (rc > 0) {
// Parse it
Expand All @@ -391,8 +394,9 @@ static void handle_mounts(int fd)
}
} else if (rc < 0) // Some kind of error - stop
break;
} while (!fd_fgets_eof());
} while (!fd_fgets_eof(fd_fgets_ctx));

fd_fgets_destroy(fd_fgets_ctx);
// update marks
fanotify_update(m);
}
Expand Down Expand Up @@ -421,11 +425,15 @@ void do_stat_report(FILE *f, int shutdown)

int already_running(void)
{
fd_fgets_context_t * fd_fgets_context = fd_fgets_init();
if (!fd_fgets_context)
return 1;

int pidfd = open(pidfile, O_RDONLY);
if (pidfd >= 0) {
char pid_buf[16];

if (fd_fgets(pid_buf, sizeof(pid_buf), pidfd)) {
if (fd_fgets(fd_fgets_context, pid_buf, sizeof(pid_buf), pidfd)) {
int pid;
char exe_buf[80], my_path[80];

Expand Down Expand Up @@ -457,16 +465,21 @@ int already_running(void)
if (pid != getpid())
goto err_out;
good:
fd_fgets_destroy(fd_fgets_context);
close(pidfd);
unlink(pidfile);
return 0;
} else
msg(LOG_ERR, "fapolicyd pid file found but unreadable");
err_out: // At this point, we have a pid file, let's just assume it's alive
// because if 2 are running, it deadlocks the machine

fd_fgets_destroy(fd_fgets_context);
close(pidfd);
return 1;
}

fd_fgets_destroy(fd_fgets_context);
return 0; // pid file doesn't exist, we're good to go
}

Expand Down
8 changes: 5 additions & 3 deletions src/library/database.c
Original file line number Diff line number Diff line change
Expand Up @@ -1315,9 +1315,10 @@ static void *update_thread_main(void *arg)
} else {
if (ffd[0].revents & POLLIN) {

fd_fgets_context_t * fd_fgets_context = fd_fgets_init();
do {
fd_fgets_rewind();
int res = fd_fgets(buff, sizeof(buff), ffd[0].fd);
fd_fgets_rewind(fd_fgets_context);
int res = fd_fgets(fd_fgets_context, buff, sizeof(buff), ffd[0].fd);

// nothing to read
if (res == -1)
Expand Down Expand Up @@ -1390,7 +1391,8 @@ static void *update_thread_main(void *arg)
}
}

} while(!fd_fgets_eof());
} while(!fd_fgets_eof(fd_fgets_context));
fd_fgets_destroy(fd_fgets_context);
}
}
}
Expand Down
72 changes: 43 additions & 29 deletions src/library/fd-fgets.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,73 +23,87 @@
#include "config.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "fd-fgets.h"

#define BUF_SIZE 8192
static char buffer[2*BUF_SIZE+1] = { 0 };
static char *current = buffer;
static const char *eptr = buffer+(2*BUF_SIZE);
static int eof = 0;

int fd_fgets_eof(void)
fd_fgets_context_t * fd_fgets_init(void)
{
return eof;
fd_fgets_context_t *ctx = malloc(sizeof(fd_fgets_context_t));
if (!ctx)
return NULL;

memset(ctx->buffer, 0, sizeof(ctx->buffer));
ctx->current = ctx->buffer;
ctx->eptr = ctx->buffer+(2*FD_FGETS_BUF_SIZE);
ctx->eof = 0;
return ctx;
}

void fd_fgets_destroy(fd_fgets_context_t *ctx)
{
free(ctx);
}

int fd_fgets_eof(fd_fgets_context_t *ctx)
{
return ctx->eof;
}

void fd_fgets_rewind(void)
void fd_fgets_rewind(fd_fgets_context_t *ctx)
{
eof = 0;
ctx->eof = 0;
}

int fd_fgets(char *buf, size_t blen, int fd)
int fd_fgets(fd_fgets_context_t *ctx, char *buf, size_t blen, int fd)
{
int complete = 0;
size_t line_len = 0;
char *line_end = NULL;

assert(blen != 0);
/* See if we have more in the buffer first */
if (current != buffer) {
line_end = strchr(buffer, '\n');
if (line_end == NULL && (size_t)(current - buffer) >= blen-1)
line_end = current-1; //enough to fill blen,point to end
if (ctx->current != ctx->buffer) {
line_end = strchr(ctx->buffer, '\n');
if (line_end == NULL && (size_t)(ctx->current - ctx->buffer) >= blen-1)
line_end = ctx->current-1; //enough to fill blen,point to end
}

/* Otherwise get some new bytes */
if (line_end == NULL && current != eptr && !eof) {
if (line_end == NULL && ctx->current != ctx->eptr && !ctx->eof) {
ssize_t len;

/* Use current since we may be adding more */
do {
len = read(fd, current, eptr - current);
len = read(fd, ctx->current, ctx->eptr - ctx->current);
} while (len < 0 && errno == EINTR);
if (len < 0)
return -1;
if (len == 0)
eof = 1;
ctx->eof = 1;
else
current[len] = 0;
current += len;
ctx->current[len] = 0;
ctx->current += len;

/* Start from beginning to see if we have one */
line_end = strchr(buffer, '\n');
line_end = strchr(ctx->buffer, '\n');
}

/* See what we have */
if (line_end) {
/* Include the last character (usually newline) */
line_len = (line_end+1) - buffer;
line_len = (line_end+1) - ctx->buffer;
/* Make sure we are within the right size */
if (line_len > blen-1)
line_len = blen-1;
complete = 1;
} else if (current == eptr) {
} else if (ctx->current == ctx->eptr) {
/* We are full but no newline */
line_len = blen-1;
complete = 1;
} else if (current >= buffer+blen-1) {
} else if (ctx->current >= ctx->buffer+blen-1) {
/* Not completely full, no newline, but enough to fill buf */
line_len = blen-1;
complete = 1;
Expand All @@ -98,18 +112,18 @@ int fd_fgets(char *buf, size_t blen, int fd)
size_t remainder_len;

/* Move to external buf and terminate it */
memcpy(buf, buffer, line_len);
memcpy(buf, ctx->buffer, line_len);
buf[line_len] = 0;
remainder_len = current - (buffer + line_len);
remainder_len = ctx->current - (ctx->buffer + line_len);
if (remainder_len > 0) {
/* We have a few leftover bytes to move */
memmove(buffer, buffer+line_len, remainder_len);
current = buffer+remainder_len;
memmove(ctx->buffer, ctx->buffer+line_len, remainder_len);
ctx->current = ctx->buffer+remainder_len;
} else {
/* Got the whole thing, just reset */
current = buffer;
ctx->current = ctx->buffer;
}
*current = 0;
*(ctx->current) = 0;
}
return complete;
}
21 changes: 17 additions & 4 deletions src/library/fd-fgets.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,23 @@
# define __attr_access(x)
#endif

int fd_fgets_eof(void);
void fd_fgets_rewind(void);
int fd_fgets(char *buf, size_t blen, int fd)
__attr_access ((__write_only__, 1, 2));
#ifndef FD_FGETS_BUF_SIZE
# define FD_FGETS_BUF_SIZE 8192
#endif

typedef struct fd_fgets_context {
char buffer[2*FD_FGETS_BUF_SIZE+1];
char *current;
char *eptr;
int eof;
} fd_fgets_context_t;

fd_fgets_context_t * fd_fgets_init(void);
void fd_fgets_destroy(fd_fgets_context_t *ctx);
int fd_fgets_eof(fd_fgets_context_t *ctx);
void fd_fgets_rewind(fd_fgets_context_t *ctx);
int fd_fgets(fd_fgets_context_t *ctx, char *buf, size_t blen, int fd);
// __attr_access ((__write_only__, 1, 2));

#endif

0 comments on commit ca261be

Please sign in to comment.