From d1252bae813eec656d25dce7d271658d65e62afe Mon Sep 17 00:00:00 2001 From: Micah Snyder Date: Wed, 6 Dec 2023 17:33:21 -0500 Subject: [PATCH] FMap: Windows & 32bit compatibility fix for Rust interface The fmap structure has some stuff that differs in size in memory between Linux and Windows, and between 32bit and 64bit architectures. Notably, `time_t` appears to be defined by the Rust bindgen module as `ulong` which may be either 8 bytes or 4 bytes, depending architecture (thanks, C). To resolve this, we'll store time as a uint64_t instead. The other problem in the fmap structure is the windows file and map handles should always be exist, and may only be used in Windows, for consistency in sizing of the structure. --- libclamav/fmap.c | 36 ++++++++++++++++++------------------ libclamav/fmap.h | 28 +++++++++++++--------------- libclamav_rust/src/sys.rs | 9 ++++++--- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/libclamav/fmap.c b/libclamav/fmap.c index 5ca70a0ec8..0548b8adf5 100644 --- a/libclamav/fmap.c +++ b/libclamav/fmap.c @@ -132,7 +132,7 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha m = cl_fmap_open_handle((void *)(ssize_t)fd, offset, len, pread_cb, 1); if (!m) return NULL; - m->mtime = st.st_mtime; + m->mtime = (uint64_t)st.st_mtime; if (NULL != name) { m->name = cli_strdup(name); @@ -152,8 +152,8 @@ static void unmap_win32(fmap_t *m) if (NULL != m->data) { UnmapViewOfFile(m->data); } - if (NULL != m->mh) { - CloseHandle(m->mh); + if (NULL != m->windows_map_handle) { + CloseHandle(m->windows_map_handle); } if (NULL != m->name) { free(m->name); @@ -169,8 +169,8 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha STATBUF st; fmap_t *m = NULL; const void *data; - HANDLE fh; - HANDLE mh; + HANDLE windows_file_handle; + HANDLE windows_map_handle; *empty = 0; if (FSTAT(fd, &st)) { @@ -194,30 +194,30 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha pages = fmap_align_items(len, pgsz); - if ((fh = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) { + if ((windows_file_handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) { cli_errmsg("fmap: cannot get a valid handle for descriptor %d\n", fd); return NULL; } - if (!(mh = CreateFileMapping(fh, NULL, PAGE_READONLY, (DWORD)((len >> 31) >> 1), (DWORD)len, NULL))) { + if (!(windows_map_handle = CreateFileMapping(windows_file_handle, NULL, PAGE_READONLY, (DWORD)((len >> 31) >> 1), (DWORD)len, NULL))) { cli_errmsg("fmap: cannot create a map of descriptor %d\n", fd); return NULL; } - if (!(data = MapViewOfFile(mh, FILE_MAP_READ, (DWORD)((offset >> 31) >> 1), (DWORD)(offset), len))) { + if (!(data = MapViewOfFile(windows_map_handle, FILE_MAP_READ, (DWORD)((offset >> 31) >> 1), (DWORD)(offset), len))) { cli_errmsg("fmap: cannot map file descriptor %d\n", fd); - CloseHandle(mh); + CloseHandle(windows_map_handle); return NULL; } if (!(m = cl_fmap_open_memory(data, len))) { cli_errmsg("fmap: cannot allocate fmap_t\n", fd); UnmapViewOfFile(data); - CloseHandle(mh); + CloseHandle(windows_map_handle); return NULL; } - m->handle = (void *)(size_t)fd; - m->handle_is_fd = 1; /* This is probably(?) needed so `fmap_fd()` can return the file descriptor. */ - m->fh = fh; - m->mh = mh; - m->unmap = unmap_win32; + m->handle = (void *)(size_t)fd; + m->handle_is_fd = true; /* This is probably(?) needed so `fmap_fd()` can return the file descriptor. */ + m->windows_file_handle = (void *)windows_file_handle; + m->windows_map_handle = (void *)windows_map_handle; + m->unmap = unmap_win32; if (NULL != name) { m->name = cli_strdup(name); @@ -416,7 +416,7 @@ extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len, } m->handle = handle; m->pread_cb = pread_cb; - m->aging = use_aging; + m->aging = use_aging != 0 ? true : false; m->offset = offset; m->nested_offset = 0; m->len = len; /* m->nested_offset + m->len = m->real_len */ @@ -430,7 +430,7 @@ extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len, m->need_offstr = handle_need_offstr; m->gets = handle_gets; m->unneed_off = handle_unneed_off; - m->handle_is_fd = 1; + m->handle_is_fd = true; m->have_md5 = false; m->have_sha1 = false; m->have_sha256 = false; @@ -587,7 +587,7 @@ static int fmap_readpage(fmap_t *m, uint64_t first_page, uint64_t count, uint64_ cli_warnmsg("fmap_readpage: fstat failed: %s\n", errtxt); return 1; } - if (m->mtime != st.st_mtime) { + if (m->mtime != (uint64_t)st.st_mtime) { cli_warnmsg("fmap_readpage: file changed as we read it\n"); return 1; } diff --git a/libclamav/fmap.h b/libclamav/fmap.h index 87742752cf..2e298e46c2 100644 --- a/libclamav/fmap.h +++ b/libclamav/fmap.h @@ -51,19 +51,19 @@ struct cl_fmap { const void *data; /* internal */ - time_t mtime; + uint64_t mtime; uint64_t pages; uint64_t pgsz; uint64_t paged; - uint16_t aging; - bool dont_cache_flag; /** indicates if we should not cache scan results for this fmap. Used if limits exceeded */ - uint16_t handle_is_fd; /** non-zero if map->handle is an fd. */ - size_t offset; /** file offset representing start of original fmap, if the fmap created reading from a file starting at offset other than 0 */ - size_t nested_offset; /** offset from start of original fmap (data) for nested scan. 0 for orig fmap. */ - size_t real_len; /** len from start of original fmap (data) to end of current (possibly nested) map. */ - /* real_len == nested_offset + len. - real_len is needed for nested maps because we only reference the original mapping data. - We convert caller's fmap offsets & lengths to real data offsets using nested_offset & real_len. */ + bool aging; /** indicates if we should age off memory mapped pages */ + bool dont_cache_flag; /** indicates if we should not cache scan results for this fmap. Used if limits exceeded */ + bool handle_is_fd; /** non-zero if map->handle is an fd. */ + size_t offset; /** file offset representing start of original fmap, if the fmap created reading from a file starting at offset other than 0 */ + size_t nested_offset; /** offset from start of original fmap (data) for nested scan. 0 for orig fmap. */ + size_t real_len; /** len from start of original fmap (data) to end of current (possibly nested) map. */ + /* real_len == nested_offset + len. + real_len is needed for nested maps because we only reference the original mapping data. + We convert caller's fmap offsets & lengths to real data offsets using nested_offset & real_len. */ /* external */ size_t len; /** length of data from nested_offset, accessible via current fmap */ @@ -82,10 +82,8 @@ struct cl_fmap { const void *(*need_offstr)(fmap_t *, size_t at, size_t len_hint); const void *(*gets)(fmap_t *, char *dst, size_t *at, size_t max_len); void (*unneed_off)(fmap_t *, size_t at, size_t len); -#ifdef _WIN32 - HANDLE fh; - HANDLE mh; -#endif + void *windows_file_handle; + void *windows_map_handle; bool have_md5; unsigned char md5[CLI_HASHLEN_MD5]; bool have_sha1; @@ -424,7 +422,7 @@ cl_error_t fmap_dump_to_file(fmap_t *map, const char *filepath, const char *tmpd * @brief Return the open file descriptor for the fmap (if available). * * This function will only provide the file descriptor if the fmap handle is set, - * and if the handle is in fact a file descriptor (handle_is_fd != 0). + * and if the handle is in fact a file descriptor (handle_is_fd == true). * * @param m The fmap. * @return int The file descriptor, or -1 if not available. diff --git a/libclamav_rust/src/sys.rs b/libclamav_rust/src/sys.rs index e683c8dd1b..ccac0bb1de 100644 --- a/libclamav_rust/src/sys.rs +++ b/libclamav_rust/src/sys.rs @@ -268,14 +268,15 @@ pub struct cl_fmap { pub handle: *mut ::std::os::raw::c_void, pub pread_cb: clcb_pread, pub data: *const ::std::os::raw::c_void, - pub mtime: time_t, + pub mtime: u64, pub pages: u64, pub pgsz: u64, pub paged: u64, - pub aging: u16, + pub aging: bool, + #[doc = " indicates if we should age off memory mapped pages"] pub dont_cache_flag: bool, #[doc = " indicates if we should not cache scan results for this fmap. Used if limits exceeded"] - pub handle_is_fd: u16, + pub handle_is_fd: bool, #[doc = " non-zero if map->handle is an fd."] pub offset: usize, #[doc = " file offset representing start of original fmap, if the fmap created reading from a file starting at offset other than 0"] @@ -311,6 +312,8 @@ pub struct cl_fmap { >, pub unneed_off: ::std::option::Option, + pub windows_file_handle: *mut ::std::os::raw::c_void, + pub windows_map_handle: *mut ::std::os::raw::c_void, pub have_md5: bool, pub md5: [::std::os::raw::c_uchar; 16usize], pub have_sha1: bool,