From d0dcc755d35dd3cd4e6f5781329962433417a521 Mon Sep 17 00:00:00 2001 From: Luke Gorrie Date: Thu, 29 Mar 2018 11:08:16 +0000 Subject: [PATCH] lj_audit.log.c: Add file size limit (default 100MB) Limit the auditlog to 100MB. This should be ample. Future changes should make this configurable. --- src/lib_jit.c | 3 ++- src/lj_auditlog.c | 69 ++++++++++++++++++++++++++++++++++------------- src/lj_auditlog.h | 2 +- 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/lib_jit.c b/src/lib_jit.c index bf04fd30ad..0e88f1523c 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c @@ -84,7 +84,8 @@ LJLIB_CF(jit_flush) LJLIB_CF(jit_auditlog) { if (L->base < L->top && tvisstr(L->base)) { - if (lj_auditlog_open(strdata(lj_lib_checkstr(L, 1)))) { + /* XXX Support auditlog file size argument. */ + if (lj_auditlog_open(strdata(lj_lib_checkstr(L, 1)), 0)) { return 0; } else { lj_err_caller(L, LJ_ERR_AUDITLOG); diff --git a/src/lj_auditlog.c b/src/lj_auditlog.c index d3c470d897..e213b12e08 100644 --- a/src/lj_auditlog.c +++ b/src/lj_auditlog.c @@ -12,39 +12,58 @@ /* Maximum data to buffer in memory before file is opened. */ #define MAX_MEM_BUFFER 1024*1024 /* State for initial in-memory stream. */ -char *membuffer; -size_t membuffersize; +static char *membuffer; +static size_t membuffersize; -FILE *fp; /* File where the audit log is written. */ -int error; /* Have we been unable to initialize the log? */ -int open; /* are we logging to a real file? */ +static FILE *fp; /* File where the audit log is written. */ +static int error; /* Have we been unable to initialize the log? */ +static int open; /* are we logging to a real file? */ +static size_t loggedbytes; /* Bytes already written to log. */ +static size_t sizelimit; /* File size when logging will stop. */ +#define DEFAULT_SIZE_LIMIT 100*1024*1024 /* Generous size limit. */ -/* -- msgpack writer - see http://msgpack.org/index.html ------------------ */ +/* -- byte counting file write wrappers ----------------------------------- */ + +static int cfputc(int c, FILE *f) { + loggedbytes++; + return fputc(c, f); +} + +static int cfputs(const char *s, FILE *f) { + loggedbytes += strlen(s); + return fputs(s, f); +} +static int cfwrite(const void *ptr, size_t size, size_t nmemb, FILE *f) { + loggedbytes += size * nmemb; + return fwrite(ptr, size, nmemb, f); +} + +/* -- msgpack writer - see http://msgpack.org/index.html ------------------ */ /* XXX assumes little endian cpu. */ static void fixmap(int size) { - fputc(0x80|size, fp); /* map header with size */ + cfputc(0x80|size, fp); /* map header with size */ }; static void str_16(const char *s) { uint16_t biglen = __builtin_bswap16(strlen(s)); - fputc(0xda, fp); /* string header */ - fwrite(&biglen, sizeof(biglen), 1, fp); /* string length */ - fputs(s, fp); /* string contents */ + cfputc(0xda, fp); /* string header */ + cfwrite(&biglen, sizeof(biglen), 1, fp); /* string length */ + cfputs(s, fp); /* string contents */ } static void uint_64(uint64_t n) { uint64_t big = __builtin_bswap64(n); - fputc(0xcf, fp); /* uint 64 header */ - fwrite(&big, sizeof(big), 1, fp); /* value */ + cfputc(0xcf, fp); /* uint 64 header */ + cfwrite(&big, sizeof(big), 1, fp); /* value */ } static void bin_32(void *ptr, int n) { uint32_t biglen = __builtin_bswap32(n); - fputc(0xc6, fp); /* array 32 header */ - fwrite(&biglen, sizeof(biglen), 1, fp); /* length */ - fwrite(ptr, n, 1, fp); /* data */ + cfputc(0xc6, fp); /* array 32 header */ + cfwrite(&biglen, sizeof(biglen), 1, fp); /* length */ + cfwrite(ptr, n, 1, fp); /* data */ } /* -- low-level object logging API ---------------------------------------- */ @@ -67,13 +86,25 @@ static void log_event(const char *type, int nattributes) { } /* Log objects that define the virtual machine. */ -void lj_auditlog_vm_definitions() +static void lj_auditlog_vm_definitions() { log_mem("lj_ir_mode", (void*)&lj_ir_mode, sizeof(lj_ir_mode)); } /* Check that the log is open before logging a message. */ static int ensure_log_started() { + if (fp != NULL) { + if (loggedbytes < sizelimit) { + return 1; + } else { + /* Log has grown to size limit. */ + log_event("auditlog_size_limit_reached", 0); + fclose(fp); + fp = NULL; + error = 1; + return 0; + } + } if (fp != NULL) return 1; /* Log already open? */ if (error) return 0; /* Log has already errored? */ /* Start logging into a memory buffer. The entries will be migrated @@ -83,6 +114,7 @@ static int ensure_log_started() { */ if ((fp = open_memstream(&membuffer, &membuffersize)) != NULL) { lj_auditlog_vm_definitions(); + sizelimit = MAX_MEM_BUFFER; return 1; } else { error = 1; @@ -95,10 +127,11 @@ static int ensure_log_started() { ** Can only open once. ** Return zero on failure. */ -int lj_auditlog_open(const char *path) +int lj_auditlog_open(const char *path, size_t maxsize) { FILE *newfp; - if (open) return 0; /* Sorry, already opened... */ + if (open || error) return 0; /* Sorry, too late... */ + sizelimit = maxsize ? maxsize : DEFAULT_SIZE_LIMIT; if (!ensure_log_started()) return 0; newfp = fopen(path, "wb+"); /* Migrate log entries from memory buffer. */ diff --git a/src/lj_auditlog.h b/src/lj_auditlog.h index 89abf4dd7f..a750d2e0b7 100644 --- a/src/lj_auditlog.h +++ b/src/lj_auditlog.h @@ -8,7 +8,7 @@ #include "lj_jit.h" #include "lj_trace.h" -int lj_auditlog_open(const char *path); +int lj_auditlog_open(const char *path, size_t maxsize); void lj_auditlog_new_prototype(GCproto *pt); void lj_auditlog_lex(const char *chunkname, const char *s, int sz);