X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/2fd4074dd2ca95b14e0256f740965c40671e31eb..36eb5d3d77426d8cbf4243ea752f8d8cd1d5c682:/src/src/store.c diff --git a/src/src/store.c b/src/src/store.c index b65649f4a..aceb0e5d6 100644 --- a/src/src/store.c +++ b/src/src/store.c @@ -62,9 +62,11 @@ The following different types of store are recognized: recopy a string being built into a tainted allocation if it meets a %s for a tainted argument. Any intermediate-layer function that (can) return a new allocation should behave this way; returning a tainted result if any tainted - content is used. Users of functions that modify existing allocations should - check if a tainted source and an untainted destination is used, and fail instead - (sprintf() being the classic case). + content is used. Intermediate-layer functions (eg. Ustrncpy) that modify + existing allocations fail if tainted data is written into an untainted area. + Users of functions that modify existing allocations should check if a tainted + source and an untainted destination is used, and fail instead (sprintf() being + the classic case). */ @@ -184,7 +186,6 @@ static void internal_tainted_free(storeblock *, const char *, int linenumber); /******************************************************************************/ -#ifndef TAINT_CHECK_FAST /* Test if a pointer refers to tainted memory. Slower version check, for use when platform intermixes malloc and mmap area @@ -203,19 +204,18 @@ int pool; for (pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++) if ((b = current_block[pool])) { - char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK; - if (CS p >= bc && CS p <= bc + b->length) return TRUE; + uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK; + if (US p >= bc && US p <= bc + b->length) return TRUE; } for (pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++) for (b = chainbase[pool]; b; b = b->next) { - char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK; - if (CS p >= bc && CS p <= bc + b->length) return TRUE; + uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK; + if (US p >= bc && US p <= bc + b->length) return TRUE; } return FALSE; } -#endif void @@ -225,6 +225,13 @@ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Taint mismatch, %s: %s %d\n", msg, func, line); } +static void +use_slow_taint_check(void) +{ +DEBUG(D_any) debug_printf("switching to slow-mode taint checking\n"); +f.taint_check_slow = TRUE; +} + /************************************************* * Get a block from the current pool * @@ -848,6 +855,14 @@ if (!(yield = malloc((size_t)size))) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to malloc %d bytes of memory: " "called from line %d in %s", size, linenumber, func); +/* If malloc ever returns apparently tainted memory, which glibc +malloc will as it uses mmap for larger requests, we must switch to +the slower checking for tainting (checking an address against all +the tainted pool block spans, rather than just the mmap span) */ + +if (!f.taint_check_slow && is_tainted(yield)) + use_slow_taint_check(); + return store_alloc_tail(yield, size, func, linenumber, US"Malloc"); }