Fix #9015 - use after free when quitting main thread having background server threads

This commit is contained in:
pancake 2017-12-18 13:27:26 +01:00
parent ff8959f1b0
commit a8897b107d
5 changed files with 58 additions and 29 deletions

View File

@ -1842,10 +1842,11 @@ R_API RCore *r_core_fini(RCore *c) {
if (!c) {
return NULL;
}
r_core_wait (c);
/* TODO: it leaks as shit */
//update_sdb (c);
// avoid double free
r_core_free_autocomplete(c);
r_core_free_autocomplete (c);
R_FREE (c->lastsearch);
c->cons->pager = NULL;
r_core_task_join (c, NULL);
@ -1898,6 +1899,7 @@ R_API RCore *r_core_fini(RCore *c) {
}
R_API RCore *r_core_free(RCore *c) {
// must wait all threads first
if (c) {
r_core_fini (c);
free (c);
@ -2169,26 +2171,23 @@ static void rap_break (void *u) {
// TODO: PLEASE move into core/io/rap? */
// TODO: use static buffer instead of mallocs all the time. it's network!
R_API int r_core_serve(RCore *core, RIODesc *file) {
R_API bool r_core_serve(RCore *core, RIODesc *file) {
ut8 cmd, flg, *ptr = NULL, buf[1024];
RSocket *c, *fd;
int i, pipefd = -1;
RIORap *rior;
ut64 x;
rior = (RIORap *)file->data;
RIORap *rior = (RIORap *)file->data;
if (!rior|| !rior->fd) {
eprintf ("rap: cannot listen.\n");
return -1;
return false;
}
fd = rior->fd;
RSocket *fd = rior->fd;
eprintf ("RAP Server started (rap.loop=%s)\n",
r_config_get (core->config, "rap.loop"));
r_cons_break_push (rap_break, rior);
reaccept:
while (!r_cons_is_breaked ()) {
c = r_socket_accept (fd);
RSocket *c = r_socket_accept (fd);
if (!c) {
break;
}
@ -2222,15 +2221,14 @@ reaccept:
if (!ptr) {
eprintf ("Cannot malloc in rmt-open len = %d\n", cmd);
} else {
RCoreFile *file;
ut64 baddr = r_config_get_i (core->config, "bin.laddr");
r_socket_read_block (c, ptr, cmd); //filename
r_socket_read_block (c, ptr, cmd);
ptr[cmd] = 0;
ut32 perm = R_IO_READ;
if (flg & R_IO_WRITE) {
perm |= R_IO_WRITE;
}
file = r_core_file_open (core, (const char *)ptr, perm, 0);
RCoreFile *file = r_core_file_open (core, (const char *)ptr, perm, 0);
if (file) {
r_core_bin_load (core, NULL, baddr);
r_io_map_add (core->io, file->fd, perm, 0, 0, r_io_fd_size (core->io, file->fd), true);
@ -2414,7 +2412,7 @@ reaccept:
}
out_of_function:
r_cons_break_pop ();
return -1;
return false;
}
R_API int r_core_search_cb(RCore *core, ut64 from, ut64 to, RCoreSearchCallback cb) {

View File

@ -39,9 +39,17 @@ typedef struct {
typedef struct {
RCore *core;
const char* input;
char* input;
} RapThread;
R_API void r_core_wait(RCore *core) {
r_cons_singleton () -> breaked = true;
r_th_kill (httpthread, true);
r_th_kill (rapthread, true);
r_th_wait (httpthread);
r_th_wait (rapthread);
}
static void http_logf(RCore *core, const char *fmt, ...) {
bool http_log_enabled = r_config_get_i (core->config, "http.log");
va_list ap;
@ -1609,17 +1617,18 @@ R_API void r_core_rtr_session(RCore *core, const char *input) {
int fd;
prompt[0] = 0;
if (IS_DIGIT(input[0])) {
if (IS_DIGIT (input[0])) {
fd = r_num_math (core->num, input);
for (rtr_n = 0; rtr_host[rtr_n].fd \
&& rtr_host[rtr_n].fd->fd != fd \
&& rtr_n < RTR_MAX_HOSTS - 1; rtr_n++);
}
for (;;) {
if (rtr_host[rtr_n].fd)
while (!r_cons_is_breaked ()) {
if (rtr_host[rtr_n].fd) {
snprintf (prompt, sizeof (prompt),
"fd:%d> ", rtr_host[rtr_n].fd->fd);
}
free (r_line_singleton ()->prompt);
r_line_singleton ()->prompt = strdup (prompt);
if (r_cons_fgets (buf, sizeof (buf), 0, NULL) < 1) {
@ -1653,9 +1662,22 @@ static void r_rap_packet_fill(ut8 *buf, const ut8* src, int len) {
}
}
static void r_core_rtr_rap_run(RCore *core, const char *input) {
/* ouch, this hurts a bit, isnt? */
r_core_cmdf (core, "o rap://%s", input);
static bool r_core_rtr_rap_run(RCore *core, const char *input) {
char *file = r_str_newf ("rap://%s", input);
int flags = R_IO_READ | R_IO_WRITE;
RIODesc *fd = r_io_open_nomap (core->io, file, flags, 0644);
if (fd) {
if (r_io_is_listener (core->io)) {
if (!r_core_serve (core, fd)) {
r_cons_singleton() -> breaked = true;
}
r_io_desc_free (fd);
}
} else {
r_cons_singleton()->breaked = true;
}
return !r_cons_singleton ()->breaked;
// r_core_cmdf (core, "o rap://%s", input);
}
static int r_core_rtr_rap_thread (RThread *th) {
@ -1666,8 +1688,7 @@ static int r_core_rtr_rap_thread (RThread *th) {
if (!rt || !rt->core) {
return false;
}
r_core_rtr_rap_run (rt->core, rt->input);
return true;
return r_core_rtr_rap_run (rt->core, rt->input);
}
R_API void r_core_rtr_cmd(RCore *core, const char *input) {
@ -1687,11 +1708,16 @@ R_API void r_core_rtr_cmd(RCore *core, const char *input) {
eprintf ("RAP Thread is already running\n");
eprintf ("This is experimental and probably buggy. Use at your own risk\n");
} else {
RapThread rt = { core, input + 1 };
rapthread = r_th_new (r_core_rtr_rap_thread, &rt, false);
RapThread *RT = R_NEW0 (RapThread);
if (RT) {
RT->core = core;
RT->input = strdup (input + 1);
//RapThread rt = { core, strdup (input + 1) };
rapthread = r_th_new (r_core_rtr_rap_thread, RT, false);
r_th_start (rapthread, true);
eprintf ("Background rap server started.\n");
}
}
return;
}

View File

@ -213,6 +213,7 @@ R_API bool r_core_init(RCore *core);
R_API RCore *r_core_new(void);
R_API RCore *r_core_free(RCore *core);
R_API RCore *r_core_fini(RCore *c);
R_API void r_core_wait(RCore *core);
R_API RCore *r_core_ncast(ut64 p);
R_API RCore *r_core_cast(void *p);
R_API int r_core_config_init(RCore *core);
@ -283,7 +284,7 @@ R_API void r_core_visual_mark_dump(RCore *core);
R_API void r_core_visual_mark_reset(RCore *core);
R_API int r_core_search_cb(RCore *core, ut64 from, ut64 to, RCoreSearchCallback cb);
R_API int r_core_serve(RCore *core, RIODesc *fd);
R_API bool r_core_serve(RCore *core, RIODesc *fd);
R_API int r_core_file_reopen(RCore *core, const char *args, int perm, int binload);
R_API void r_core_file_reopen_debug(RCore *core, const char *args);
R_API RCoreFile * r_core_file_find_by_fd(RCore* core, ut64 fd);

View File

@ -177,6 +177,7 @@ static RIODesc *rap__open(RIO *io, const char *pathname, int rw, int mode) {
if (is_ssl) {
if (file && *file) {
if (!r_socket_listen (rior->fd, port, file)) {
r_socket_free (rior->fd);
free (rior);
return NULL;
}

View File

@ -67,9 +67,12 @@ R_API void r_th_break(RThread *th) {
}
R_API int r_th_kill(RThread *th, int force) {
if (!th) {
return false;
}
th->breaked = true;
r_th_break(th);
r_th_wait(th);
r_th_break (th);
r_th_wait (th);
#if HAVE_PTHREAD
#ifdef __ANDROID__
pthread_kill (th->tid, 9);