void destroy_ctx(int desc, cli_ctx *ctx) { funmap(*(ctx->fmap)); close(desc); free(ctx->fmap); cl_engine_free((struct cl_engine *)ctx->engine); free(ctx); }
void cli_chm_close(chm_metadata_t *metadata) { if (metadata->ufd >= 0) { close(metadata->ufd); } funmap(metadata->map); }
// Clean up a file-server file descriptor. // This function is called by fd_close. static int file_close(struct Fd *fd) { // Unmap any data mapped for the file, // then tell the file server that we have closed the file // (to free up its resources). // LAB 5: Your code here. void *va; void *start; void *end; int r; start=(void *)fd2data(fd); end=(void *)(start + fd->fd_file.file.f_size); for (va=(void *)fd2data(fd); va <= end; va+=PGSIZE) if (va_is_dirty2(va)) if ((r = fsipc_dirty(fd->fd_file.id, (off_t) (va - start))) < 0) return r; if ((r = fsipc_close(fd->fd_file.id)) < 0) return r; funmap(fd, fd->fd_file.file.f_size, 0, 0); return 0; }
int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres) { int ret = CL_EMEM, empty; fmap_t *map = *ctx->fmap; if((*ctx->fmap = fmap_check_empty(desc, 0, 0, &empty))) { ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode, acres, NULL); map->dont_cache_flag = (*ctx->fmap)->dont_cache_flag; funmap(*ctx->fmap); } *ctx->fmap = map; if(empty) return CL_CLEAN; return ret; }
// Clean up a file-server file descriptor. // This function is called by fd_close. static int file_close(struct Fd *fd) { // Unmap any data mapped for the file, // then tell the file server that we have closed the file // (to free up its resources). // LAB 5: Your code here. int r; if ((r = funmap(fd, fd->fd_file.file.f_size, 0, 1)) < 0) return r; if (debug) cprintf("close %s\n", fd->fd_file.file.f_name); return fsipc_close(fd->fd_file.id); }
END_TEST #endif START_TEST(test_screnc_nullterminate) { int fd = open_testfile("input/screnc_test"); fmap_t *map; fail_unless(mkdir(dir, 0700) == 0,"mkdir failed"); map = fmap(fd, 0, 0); fail_unless(!!map, "fmap failed"); fail_unless(html_screnc_decode(map, dir) == 1, "html_screnc_decode failed"); funmap(map); fail_unless(cli_rmdirs(dir) == 0, "rmdirs failed"); close(fd); }
// Call the file system server to obtain and map file pages // when the size of the file as mapped in our memory increases. // Harmlessly does nothing if oldsize >= newsize. // Returns 0 on success, < 0 on error. // If there is an error, unmaps any newly allocated pages. static int fmap(struct Fd* fd, off_t oldsize, off_t newsize) { size_t i; char *va; int r; va = fd2data(fd); for (i = ROUNDUP(oldsize, PGSIZE); i < newsize; i += PGSIZE) { if ((r = fsipc_map(fd->fd_file.id, i, va + i)) < 0) { // unmap anything we may have mapped so far funmap(fd, i, oldsize, 0); return r; } } return 0; }
// Call the file system server to obtain and map file pages // when the size of the file as mapped in our memory increases. // Harmlessly does nothing if oldsize >= newsize. // Returns 0 on success, < 0 on error. // If there is an error, unmaps any newly allocated pages. static int fmap(struct Fd* fd, off_t oldsize, off_t newsize) { size_t i; char *va; int r; // Hint: Use fsipc_map. // Hint: Remember to unmap any pages you mapped if // an error occurs. // LAB 5: Your code here. va = fd2data(fd); for (i = ROUNDUP(oldsize, PGSIZE); i < newsize; i += PGSIZE) { if ((r = fsipc_map(fd->fd_file.id, i, va + i)) < 0) { funmap(fd, i, oldsize, 0); return r; } } return 0; }
// Truncate or extend an open file to 'size' bytes static int file_trunc(struct Fd *fd, off_t newsize) { int r; off_t oldsize; uint32_t fileid; if (newsize > MAXFILESIZE) return -E_NO_DISK; fileid = fd->fd_file.id; oldsize = fd->fd_file.file.f_size; if ((r = fsipc_set_size(fileid, newsize)) < 0) return r; assert(fd->fd_file.file.f_size == newsize); if ((r = fmap(fd, oldsize, newsize)) < 0) return r; funmap(fd, oldsize, newsize, 0); return 0; }
int main(int argc, char *argv[]) { FILE *f; struct cli_bc *bc; struct cli_bc_ctx *ctx; int rc, dbgargc, bc_stats=0; struct optstruct *opts; const struct optstruct *opt; unsigned funcid=0, i; struct cli_all_bc bcs; int fd = -1; unsigned tracelevel; if(check_flevel()) exit(1); opts = optparse(NULL, argc, argv, 1, OPT_CLAMBC, 0, NULL); if (!opts) { fprintf(stderr, "ERROR: Can't parse command line options\n"); exit(1); } if(optget(opts, "version")->enabled) { printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version()); cl_init(CL_INIT_DEFAULT); cli_bytecode_printversion(); optfree(opts); exit(0); } if(optget(opts, "help")->enabled || !opts->filename) { optfree(opts); help(); exit(0); } f = fopen(opts->filename[0], "r"); if (!f) { fprintf(stderr, "Unable to load %s\n", argv[1]); optfree(opts); exit(2); } bc = malloc(sizeof(*bc)); if (!bc) { fprintf(stderr, "Out of memory\n"); optfree(opts); exit(3); } if (optget(opts,"debug")->enabled) { cl_debug(); debug_flag=1; } rc = cl_init(CL_INIT_DEFAULT); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to init libclamav: %s\n", cl_strerror(rc)); optfree(opts); exit(4); } dbgargc=1; while (opts->filename[dbgargc]) dbgargc++; if (dbgargc > 1) cli_bytecode_debug(dbgargc, opts->filename); if (optget(opts, "force-interpreter")->enabled) { bcs.engine = NULL; } else { rc = cli_bytecode_init(&bcs); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to init bytecode engine: %s\n", cl_strerror(rc)); optfree(opts); exit(4); } } bcs.all_bcs = bc; bcs.count = 1; if((opt = optget(opts, "statistics"))->enabled) { while(opt) { if (!strcasecmp(opt->strarg, "bytecode")) bc_stats=1; opt = opt->nextarg; } } rc = cli_bytecode_load(bc, f, NULL, optget(opts, "trust-bytecode")->enabled, bc_stats); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to load bytecode: %s\n", cl_strerror(rc)); optfree(opts); exit(4); } fclose(f); if (bc->state == bc_skip) { fprintf(stderr,"bytecode load skipped\n"); exit(0); } if (debug_flag) printf("[clambc] Bytecode loaded\n"); if (optget(opts, "info")->enabled) { cli_bytecode_describe(bc); } else if (optget(opts, "printsrc")->enabled) { print_src(opts->filename[0]); } else if (optget(opts, "printbcir")->enabled) { cli_bytetype_describe(bc); cli_bytevalue_describe(bc, 0); cli_bytefunc_describe(bc, 0); } else { cli_ctx cctx; struct cl_engine *engine = cl_engine_new(); fmap_t *map = NULL; memset(&cctx, 0, sizeof(cctx)); if (!engine) { fprintf(stderr,"Unable to create engine\n"); optfree(opts); exit(3); } rc = cl_engine_compile(engine); if (rc) { fprintf(stderr,"Unable to compile engine: %s\n", cl_strerror(rc)); optfree(opts); exit(4); } rc = cli_bytecode_prepare2(engine, &bcs, BYTECODE_ENGINE_MASK); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to prepare bytecode: %s\n", cl_strerror(rc)); optfree(opts); exit(4); } if (debug_flag) printf("[clambc] Bytecode prepared\n"); ctx = cli_bytecode_context_alloc(); if (!ctx) { fprintf(stderr,"Out of memory\n"); exit(3); } ctx->ctx = &cctx; cctx.engine = engine; cctx.fmap = cli_calloc(sizeof(fmap_t*), engine->maxreclevel+2); if (!cctx.fmap) { fprintf(stderr,"Out of memory\n"); exit(3); } memset(&dbg_state, 0, sizeof(dbg_state)); dbg_state.file = "<libclamav>"; dbg_state.line = 0; dbg_state.col = 0; dbg_state.showline = !optget(opts, "no-trace-showsource")->enabled; tracelevel = optget(opts, "trace")->numarg; cli_bytecode_context_set_trace(ctx, tracelevel, tracehook, tracehook_op, tracehook_val, tracehook_ptr); if (opts->filename[1]) { funcid = atoi(opts->filename[1]); } cli_bytecode_context_setfuncid(ctx, bc, funcid); if (debug_flag) printf("[clambc] Running bytecode function :%u\n", funcid); if (opts->filename[1]) { i=2; while (opts->filename[i]) { rc = cli_bytecode_context_setparam_int(ctx, i-2, atoi(opts->filename[i])); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to set param %u: %s\n", i-2, cl_strerror(rc)); } i++; } } if ((opt = optget(opts,"input"))->enabled) { fd = open(opt->strarg, O_RDONLY); if (fd == -1) { fprintf(stderr, "Unable to open input file %s: %s\n", opt->strarg, strerror(errno)); optfree(opts); exit(5); } map = fmap(fd, 0, 0); if (!map) { fprintf(stderr, "Unable to map input file %s\n", opt->strarg); exit(5); } rc = cli_bytecode_context_setfile(ctx, map); if (rc != CL_SUCCESS) { fprintf(stderr, "Unable to set file %s: %s\n", opt->strarg, cl_strerror(rc)); optfree(opts); exit(5); } } /* for testing */ ctx->hooks.match_counts = deadbeefcounts; ctx->hooks.match_offsets = deadbeefcounts; rc = cli_bytecode_run(&bcs, bc, ctx); if (rc != CL_SUCCESS) { fprintf(stderr,"Unable to run bytecode: %s\n", cl_strerror(rc)); } else { uint64_t v; if (debug_flag) printf("[clambc] Bytecode run finished\n"); v = cli_bytecode_context_getresult_int(ctx); if (debug_flag) printf("[clambc] Bytecode returned: 0x%llx\n", (long long)v); } cli_bytecode_context_destroy(ctx); if (map) funmap(map); cl_engine_free(engine); free(cctx.fmap); } cli_bytecode_destroy(bc); cli_bytecode_done(&bcs); free(bc); optfree(opts); if (fd != -1) close(fd); if (debug_flag) printf("[clambc] Exiting\n"); cl_cleanup_crypto(); return 0; }
int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx) { struct stat statbuf; int retval; cli_dbgmsg("in cli_chm_open\n"); if ((retval = chm_init_metadata(metadata)) != CL_SUCCESS) { return retval; } if (fstat(fd, &statbuf) == 0) { if (statbuf.st_size < CHM_ITSF_MIN_LEN) { return CL_ESTAT; } metadata->m_length = statbuf.st_size; metadata->map = fmap(fd, 0, metadata->m_length); if (!metadata->map) { return CL_EMAP; } } else { char err[128]; cli_warnmsg("fstat() failed: %s\n", cli_strerror(errno, err, sizeof(err))); return CL_ESTAT; } if (!itsf_read_header(metadata)) { goto abort; } itsf_print_header(&metadata->itsf_hdr); if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) { goto abort; } itsp_print_header(&metadata->itsp_hdr); metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN; /* TODO: need to check this first calculation, currently have no files of this type */ if (metadata->itsp_hdr.index_head > 0) { metadata->chunk_offset += metadata->itsp_hdr.index_head * metadata->itsp_hdr.block_len; } metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1; /* Versions before 3 didn't have a data_offset */ /* TODO: need to check this calculation, currently have no files of this type */ if (metadata->itsf_hdr.version < 3) { metadata->itsf_hdr.data_offset = metadata->itsf_hdr.dir_offset + CHM_ITSP_LEN + (metadata->itsp_hdr.block_len*metadata->itsp_hdr.num_blocks); } while (metadata->num_chunks) { if (read_chunk(metadata) != CL_SUCCESS) { cli_dbgmsg("read_chunk failed\n"); goto abort; } if (read_control_entries(metadata) == FALSE) { goto abort; } metadata->num_chunks--; metadata->chunk_offset += metadata->itsp_hdr.block_len; } if (!metadata->sys_content.length || !metadata->sys_control.length || !metadata->sys_reset.length) { cli_dbgmsg("sys file missing\n"); goto abort; } metadata->ufd = chm_decompress_stream(fd, metadata, dirname, ctx); if (metadata->ufd == -1) { goto abort; } metadata->chunk_entries = 0; metadata->chunk_data = NULL; metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN; metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1; return CL_SUCCESS; abort: funmap(metadata->map); return CL_EFORMAT; }
extern void cl_fmap_close(cl_fmap_t *map) { funmap(map); }