From: Timo Teräs Fix setre[gu]id handling for musl. The libc calls work per POSIX definition and change the process values (including all threads). Remove the per-thread hacks. This fixes a race condition that created thread calls first setreuid() causing the setgroups() call in the main thread to fail with -EPERM. diff -ru fprobe-ulog-1.2.orig/src/fprobe-ulog.c fprobe-ulog-1.2/src/fprobe-ulog.c --- fprobe-ulog-1.2.orig/src/fprobe-ulog.c 2015-06-01 08:48:25.858651393 -0300 +++ fprobe-ulog-1.2/src/fprobe-ulog.c 2015-06-01 08:49:07.645734248 -0300 @@ -622,18 +622,6 @@ return p; } -void setuser() { - /* - Workaround for clone()-based threads - Try to change EUID independently of main thread - */ - if (pw) { - setgroups(0, NULL); - setregid(pw->pw_gid, pw->pw_gid); - setreuid(pw->pw_uid, pw->pw_uid); - } -} - void *emit_thread() { struct Flow *flow; @@ -645,8 +633,6 @@ p = (void *) &emit_packet + netflow->HeaderSize; timeout.tv_nsec = 0; - setuser(); - for (;;) { pthread_mutex_lock(&emit_mutex); while (!flows_emit) { @@ -733,8 +719,6 @@ char logbuf[256]; #endif - setuser(); - timeout.tv_nsec = 0; pthread_mutex_lock(&unpending_mutex); @@ -780,8 +764,6 @@ struct Time now; struct timespec timeout; - setuser(); - timeout.tv_nsec = 0; pthread_mutex_lock(&scan_mutex); @@ -876,8 +858,6 @@ char logbuf[256]; #endif - setuser(); - while (!killed) { len = ipulog_read(ulog_handle, cap_buf, CAPTURE_SIZE, 1); if (len <= 0) { @@ -1386,6 +1366,21 @@ } } + if (pw) { + if (setgroups(0, NULL)) { + my_log(LOG_CRIT, "setgroups(): %s", strerror(errno)); + exit(1); + } + if (setregid(pw->pw_gid, pw->pw_gid)) { + my_log(LOG_CRIT, "setregid(%u): %s", pw->pw_gid, strerror(errno)); + exit(1); + } + if (setreuid(pw->pw_uid, pw->pw_uid)) { + my_log(LOG_CRIT, "setreuid(%u): %s", pw->pw_uid, strerror(errno)); + exit(1); + } + } + schedp.sched_priority = schedp.sched_priority - THREADS + 2; pthread_attr_init(&tattr); for (i = 0; i < THREADS - 1; i++) { @@ -1404,21 +1399,6 @@ schedp.sched_priority++; } - if (pw) { - if (setgroups(0, NULL)) { - my_log(LOG_CRIT, "setgroups(): %s", strerror(errno)); - exit(1); - } - if (setregid(pw->pw_gid, pw->pw_gid)) { - my_log(LOG_CRIT, "setregid(%u): %s", pw->pw_gid, strerror(errno)); - exit(1); - } - if (setreuid(pw->pw_uid, pw->pw_uid)) { - my_log(LOG_CRIT, "setreuid(%u): %s", pw->pw_uid, strerror(errno)); - exit(1); - } - } - my_log(LOG_INFO, "pid: %d", pid); my_log(LOG_INFO, "options: u=%u s=%u g=%u d=%u e=%u n=%u a=%s " "M=%d b=%u m=%u q=%u B=%u r=%u t=%u:%u c=%s u=%s v=%u l=%u%s",