Commit cfa0983d authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

ws_emu: Introduce the workspace emulator

The goal of the workspace emulator is to replicate the regular workspace
behavior with individual allocations and make it work transparently.

It's the successor of the workspace sanitizer from #3320 with notable
differences:

- enabled at configure time instead of run time
- in a separate source file instead of mixed in
- using sparse allocations instead of built-in red zones

This means that the workspace emulator can be combined with regular
sanitizer, in particular asan and lsan. If available, asan's public
interface is used to mitigate the possible overflow of a reservation
after some of it was released.

Even without sanitizers, the fact that we integrate with jemalloc by
default and enable its abort and junk options in varnishtest is enough
to detect a use-after-free in some cases.

With sanitizers though, the workspace emulator can observe #3550.

One drawback is that the logic is split in two files, and some functions
are identical in the two files. It might be possible to split cache_ws.c
into something like cache_ws_alloc.c and cache_ws_util.c for example.

Closes #3320
Refs #3550
Refs #3600
parent 17ca56af
......@@ -53,7 +53,6 @@ varnishd_SOURCES = \
cache/cache_vrt_vcl.c \
cache/cache_vrt_vmod.c \
cache/cache_wrk.c \
cache/cache_ws.c \
common/common_vsc.c \
common/common_vsmw.c \
hash/hash_classic.c \
......@@ -110,6 +109,14 @@ varnishd_SOURCES = \
waiter/cache_waiter_ports.c \
waiter/mgt_waiter.c
if ENABLE_WORKSPACE_EMULATOR
varnishd_SOURCES += \
cache/cache_ws_emu.c
else
varnishd_SOURCES += \
cache/cache_ws.c
endif
if WITH_PERSISTENT_STORAGE
varnishd_SOURCES += \
storage/mgt_storage_persistent.c \
......
......@@ -534,16 +534,9 @@ WS_IsReserved(const struct ws *ws)
void WS_Rollback(struct ws *, uintptr_t);
void *WS_AtOffset(const struct ws *ws, unsigned off, unsigned len);
unsigned WS_ReservationOffset(const struct ws *ws);
unsigned WS_ReqPipeline(struct ws *, const void *b, const void *e);
static inline unsigned
WS_ReservationOffset(const struct ws *ws)
{
AN(ws->r);
return (ws->f - ws->s);
}
/* http1/cache_http1_pipe.c */
void V1P_Init(void);
......
......@@ -386,6 +386,14 @@ WS_AtOffset(const struct ws *ws, unsigned off, unsigned len)
return (ptr);
}
unsigned
WS_ReservationOffset(const struct ws *ws)
{
AN(ws->r);
return (ws->f - ws->s);
}
/*---------------------------------------------------------------------
* Build a VSB on a workspace.
* Usage pattern:
......
This diff is collapsed.
varnishtest "Check timeout_linger"
feature !workspace_emulator
# XXX this test exploits the fact that the struct waited is
# left near the free pointer of the session ws when a session
# made a tour over the waiter
......
varnishtest "Test std.rollback"
# ws_emu triggers #3550
feature !workspace_emulator
# bug regressions:
# - #3009
# - #3083
......
varnishtest "Test rollback and retry"
# ws_emu triggers #3550
feature !workspace_emulator
server s1 {
rxreq
txresp -nolen -hdr "Content-Length: 3"
......
......@@ -450,6 +450,8 @@ addr_no_randomize_works(void)
* Varnish was built with the undefined behavior sanitizer.
* sanitizer
* Varnish was built with a sanitizer.
* workspace_emulator
* Varnish was built with its workspace emulator.
*
* A feature name can be prefixed with an exclamation mark (!) to skip a
* test if a feature is present.
......@@ -495,6 +497,12 @@ static const unsigned sanitizer = 1;
static const unsigned sanitizer = 0;
#endif
#if ENABLE_WORKSPACE_EMULATOR
static const unsigned workspace_emulator = 1;
#else
static const unsigned workspace_emulator = 0;
#endif
#if WITH_PERSISTENT_STORAGE
static const unsigned with_persistent_storage = 1;
#else
......@@ -560,6 +568,7 @@ cmd_feature(CMD_ARGS)
FEATURE("ubsan", ubsan);
FEATURE("sanitizer", sanitizer);
FEATURE("SO_RCVTIMEO_WORKS", so_rcvtimeo_works);
FEATURE("workspace_emulator", workspace_emulator);
if (!strcmp(feat, "cmd")) {
good = 1;
......
......@@ -331,6 +331,20 @@ if test "x$UBSAN_FLAGS$TSAN_FLAGS$ASAN_FLAGS$MSAN_FLAGS" != "x"; then
LDFLAGS="$LDFLAGS $SAN_LDFLAGS"
fi
AC_ARG_ENABLE(workspace-emulator,
AS_HELP_STRING([--enable-workspace-emulator],
[emulate workspace allocations (default is NO)]),
[], [enable_workspace_emulator=no])
AM_CONDITIONAL([ENABLE_WORKSPACE_EMULATOR],
[test "$enable_workspace_emulator" = yes])
AM_COND_IF([ENABLE_WORKSPACE_EMULATOR], [
AC_CHECK_HEADERS([sanitizer/asan_interface.h])
AC_DEFINE([ENABLE_WORKSPACE_EMULATOR], [1],
[Define to 1 if the workspace emulator is enabled])
])
# Use jemalloc on Linux
JEMALLOC_LDADD=
AC_ARG_WITH([jemalloc],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment