utrace: Trace processes across forks
authorMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 12 Sep 2017 11:12:38 +0000 (13:12 +0200)
committerJohn Crispin <john@phrozen.org>
Thu, 28 Sep 2017 06:26:56 +0000 (08:26 +0200)
commit8b7d47af206e057437832d08116b497d38683daa
treed5e3df3ee0f287e4124122c4957a1475e1f6883b
parentc6b6ec6d234e3de3dba573d59754a8c434741e39
utrace: Trace processes across forks

Without this change, utrace can trace only a single process. When the
process forks, syscalls of its children do not appear in utrace
output. This is a problem, because seccomp filters are inherited by
children and therefore filters generated by utrace may lack legitimate
syscalls.

This commit enables utrace to trace processes across forks. The
functionality can be demonstrated by the following examples:

    utrace /bin/touch /tmp/xxx

produces:

    {
            "whitelist": [
                    "rt_sigaction",
                    "rt_sigreturn",
                    "exit",
                    "getuid",
                    "exit_group",
                    "utimensat"
            ],
            "policy": 1
    }

The command:

    utrace /bin/sh -c 'touch /tmp/xxx'

without this commit produces:

    {
            "whitelist": [
                    "stat",
                    "rt_sigaction",
                    "rt_sigprocmask",
                    "rt_sigreturn",
                    "getpid",
                    "fork",
                    "exit",
                    "wait4",
                    "uname",
                    "getcwd",
                    "getuid",
                    "getppid",
                    "exit_group"
            ],
            "policy": 1
    }

but with this commit, the output is the following:

    {
            "whitelist": [
                    "read",
                    "open",
                    "close",
                    "stat",
                    "fstat",
                    "mmap",
                    "mprotect",
                    "rt_sigaction",
                    "rt_sigprocmask",
                    "rt_sigreturn",
                    "getpid",
                    "fork",
                    "execve",
                    "exit",
                    "wait4",
                    "uname",
                    "fcntl",
                    "getcwd",
                    "getuid",
                    "getppid",
                    "arch_prctl",
                    "gettid",
                    "set_tid_address",
                    "exit_group",
                    "utimensat"
            ],
            "policy": 1
    }

Note that in addition to utimensat syscall from touch, this output
contains more syscalls than what is in the union of single-process sh
and touch traces. The reason is that single-process traces do not
include syscalls from dynamic linker (due to preload trick), but the
trace of forked processes includes the dynamic linker syscalls. This
is unavoidable, because dynamic linker of the forked processes will be
subject to seccomp filters of the parent process.

Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>
trace/trace.c