Skip to content

Commit

Permalink
Refactoring RBin.open/close and RBinOptions ##bin
Browse files Browse the repository at this point in the history
* r_bin_close should be r_bin_file_close
* moved bin/open.c into bin.c
* set BinFile id in r_bin_load_io
* use r_bin_open_io instead of r_bin_load_io
* also prefer RBinOptions instead of multiple arguments
* rename r_bin_load to r_bin_open and use RBinOptions
  • Loading branch information
ret2libc authored and radare committed Nov 7, 2018
1 parent 71053f1 commit 08e5b4a
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 127 deletions.
15 changes: 5 additions & 10 deletions binr/rabin2/rabin2.c
Expand Up @@ -997,17 +997,12 @@ int main(int argc, char **argv) {
r_bin_force_plugin (bin, forcebin);
r_bin_load_filter (bin, action);

RBinOptions bo = {
.offset = 0LL,
.baseaddr = baddr,
.rawstr = rawstr,
.loadaddr = laddr,
.xtr_idx = xtr_idx,
.iofd = fd,
};
RBinOptions opt;
r_bin_options_init (&opt, fd, baddr, laddr, rawstr);
opt.xtr_idx = xtr_idx;

if (!r_bin_open (bin, file, &bo)) {
//if this return null means that we did not return a valid bin object
if (!r_bin_open (bin, file, &opt)) {
//if this return false means that we did not return a valid bin object
//but we have yet the chance that this file is a fat binary
if (!bin->cur || !bin->cur->xtr_data) {
eprintf ("r_bin: Cannot open file\n");
Expand Down
2 changes: 1 addition & 1 deletion libr/bin/Makefile
Expand Up @@ -21,7 +21,7 @@ include $(LIBR)/magic/deps.mk

STATIC_OBJS=$(addprefix $(LTOP)/bin/p/, $(STATIC_OBJ))
OBJS=bin.o dbginfo.o bin_ldr.o bin_write.o demangle.o
OBJS+=dwarf.o filter.o bfile.o obj.o open.o blang.o
OBJS+=dwarf.o filter.o bfile.o obj.o blang.o
OBJS+=mangling/cxx/cp-demangle.o ${STATIC_OBJS}
OBJS+=mangling/demangler.o
OBJS+=mangling/microsoft_demangle.o
Expand Down
29 changes: 19 additions & 10 deletions libr/bin/bfile.c
Expand Up @@ -506,17 +506,16 @@ R_API RBinFile *r_bin_file_find_by_fd(RBin *bin, ut32 bin_fd) {

R_API RBinFile *r_bin_file_find_by_name(RBin *bin, const char *name) {
RListIter *iter;
RBinFile *bf = NULL;
if (!bin || !name) {
return NULL;
}
RBinFile *bf;

r_return_val_if_fail (bin && name, NULL);

r_list_foreach (bin->binfiles, iter, bf) {
if (bf && bf->file && !strcmp (bf->file, name)) {
break;
return bf;
}
bf = NULL;
}
return bf;
return NULL;
}

R_IPI RBinFile *r_bin_file_find_by_name_n(RBin *bin, const char *name, int idx) {
Expand Down Expand Up @@ -639,9 +638,8 @@ R_API void r_bin_file_free(void /*RBinFile*/ *bf_) {
// This function populate RBinFile->xtr_data, that information is enough to
// create RBinObject when needed using r_bin_file_object_new_from_xtr_data
R_IPI RBinFile *r_bin_file_xtr_load_bytes(RBin *bin, RBinXtrPlugin *xtr, const char *filename, const ut8 *bytes, ut64 sz, ut64 file_sz, ut64 baseaddr, ut64 loadaddr, int idx, int fd, int rawstr) {
if (!bin || !bytes) {
return NULL;
}
r_return_val_if_fail (bin && xtr && bytes, NULL);

RBinFile *bf = r_bin_file_find_by_name (bin, filename);
if (!bf) {
bf = file_create_append (bin, filename, bytes, sz,
Expand Down Expand Up @@ -837,3 +835,14 @@ R_IPI RList *r_bin_file_get_strings(RBinFile *a, int min, int dump, int raw) {
R_API ut64 r_bin_file_get_baddr(RBinFile *binfile) {
return binfile? r_bin_object_get_baddr (binfile->o): UT64_MAX;
}

R_API bool r_bin_file_close(RBin *bin, int bd) {
RBinFile *bf = r_id_storage_take (bin->ids, bd);
if (bf) {
// file_free removes the fd already.. maybe its unnecessary
r_id_storage_delete (bin->ids, bd);
r_bin_file_free (bf);
return true;
}
return false;
}
122 changes: 75 additions & 47 deletions libr/bin/bin.c
Expand Up @@ -116,6 +116,14 @@ R_API RList *r_bin_dump_strings(RBinFile *bf, int min, int raw) {
return r_bin_file_get_strings (bf, min, 1, raw);
}

R_API void r_bin_options_init(RBinOptions *opt, int fd, ut64 baseaddr, ut64 loadaddr, int rawstr) {
memset (opt, 0, sizeof (*opt));
opt->baseaddr = baseaddr;
opt->loadaddr = loadaddr;
opt->fd = fd;
opt->rawstr = rawstr;
}

R_API void r_bin_info_free(RBinInfo *rb) {
if (!rb) {
return;
Expand Down Expand Up @@ -191,18 +199,26 @@ R_API void r_bin_string_free(void *_str) {
// kinda a clunky functions
// XXX - this is a rather hacky way to do things, there may need to be a better
// way.
R_API int r_bin_load(RBin *bin, const char *file, ut64 baseaddr, ut64 loadaddr, int xtr_idx, int fd, int rawstr) {
r_return_val_if_fail (bin && bin->iob.io, false);
R_API bool r_bin_open(RBin *bin, const char *file, RBinOptions *opt) {
r_return_val_if_fail (bin && bin->iob.io && opt, false);

RIOBind *iob = &(bin->iob);
if (!iob->desc_get (iob->io, fd)) {
fd = iob->fd_open (iob->io, file, R_PERM_R, 0644);
if (!iob->desc_get (iob->io, opt->fd)) {
opt->fd = iob->fd_open (iob->io, file, R_PERM_R, 0644);
}
if (fd < 0) {
if (opt->fd < 0) {
eprintf ("Couldn't open bin for file '%s'\n", file);
return false;
}
bin->rawstr = rawstr;
return r_bin_load_io (bin, fd, baseaddr, loadaddr, xtr_idx, 0, NULL, 0);
opt->offset = 0;
opt->sz = 0;
opt->pluginname = NULL;
return r_bin_open_io (bin, opt);
}

static void bin_options_from_bo(RBinOptions *opt, RBin *bin, RBinObject *bo, int fd, ut64 baseaddr) {
r_bin_options_init (opt, fd, baseaddr, bo->loadaddr, bin->rawstr);
opt->offset = bo->boffset;
}

R_API int r_bin_reload(RBin *bin, int fd, ut64 baseaddr) {
Expand Down Expand Up @@ -255,8 +271,9 @@ R_API int r_bin_reload(RBin *bin, int fd, ut64 baseaddr) {
}
if (r_list_length (the_obj_list) == 1) {
RBinObject *bo = (RBinObject *)r_list_get_n (the_obj_list, 0);
res = r_bin_load_io (bin, fd, baseaddr,
bo->loadaddr, 0, bo->boffset, NULL, 0);
RBinOptions opt;
bin_options_from_bo (&opt, bin, bo, fd, baseaddr);
res = r_bin_open_io (bin, &opt);
}
iob->fd_close (iob->io, tfd);
goto error;
Expand All @@ -280,7 +297,9 @@ R_API int r_bin_reload(RBin *bin, int fd, ut64 baseaddr) {
r_list_foreach (the_obj_list, iter, bo) {
// XXX - naive. do we need a way to prevent multiple "anys" from being opened?
// TODO: use of bo->plugin->name seems to be bad
res = r_bin_load_io (bin, fd, baseaddr, bo->loadaddr, 0, bo->boffset, NULL, 0);
RBinOptions opt;
bin_options_from_bo (&opt, bin, bo, fd, baseaddr);
res = r_bin_open_io (bin, &opt);
}
bf->o = r_list_get_n (bf->objs, 0);
free (buf_bytes);
Expand All @@ -290,7 +309,10 @@ R_API int r_bin_reload(RBin *bin, int fd, ut64 baseaddr) {
return res;
}

R_API bool r_bin_load_io(RBin *bin, int fd, ut64 baseaddr, ut64 loadaddr, int xtr_idx, ut64 offset, const char *name, ut64 sz) {
R_API bool r_bin_open_io(RBin *bin, RBinOptions *opt) {
r_return_val_if_fail (bin && opt && bin->iob.io, false);
r_return_val_if_fail (opt->fd >= 0 && (st64)opt->sz >= 0, false);

RIOBind *iob = &(bin->iob);
RIO *io = iob? iob->io: NULL;
RListIter *it;
Expand All @@ -300,102 +322,108 @@ R_API bool r_bin_load_io(RBin *bin, int fd, ut64 baseaddr, ut64 loadaddr, int xt
RBinFile *binfile = NULL;
int tfd = -1;

r_return_val_if_fail (bin && io && fd >= 0 && (st64)sz >= 0, false);
bool is_debugger = iob->fd_is_dbg (io, opt->fd);
const char *fname = iob->fd_get_name (io, opt->fd);

bool is_debugger = iob->fd_is_dbg (io, fd);
const char *fname = iob->fd_get_name (io, fd);
if (loadaddr == UT64_MAX) {
loadaddr = 0;
bin->rawstr = opt->rawstr;
if (opt->loadaddr == UT64_MAX) {
opt->loadaddr = 0;
}
file_sz = iob->fd_size (io, fd);
file_sz = iob->fd_size (io, opt->fd);
// file_sz = UT64_MAX happens when attaching to frida:// and other non-debugger io plugins which results in double opening
if (is_debugger && file_sz == UT64_MAX) {
tfd = iob->fd_open (io, fname, R_PERM_R, 0644);
if (tfd >= 1) {
file_sz = iob->fd_size (io, tfd);
}
}
if (!sz) {
sz = file_sz;
if (!opt->sz) {
opt->sz = file_sz;
}
// check if blockdevice?
if (sz >= UT32_MAX) {
sz = 1024 * 32;
if (opt->sz >= UT32_MAX) {
opt->sz = 1024 * 32;
}

bin->file = fname;
sz = R_MIN (file_sz, sz);
opt->sz = R_MIN (file_sz, opt->sz);
if (!r_list_length (bin->binfiles)) {
if (is_debugger) {
//use the temporal RIODesc to read the content of the file instead
//from the memory
if (tfd >= 0) {
buf_bytes = calloc (1, sz + 1);
buf_bytes = calloc (1, opt->sz + 1);
if (buf_bytes) {
iob->fd_read_at (io, tfd, 0, buf_bytes, sz);
iob->fd_read_at (io, tfd, 0, buf_bytes, opt->sz);
}
// iob->fd_close (io, tfd);
}
}
}
// this thing works for 2GB ELF core from vbox
if (!buf_bytes) {
if ((int)sz < 0) {
eprintf ("Cannot allocate %d bytes\n", (int)(sz));
if ((int)opt->sz < 0) {
eprintf ("Cannot allocate %d bytes\n", (int)(opt->sz));
return false;
}
const int asz = sz? sz: 1;
const int asz = opt->sz? (int)opt->sz: 1;
buf_bytes = calloc (1, asz);
if (!buf_bytes) {
eprintf ("Cannot allocate %d bytes.\n", asz);
return false;
}
ut64 seekaddr = is_debugger? baseaddr: loadaddr;
if (!iob->fd_read_at (io, fd, seekaddr, buf_bytes, asz)) {
sz = 0LL;
ut64 seekaddr = is_debugger? opt->baseaddr: opt->loadaddr;
if (!iob->fd_read_at (io, opt->fd, seekaddr, buf_bytes, asz)) {
opt->sz = 0LL;
}
}
if (bin->use_xtr && !name && (st64)sz > 0) {
if (bin->use_xtr && !opt->pluginname && (st64)opt->sz > 0) {
// XXX - for the time being this is fine, but we may want to
// change the name to something like
// <xtr_name>:<bin_type_name>
r_list_foreach (bin->binxtrs, it, xtr) {
if (xtr && xtr->check_bytes (buf_bytes, sz)) {
if (xtr && (xtr->extract_from_bytes || xtr->extractall_from_bytes)) {
if (is_debugger && sz != file_sz) {
if (xtr && xtr->check_bytes (buf_bytes, opt->sz)) {
if (xtr->extract_from_bytes || xtr->extractall_from_bytes) {
if (is_debugger && opt->sz != file_sz) {
R_FREE (buf_bytes);
if (tfd < 0) {
tfd = iob->fd_open (io, fname, R_PERM_R, 0);
}
sz = iob->fd_size (io, tfd);
if (sz != UT64_MAX) {
buf_bytes = calloc (1, sz + 1);
opt->sz = iob->fd_size (io, tfd);
if (opt->sz != UT64_MAX) {
buf_bytes = calloc (1, opt->sz + 1);
if (buf_bytes) {
(void) iob->fd_read_at (io, tfd, 0, buf_bytes, sz);
(void)iob->fd_read_at (io, tfd, 0, buf_bytes, opt->sz);
}
}
// DOUBLECLOSE UAF : iob->fd_close (io, tfd);
tfd = -1; // marking it closed
} else if (sz != file_sz) {
(void) iob->read_at (io, 0LL, buf_bytes, sz);
tfd = -1; // marking it closed
} else if (opt->sz != file_sz) {
(void)iob->read_at (io, 0LL, buf_bytes, opt->sz);
}
binfile = r_bin_file_xtr_load_bytes (bin, xtr,
fname, buf_bytes, sz, file_sz,
baseaddr, loadaddr, xtr_idx,
fd, bin->rawstr);
fname, buf_bytes, opt->sz, file_sz,
opt->baseaddr, opt->loadaddr, opt->xtr_idx,
opt->fd, bin->rawstr);
}
xtr = NULL;
}
}
}
if (!binfile) {
binfile = r_bin_file_new_from_bytes (
bin, fname, buf_bytes, sz, file_sz, bin->rawstr,
baseaddr, loadaddr, fd, name, offset);
bin, fname, buf_bytes, opt->sz, file_sz, bin->rawstr,
opt->baseaddr, opt->loadaddr, opt->fd, opt->pluginname, opt->offset);
} else {
free (buf_bytes);
}
return binfile? r_bin_file_set_cur_binfile (bin, binfile): false;

if (!binfile || !r_bin_file_set_cur_binfile (bin, binfile)) {
return false;
}

r_id_storage_set (bin->ids, bin->cur, binfile->id);
return true;
}

R_API RBinPlugin *r_bin_get_binplugin_by_name(RBin *bin, const char *name) {
Expand Down
1 change: 0 additions & 1 deletion libr/bin/meson.build
Expand Up @@ -8,7 +8,6 @@ files = [
'filter.c',
'bfile.c',
'obj.c',
'open.c',
'p/bin_any.c',
'p/bin_art.c',
'p/bin_avr.c',
Expand Down
32 changes: 0 additions & 32 deletions libr/bin/open.c

This file was deleted.

26 changes: 12 additions & 14 deletions libr/core/cfile.c
Expand Up @@ -314,21 +314,16 @@ static int r_core_file_do_load_for_debug(RCore *r, ut64 baseaddr, const char *fi
r_config_set_i (r->config, "bin.baddr", baseaddr);
}
#endif
int fd = cf ? cf->fd : -1;
RBinOptions bo = {
.offset = 0LL,
.baseaddr = baseaddr,
.rawstr = false,
.xtr_idx = xtr_idx,
.iofd = fd,
.loadaddr = UT64_MAX,
};

if (r_bin_open (r->bin, filenameuri, &bo) == -1) {
int fd = cf? cf->fd: -1;
RBinOptions opt;
r_bin_options_init (&opt, fd, baseaddr, UT64_MAX, false);
opt.xtr_idx = xtr_idx;
if (!r_bin_open (r->bin, filenameuri, &opt)) {
eprintf ("RBinLoad: Cannot open %s\n", filenameuri);
if (r_config_get_i (r->config, "bin.rawstr")) {
bo.rawstr = true;
if (r_bin_open (r->bin, filenameuri, &bo) == -1) {
r_bin_options_init (&opt, fd, baseaddr, UT64_MAX, true);
opt.xtr_idx = xtr_idx;
if (!r_bin_open (r->bin, filenameuri, &opt)) {
return false;
}
}
Expand Down Expand Up @@ -381,7 +376,10 @@ static int r_core_file_do_load_for_io_plugin(RCore *r, ut64 baseaddr, ut64 loada
return false;
}
r_io_use_fd (r->io, fd);
if (!r_bin_load_io (r->bin, fd, baseaddr, loadaddr, xtr_idx, 0, NULL, 0)) {
RBinOptions opt;
r_bin_options_init (&opt, fd, baseaddr, loadaddr, r->bin->rawstr);
opt.xtr_idx = xtr_idx;
if (!r_bin_open_io (r->bin, &opt)) {
//eprintf ("Failed to load the bin with an IO Plugin.\n");
return false;
}
Expand Down

0 comments on commit 08e5b4a

Please sign in to comment.