[Mesa-dev] [PATCH] RFC: Workaround for pthread_setaffinity_np() seccomp filtering
marcandre.lureau at redhat.com
marcandre.lureau at redhat.com
Wed Feb 27 23:13:39 UTC 2019
From: Marc-André Lureau <marcandre.lureau at redhat.com>
Since commit d877451b48a59ab0f9a4210fc736f51da5851c9a ("util/u_queue:
add UTIL_QUEUE_INIT_SET_FULL_THREAD_AFFINITY"), mesa calls
sched_setaffinity syscall. Unfortunately, qemu crashes with SIGSYS
when sandboxing is enabled (by default with libvirt), as this syscall
is filtered.
There doesn't seem to be a way to check for the seccomp rule other
than doing a call, which may result in various behaviour depending on
seccomp actions. There is a PTRACE_SECCOMP_GET_FILTER, but it is
low-level and a priviledged operation (but there might be a way to use
it?). A safe way would be to try the call in a subprocess,
unfortunately, qemu also prohibits fork(). Also this could be subject
to TOCTOU.
There seems to be few solutions, but the issue can be considered a
regression for various libvirt/Boxes users.
Introduce MESA_NO_THREAD_AFFINITY environment variable to prevent the
offending call. Wrap pthread_setaffinity_np() in a utility function
u_pthread_setaffinity_np(), returning a EACCESS error if the variable
is set.
Note: one call is left with a FIXME, as I didn't investigate how to
build and test it, help welcome!
See also:
https://bugs.freedesktop.org/show_bug.cgi?id=109695
Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
---
.../drivers/swr/rasterizer/core/threads.cpp | 1 +
src/util/u_queue.c | 2 +-
src/util/u_thread.h | 15 ++++++++++++++-
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/gallium/drivers/swr/rasterizer/core/threads.cpp b/src/gallium/drivers/swr/rasterizer/core/threads.cpp
index e30c1170568..d10c79512a1 100644
--- a/src/gallium/drivers/swr/rasterizer/core/threads.cpp
+++ b/src/gallium/drivers/swr/rasterizer/core/threads.cpp
@@ -364,6 +364,7 @@ void bindThread(SWR_CONTEXT* pContext,
CPU_ZERO(&cpuset);
CPU_SET(threadId, &cpuset);
+ /* FIXME: use u_pthread_setaffinity_np() if possible */
int err = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (err != 0)
{
diff --git a/src/util/u_queue.c b/src/util/u_queue.c
index 3812c824b6d..dea8d2bb4ae 100644
--- a/src/util/u_queue.c
+++ b/src/util/u_queue.c
@@ -249,7 +249,7 @@ util_queue_thread_func(void *input)
for (unsigned i = 0; i < CPU_SETSIZE; i++)
CPU_SET(i, &cpuset);
- pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+ u_pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
}
#endif
diff --git a/src/util/u_thread.h b/src/util/u_thread.h
index a46c18d3db2..a4e6dbae5d7 100644
--- a/src/util/u_thread.h
+++ b/src/util/u_thread.h
@@ -70,6 +70,19 @@ static inline void u_thread_setname( const char *name )
(void)name;
}
+#if defined(HAVE_PTHREAD_SETAFFINITY)
+static inline int u_pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,
+ const cpu_set_t *cpuset)
+{
+ if (getenv("MESA_NO_THREAD_AFFINITY")) {
+ errno = EACCES;
+ return -1;
+ }
+
+ return pthread_setaffinity_np(thread, cpusetsize, cpuset);
+}
+#endif
+
/**
* An AMD Zen CPU consists of multiple modules where each module has its own L3
* cache. Inter-thread communication such as locks and atomics between modules
@@ -89,7 +102,7 @@ util_pin_thread_to_L3(thrd_t thread, unsigned L3_index, unsigned cores_per_L3)
CPU_ZERO(&cpuset);
for (unsigned i = 0; i < cores_per_L3; i++)
CPU_SET(L3_index * cores_per_L3 + i, &cpuset);
- pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset);
+ u_pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset);
#endif
}
--
2.21.0
More information about the mesa-dev
mailing list