This commit is contained in:
Felicitas Pojtinger 2026-07-17 00:46:54 -04:00 committed by GitHub
commit 575bd247fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 104 additions and 10 deletions

View file

@ -306,6 +306,16 @@ static int encode_notify_thread_id(pid_t rtid, struct pstree_item *item, PosixTi
if (!(root_ns_mask & CLONE_NEWPID)) {
/* Non-pid-namespace case */
for (i = 0; i < item->nr_threads; i++) {
if (item->threads[i].real == rtid)
break;
}
if (i == item->nr_threads) {
pr_warn("Skipping timer because notify thread %d is dead\n", rtid);
return 1;
}
pte->notify_thread_id = rtid;
pte->has_notify_thread_id = true;
return 0;
@ -326,8 +336,8 @@ static int encode_notify_thread_id(pid_t rtid, struct pstree_item *item, PosixTi
}
if (vtid == 0) {
pr_err("Unable to convert the notify thread id %d\n", rtid);
return -1;
pr_warn("Skipping timer because notify thread %d is dead\n", rtid);
return 1;
}
pte->notify_thread_id = vtid;
@ -351,10 +361,7 @@ static int encode_posix_timer(struct pstree_item *item, struct posix_timer *v, s
pte->vsec = v->val.it_value.tv_sec;
pte->vnsec = v->val.it_value.tv_nsec;
if (encode_notify_thread_id(vp->spt.notify_thread_id, item, pte))
return -1;
return 0;
return encode_notify_thread_id(vp->spt.notify_thread_id, item, pte);
}
int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args, struct parasite_ctl *ctl,
@ -367,7 +374,7 @@ int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args,
struct parasite_dump_posix_timers_args *args;
int ret, exit_code = -1;
int args_size;
int i;
int i, j;
if (core_alloc_posix_timers(tte, proc_args->timer_n, &pte))
return -1;
@ -386,14 +393,28 @@ int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args,
if (ret < 0)
goto end_posix;
/*
* i advances every iteration (indexes parasite-filled args->timer[]);
* j advances only for timers we keep, both the next output slot
* and the final count. Timers whose notify thread has exited are
* skipped (i.e., j <= i).
*/
i = 0;
j = 0;
list_for_each_entry(temp, &proc_args->timers, list) {
posix_timer_entry__init(&pte[i]);
if (encode_posix_timer(item, &args->timer[i], temp, &pte[i]))
posix_timer_entry__init(&pte[j]);
ret = encode_posix_timer(item, &args->timer[i], temp, &pte[j]);
if (ret < 0)
goto end_posix;
tte->posix[i] = &pte[i];
if (ret == 1) {
i++;
continue;
}
tte->posix[j] = &pte[j];
i++;
j++;
}
tte->n_posix = j;
exit_code = 0;
end_posix:

View file

@ -81,6 +81,7 @@ TST_NOFILE := \
pthread_timers \
pthread_timers_h \
leader_posix_timer \
dead_thread_posix_timer \
rseq00 \
membarrier \
vdso00 \
@ -638,6 +639,7 @@ pthread02: LDLIBS += -pthread
pthread_timers: LDLIBS += -lrt -pthread
pthread_timers_h: LDLIBS += -lrt -pthread
leader_posix_timer: LDLIBS += -lrt -pthread
dead_thread_posix_timer: LDLIBS += -lrt -pthread
different_creds: LDLIBS += -pthread
sigpending: LDLIBS += -pthread
sigaltstack: LDLIBS += -pthread

View file

@ -0,0 +1,70 @@
#include <pthread.h>
#include <signal.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
#include "zdtmtst.h"
#ifndef SIGEV_THREAD_ID
#define SIGEV_THREAD_ID 4
#endif
const char *test_doc = "Check that a SIGEV_THREAD_ID timer targeting a dead thread doesn't break dump";
const char *test_author = "Felicitas Pojtinger <felicitaspojtinger@loopholelabs.io>";
static timer_t timerid;
static void *worker(void *arg)
{
pid_t tid;
struct sigevent evp = {};
tid = syscall(SYS_gettid);
evp.sigev_notify = SIGEV_THREAD_ID;
#ifdef __GLIBC__
evp._sigev_un._tid = tid;
#else
evp.sigev_notify_thread_id = tid;
#endif
evp.sigev_signo = SIGRTMIN;
if (timer_create(CLOCK_MONOTONIC, &evp, &timerid)) {
pr_perror("timer_create");
return (void *)1;
}
return NULL;
}
int main(int argc, char **argv)
{
pthread_t thr;
void *ret;
test_init(argc, argv);
if (pthread_create(&thr, NULL, worker, NULL)) {
pr_perror("pthread_create");
return 1;
}
if (pthread_join(thr, &ret)) {
pr_perror("pthread_join");
return 1;
}
if (ret != NULL) {
fail("Timer creation thread failed");
return 1;
}
test_daemon();
test_waitsig();
pass();
timer_delete(timerid);
return 0;
}

View file

@ -0,0 +1 @@
{'feature': 'ns_pid'}