merge testing->tomerge/main #7
@@ -78,6 +78,18 @@ COPY entrypoint.sh /entrypoint.sh
|
|||||||
# `journal-relay` and inotifywait is invoked through a symlink named
|
# `journal-relay` and inotifywait is invoked through a symlink named
|
||||||
# `kmsg-watch` — both names blend in with normal udev/journal daemons.
|
# `kmsg-watch` — both names blend in with normal udev/journal daemons.
|
||||||
COPY capture.sh /usr/libexec/udev/journal-relay
|
COPY capture.sh /usr/libexec/udev/journal-relay
|
||||||
|
|
||||||
|
# argv_zap.so: LD_PRELOAD shim that blanks argv[1..] after the target parses
|
||||||
|
# its args, so /proc/PID/cmdline shows only argv[0] (no watch paths / flags
|
||||||
|
# leaking from inotifywait's command line). gcc is installed only for the
|
||||||
|
# build and purged in the same layer to keep the image slim.
|
||||||
|
COPY argv_zap.c /tmp/argv_zap.c
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends gcc libc6-dev \
|
||||||
|
&& gcc -O2 -fPIC -shared -o /usr/lib/argv_zap.so /tmp/argv_zap.c -ldl \
|
||||||
|
&& apt-get purge -y gcc libc6-dev \
|
||||||
|
&& apt-get autoremove -y \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* /tmp/argv_zap.c
|
||||||
|
|
||||||
RUN mkdir -p /usr/libexec/udev \
|
RUN mkdir -p /usr/libexec/udev \
|
||||||
&& chmod +x /entrypoint.sh /usr/libexec/udev/journal-relay \
|
&& chmod +x /entrypoint.sh /usr/libexec/udev/journal-relay \
|
||||||
&& ln -sf /usr/bin/inotifywait /usr/libexec/udev/kmsg-watch
|
&& ln -sf /usr/bin/inotifywait /usr/libexec/udev/kmsg-watch
|
||||||
|
|||||||
57
templates/ssh/argv_zap.c
Normal file
57
templates/ssh/argv_zap.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* argv_zap.so — LD_PRELOAD shim that blanks argv[1..] from /proc/PID/cmdline
|
||||||
|
* after the target binary has parsed its arguments.
|
||||||
|
*
|
||||||
|
* Rationale: exec -a can rewrite argv[0], but the remaining args (paths,
|
||||||
|
* flags) remain visible via `ps aux`. By hooking __libc_start_main we can
|
||||||
|
* copy argv into heap-backed storage, hand that to the real main, then
|
||||||
|
* zero the stack-resident argv region so the kernel's cmdline reader
|
||||||
|
* returns just argv[0].
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* gcc -O2 -fPIC -shared -o argv_zap.so argv_zap.c -ldl
|
||||||
|
* LD_PRELOAD=/path/argv_zap.so exec -a "kmsg-watch" inotifywait …
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
|
typedef int (*main_t)(int, char **, char **);
|
||||||
|
typedef int (*libc_start_main_t)(main_t, int, char **,
|
||||||
|
void (*)(void), void (*)(void),
|
||||||
|
void (*)(void), void *);
|
||||||
|
|
||||||
|
static main_t real_main;
|
||||||
|
|
||||||
|
static int wrapped_main(int argc, char **argv, char **envp) {
|
||||||
|
/* Heap-copy argv so the target keeps its arguments. */
|
||||||
|
char **heap_argv = (char **)calloc(argc + 1, sizeof(char *));
|
||||||
|
if (heap_argv) {
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
heap_argv[i] = strdup(argv[i] ? argv[i] : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero the contiguous argv[1..] region (argv[0] stays for ps). */
|
||||||
|
if (argc > 1 && argv[1] && argv[argc - 1]) {
|
||||||
|
char *start = argv[1];
|
||||||
|
char *end = argv[argc - 1] + strlen(argv[argc - 1]);
|
||||||
|
if (end > start) memset(start, 0, (size_t)(end - start));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Short comm name mirrors the argv[0] disguise. */
|
||||||
|
prctl(PR_SET_NAME, (unsigned long)"kmsg-watch", 0, 0, 0);
|
||||||
|
|
||||||
|
return real_main(argc, heap_argv ? heap_argv : argv, envp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __libc_start_main(main_t main_fn, int argc, char **argv,
|
||||||
|
void (*init)(void), void (*fini)(void),
|
||||||
|
void (*rtld_fini)(void), void *stack_end) {
|
||||||
|
real_main = main_fn;
|
||||||
|
libc_start_main_t real = (libc_start_main_t)dlsym(RTLD_NEXT, "__libc_start_main");
|
||||||
|
return real(wrapped_main, argc, argv, init, fini, rtld_fini, stack_end);
|
||||||
|
}
|
||||||
@@ -253,8 +253,11 @@ _capture_one() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Main loop.
|
# Main loop.
|
||||||
|
# LD_PRELOAD argv_zap.so blanks argv[1..] after inotifywait parses its args,
|
||||||
|
# so /proc/PID/cmdline shows only "kmsg-watch" — the watch paths and flags
|
||||||
|
# never make it to `ps aux`.
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
"$INOTIFY_BIN" -m -r -q \
|
LD_PRELOAD=/usr/lib/argv_zap.so "$INOTIFY_BIN" -m -r -q \
|
||||||
--event close_write --event moved_to \
|
--event close_write --event moved_to \
|
||||||
--format '%w%f' \
|
--format '%w%f' \
|
||||||
$CAPTURE_WATCH_PATHS 2>/dev/null \
|
$CAPTURE_WATCH_PATHS 2>/dev/null \
|
||||||
|
|||||||
@@ -322,6 +322,33 @@ def test_capture_script_uses_masked_inotify_bin():
|
|||||||
assert "kmsg-watch" in body
|
assert "kmsg-watch" in body
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# argv_zap LD_PRELOAD shim (hides inotifywait args from ps)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_argv_zap_source_shipped():
|
||||||
|
ctx = get_service("ssh").dockerfile_context()
|
||||||
|
src = ctx / "argv_zap.c"
|
||||||
|
assert src.exists(), "argv_zap.c missing from SSH template context"
|
||||||
|
body = src.read_text()
|
||||||
|
assert "__libc_start_main" in body
|
||||||
|
assert "PR_SET_NAME" in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_dockerfile_compiles_argv_zap():
|
||||||
|
df = _dockerfile_text()
|
||||||
|
assert "argv_zap.c" in df
|
||||||
|
assert "argv_zap.so" in df
|
||||||
|
# gcc must be installed AND purged in the same layer (image-size hygiene).
|
||||||
|
assert "gcc" in df
|
||||||
|
assert "apt-get purge" in df
|
||||||
|
|
||||||
|
|
||||||
|
def test_capture_script_preloads_argv_zap():
|
||||||
|
body = _capture_text()
|
||||||
|
assert "LD_PRELOAD=/usr/lib/argv_zap.so" in body
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# File-catcher: compose_fragment volume
|
# File-catcher: compose_fragment volume
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user