From 2133c22052aa67d0705f44eb71cc881e716a61ed Mon Sep 17 00:00:00 2001 From: The Tumultuous Unicorn Of Darkness Date: Sat, 27 Jul 2024 13:25:08 +0200 Subject: [PATCH] Improve set_cpu_affinity() on NetBSD By default, running libcpuid as regular user on NetBSD shows nothing: set_cpu_affinity() fails quietly so cpu_identify_all() is not able to get raw data. This commit display a warning when an unallowed user try to set CPU affinity. --- libcpuid/cpuid_main.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/libcpuid/cpuid_main.c b/libcpuid/cpuid_main.c index dd757d8..e5ad329 100644 --- a/libcpuid/cpuid_main.c +++ b/libcpuid/cpuid_main.c @@ -526,6 +526,8 @@ static bool set_cpu_affinity(logical_cpu_t logical_cpu) #endif /* defined __DragonFly__ */ #if defined __NetBSD__ +#include +#include #include #include @@ -553,9 +555,36 @@ static bool restore_cpu_affinity(void) static bool set_cpu_affinity(logical_cpu_t logical_cpu) { - cpuset_t *cpuset; - cpuset = cpuset_create(); - cpuset_set((cpuid_t) logical_cpu, cpuset); + int result = -1; + size_t size = sizeof(result); + + /* Note: pthread_setaffinity_np() always returns 0 even if the target logical CPU does not exist */ + if (logical_cpu >= get_total_cpus()) + return false; + + /* Check if user is allowed to control CPU sets: https://man.netbsd.org/secmodel_extensions.9 */ + if (getuid() != 0) { + if (sysctlbyname("security.models.extensions.user_set_cpu_affinity", &result, &size, NULL, 0)) { + warnf("failed to get sysctl value for security.models.extensions.user_set_cpu_affinity\n"); + return false; + } + else if (result == 0) { + warnf("user is not allowed to control the CPU affinity: you may enable \"Non-superuser control of CPU sets\" by setting sysctl security.models.extensions.user_set_cpu_affinity=1\n"); + return false; + } + } + + cpuset_t *cpuset = cpuset_create(); + if (cpuset == NULL) { + warnf("failed to create CPU set for logical CPU %u\n", logical_cpu); + return false; + } + + if (cpuset_set((cpuid_t) logical_cpu, cpuset) < 0) { + warnf("failed to set CPU set for logical CPU %u\n", logical_cpu); + return false; + } + int ret = pthread_setaffinity_np(pthread_self(), cpuset_size(cpuset), cpuset); cpuset_destroy(cpuset); return ret == 0;