[Mesa-dev] [PATCH] RFC: Workaround for pthread_setaffinity_np() seccomp filtering
Marc-André Lureau
marcandre.lureau at gmail.com
Thu Feb 28 09:57:02 UTC 2019
Hi
On Thu, Feb 28, 2019 at 1:17 AM Marek Olšák <maraeo at gmail.com> wrote:
>
> I'd rather have something more robust than an env var, like catching SIGSYS.
With current qemu in most distros, it defaults to SIGSYS (we switched
away from SCMP_ACT_KILL, which had other problems). With more recent
qemu/libseccomp, it will default to SCMP_ACT_KILL_PROCESS. In those
KILL action cases, mesa will not be able to catch the failing
syscalls.
>
> Marek
>
> On Wed, Feb 27, 2019 at 6:13 PM <marcandre.lureau at redhat.com> wrote:
>>
>> 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
>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
--
Marc-André Lureau
More information about the mesa-dev
mailing list