summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libsandbox/trace.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/libsandbox/trace.c b/libsandbox/trace.c
index 2110a46..f3390d9 100644
--- a/libsandbox/trace.c
+++ b/libsandbox/trace.c
@@ -46,6 +46,26 @@ pid_t trace_pid;
# define sb_openat_pre_check sb_openat64_pre_check
#endif
+static int trace_yama_level(void)
+{
+ char ch;
+ int fd;
+
+ /* ptrace scope binds access to specific capabilities. Lets use uid==0 as a
+ * lazy proxy for "we have all capabilities" until we can refine this.
+ */
+ if (getuid() == 0)
+ return 0;
+
+ fd = open("/proc/sys/kernel/yama/ptrace_scope", O_RDONLY | O_CLOEXEC);
+ if (fd == -1)
+ return 0;
+
+ RETRY_EINTR(read(fd, &ch, 1));
+ close(fd);
+ return ch - '0';
+}
+
static void trace_exit(int status)
{
/* if we were vfork-ed, clear trace_pid and exit */
@@ -526,6 +546,16 @@ static void trace_loop(void)
sb_debug("following forking event %i; pid=%li %i\n",
event, newpid, before_syscall);
+ /* If YAMA ptrace_scope is active, then we can't hand off the child
+ * to a new tracer. Give up. #821403
+ */
+ int yama = trace_yama_level();
+ if (yama >= 1) {
+ sb_eqawarn("Unable to trace children due to YAMA ptrace_scope=%i\n", yama);
+ ptrace(PTRACE_DETACH, newpid, NULL, NULL);
+ continue;
+ }
+
/* Pipe for synchronizing detach & attach events. */
int fds[2];
ret = pipe(fds);
@@ -674,6 +704,13 @@ static char *flatten_args(char *const argv[])
bool trace_possible(const char *filename, char *const argv[], const void *data)
{
+ /* If YAMA ptrace_scope is very high, then we can't trace at all. #771360 */
+ int yama = trace_yama_level();
+ if (yama >= 2) {
+ sb_eqawarn("YAMA ptrace_scope=%i\n", yama);
+ goto fail;
+ }
+
if (_trace_possible(data)) {
/* If we're in an environment like QEMU where ptrace doesn't work, then
* don't try to use it. If ptrace does work, this should fail with ESRCH.
@@ -683,6 +720,7 @@ bool trace_possible(const char *filename, char *const argv[], const void *data)
return errno == ENOSYS ? false : true;
}
+ fail:
char *args = flatten_args(argv);
sb_eqawarn("Unable to trace static ELF: %s: %s\n", filename, args);
free(args);