summaryrefslogtreecommitdiffstats
path: root/src/audit-error.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audit-error.c')
-rw-r--r--src/audit-error.c116
1 files changed, 101 insertions, 15 deletions
diff --git a/src/audit-error.c b/src/audit-error.c
index 2ece447..b1b0cd9 100644
--- a/src/audit-error.c
+++ b/src/audit-error.c
@@ -19,6 +19,9 @@ extern FILE *lt_audit_in;
static struct hsearch_data symbol_tab;
static int symbol_tab_init = 0;
+static int automated_symbols_find(struct lt_config_audit *cfg,
+ const char *name);
+
struct lt_error_sym* lt_error_sym_get(struct lt_config_shared *cfg,
const char *name)
{
@@ -118,6 +121,7 @@ static int install_sigsegv(struct lt_config_shared *cfg)
static __thread unsigned long automated_sym_cnt = 0;
int lt_error_sym_exit(struct lt_config_audit *cfg,
+ const char *symname,
struct lt_symbol *sym,
struct timeval *tv,
struct link_map *lr,
@@ -128,34 +132,41 @@ int lt_error_sym_exit(struct lt_config_audit *cfg,
struct lt_error_sym *esym;
struct lt_error_config *cfg_err = cfg->error_config;
int keep = 0;
+ int handle_sigsegv;
long ret;
- /* we're not interested in this symbol */
- if (!sym || !sym->error)
- return -1;
-
- esym = sym->error;
-
- PRINT_VERBOSE(cfg, 1, "symbol %s, call %lu, n %ld\n",
- sym->name, esym->call, cfg_err->n);
-
if (cfg_err->automated) {
struct lt_error_config_sym *cfg_sym;
+ if (!automated_symbols_find(cfg, symname))
+ return 0;
+
if (automated_sym_cnt >= cfg_err->sym_cnt)
return -1;
cfg_sym = &cfg_err->sym[automated_sym_cnt];
ret = cfg_sym->ret;
keep = cfg_sym->keep;
+ handle_sigsegv = cfg_sym->handle_sigsegv;
*info = automated_sym_cnt++;
} else {
+
+ /* we're not interested in this symbol */
+ if (!sym || !sym->error)
+ return -1;
+
+ esym = sym->error;
+
+ PRINT_VERBOSE(cfg, 1, "symbol %s, call %lu, n %ld\n",
+ sym->name, esym->call, cfg_err->n);
+
/* we are not interested in this call number */
if (esym->call++ != cfg_err->n)
return -1;
ret = esym->ret;
+ handle_sigsegv = esym->handle_sigsegv;
}
if (keep)
@@ -173,7 +184,7 @@ int lt_error_sym_exit(struct lt_config_audit *cfg,
/* and share some info about the sinner */
share_info(cfg, ret, keep, tv, lr, inregs);
- if (esym->handle_sigsegv && install_sigsegv(cfg->sh))
+ if (handle_sigsegv && install_sigsegv(cfg->sh))
PRINT_VERBOSE(cfg, 1, "failed to install SIGSEGV handler\n");
return 0;
@@ -241,6 +252,9 @@ int lt_error_init(struct lt_config_audit *cfg)
struct lt_error_config *cfg_err = cfg->error_config;
int sym_cnt = cfg_err->sym_cnt, i, ok = 1;
+ if (cfg_err->automated)
+ return 0;
+
lt_sh(cfg, error_sim) = 0;
for(i = 0; i < sym_cnt; i++) {
@@ -264,21 +278,89 @@ int lt_error_init(struct lt_config_audit *cfg)
return 0;
}
+static struct hsearch_data automated_symbol_tab;
+
+static int automated_symbols_find(struct lt_config_audit *cfg,
+ const char *name)
+{
+ ENTRY e, *ep;
+ int found;
+
+ e.key = (char*) name;
+ found = hsearch_r(e, FIND, &ep, &automated_symbol_tab);
+
+ PRINT_VERBOSE(cfg, 1, "found %d, name %s\n", found, name);
+
+ return found;
+}
+
+static int automated_symbols_init(struct lt_config_audit *cfg,
+ struct lt_error_config *cfg_err,
+ int fd)
+{
+ char *symbols, *name;
+ off_t off = lseek(fd, 0, SEEK_CUR);
+ off_t file_size = lseek(fd, 0, SEEK_END);
+ int size = (int) (file_size - off);
+
+ PRINT_VERBOSE(cfg, 1, "size %d\n", size);
+
+ symbols = malloc(size);
+ if (!symbols) {
+ perror("malloc failed");
+ return -1;
+ }
+
+ lseek(fd, off, SEEK_SET);
+ if (size != read(fd, symbols, size)) {
+ perror("read failed");
+ return -1;
+ }
+
+ if (!hcreate_r(SYMBOL_TAB_SIZE, &automated_symbol_tab)) {
+ perror("failed to create hash table");
+ return -1;
+ }
+
+ name = symbols;
+
+ while(1) {
+ ENTRY e, *ep;
+
+ e.key = symbols;
+ e.data = (void*) 1;
+
+ PRINT_VERBOSE(cfg, 1, "name %s\n", name);
+
+ if (!hsearch_r(e, ENTER, &ep, &automated_symbol_tab)) {
+ perror("hsearch_r failed");
+ break;
+ }
+
+ name += strlen(name) + 1;
+ if (name >= (symbols + size))
+ break;
+ }
+
+ PRINT_VERBOSE(cfg, 1, "done\n");
+ return 0;
+}
+
int lt_error_config_read(struct lt_config_audit *cfg, int fd)
{
int size;
struct lt_error_config *cfg_err, cfg_err_st;
+ ssize_t n;
- if (-1 == read(fd, &cfg_err_st, sizeof(cfg_err_st))) {
+ n = read(fd, &cfg_err_st, sizeof(cfg_err_st));
+ if (n != sizeof(cfg_err_st)) {
perror("read failed");
return -1;
}
size = cfg_err_st.sym_cnt * sizeof(struct lt_error_config_sym);
- if (size <= 0) {
- PRINT_VERBOSE(cfg, 1, "failed: no error symbols defined\n");
- return -1;
- }
+
+ PRINT_VERBOSE(cfg, 1, "symbols count %d\n", cfg_err_st.sym_cnt);
cfg_err = malloc(sizeof(*cfg_err) + size);
if (!cfg_err) {
@@ -293,6 +375,10 @@ int lt_error_config_read(struct lt_config_audit *cfg, int fd)
return -1;
}
+ if (cfg_err->automated &&
+ automated_symbols_init(cfg, cfg_err, fd))
+ return -1;
+
cfg->error_config = cfg_err;
return size + sizeof(cfg_err_st);