git: fcafa2453102 - releng/14.0 - timerfd: fix up a memory leak and missing locking
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 28 Sep 2023 22:28:14 UTC
The branch releng/14.0 has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=fcafa24531021555976b4945d9c58667c0f75ca2 commit fcafa24531021555976b4945d9c58667c0f75ca2 Author: Mateusz Guzik <mjg@FreeBSD.org> AuthorDate: 2023-08-25 14:21:39 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2023-09-28 22:26:19 +0000 timerfd: fix up a memory leak and missing locking timerfd01 from ltp passes (and some other don't), but none of the tests crash the kernel. This is a bare minimum patch to fix up the immediate regression. Reported by: yasu (cherry picked from commit 02f534b57f84d6f4f97c337b05b383c8b3aaf18c) Approved by: re (cperciva@) (cherry picked from commit 8c496b26641e3d86b0c9db0ed2b4598093df6d5a) Approved-by: re (cperciva) --- sys/kern/sys_timerfd.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/sys/kern/sys_timerfd.c b/sys/kern/sys_timerfd.c index 6948fa059b8c..2bf2a05c443c 100644 --- a/sys/kern/sys_timerfd.c +++ b/sys/kern/sys_timerfd.c @@ -43,6 +43,7 @@ #include <sys/queue.h> #include <sys/selinfo.h> #include <sys/stat.h> +#include <sys/sx.h> #include <sys/sysctl.h> #include <sys/sysent.h> #include <sys/sysproto.h> @@ -59,7 +60,11 @@ #endif static MALLOC_DEFINE(M_TIMERFD, "timerfd", "timerfd structures"); -static LIST_HEAD(, timerfd) timerfd_head; + +static struct sx timerfd_list_lock; +static LIST_HEAD(, timerfd) timerfd_list; +SX_SYSINIT(timerfd, &timerfd_list_lock, "timerfd_list_lock"); + static struct unrhdr64 tfdino_unr; #define TFD_NOJUMP 0 /* Realtime clock has not jumped. */ @@ -125,7 +130,8 @@ timerfd_jumped(void) struct timespec boottime, diff; timerfd_getboottime(&boottime); - LIST_FOREACH(tfd, &timerfd_head, entry) { + sx_xlock(&timerfd_list_lock); + LIST_FOREACH(tfd, &timerfd_list, entry) { mtx_lock(&tfd->tfd_lock); if (tfd->tfd_clockid != CLOCK_REALTIME || (tfd->tfd_timflags & TFD_TIMER_ABSTIME) == 0 || @@ -160,6 +166,7 @@ timerfd_jumped(void) tfd->tfd_boottim = boottime; mtx_unlock(&tfd->tfd_lock); } + sx_xunlock(&timerfd_list_lock); } static int @@ -314,11 +321,14 @@ timerfd_close(struct file *fp, struct thread *td) { struct timerfd *tfd = fp->f_data; + sx_xlock(&timerfd_list_lock); + LIST_REMOVE(tfd, entry); + sx_xunlock(&timerfd_list_lock); + callout_drain(&tfd->tfd_callout); seldrain(&tfd->tfd_sel); knlist_destroy(&tfd->tfd_sel.si_note); mtx_destroy(&tfd->tfd_lock); - LIST_REMOVE(tfd, entry); free(tfd, M_TIMERFD); fp->f_ops = &badfileops; @@ -420,9 +430,11 @@ kern_timerfd_create(struct thread *td, int clockid, int flags) if ((flags & TFD_CLOEXEC) != 0) fflags |= O_CLOEXEC; + error = falloc(td, &fp, &fd, fflags); + if (error != 0) + return (error); + tfd = malloc(sizeof(*tfd), M_TIMERFD, M_WAITOK | M_ZERO); - if (tfd == NULL) - return (ENOMEM); tfd->tfd_clockid = (clockid_t)clockid; tfd->tfd_flags = flags; tfd->tfd_ino = alloc_unr64(&tfdino_unr); @@ -431,16 +443,15 @@ kern_timerfd_create(struct thread *td, int clockid, int flags) knlist_init_mtx(&tfd->tfd_sel.si_note, &tfd->tfd_lock); timerfd_getboottime(&tfd->tfd_boottim); getnanotime(&tfd->tfd_birthtim); - LIST_INSERT_HEAD(&timerfd_head, tfd, entry); + sx_xlock(&timerfd_list_lock); + LIST_INSERT_HEAD(&timerfd_list, tfd, entry); + sx_xunlock(&timerfd_list_lock); - error = falloc(td, &fp, &fd, fflags); - if (error != 0) - return (error); fflags = FREAD; if ((flags & TFD_NONBLOCK) != 0) fflags |= FNONBLOCK; - finit(fp, fflags, DTYPE_TIMERFD, tfd, &timerfdops); + fdrop(fp, td); td->td_retval[0] = fd;