From d8cc70f6d5a37b9b773c85f8666d6c5f7f65a29b Mon Sep 17 00:00:00 2001 From: Paul Floyd Date: Sun, 25 Dec 2022 10:18:51 +0100 Subject: [PATCH] FreeBSD only: fix 445743 Restart 3 of the umtx_op mutex operations if they are interrupted. --- coregrind/m_signals.c | 2 +- coregrind/m_syswrap/priv_types_n_macros.h | 1 + coregrind/m_syswrap/syswrap-freebsd.c | 32 ++++++++++++++++------- coregrind/m_syswrap/syswrap-main.c | 8 +++++- coregrind/pub_core_syswrap.h | 2 ++ 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index bfddbe392a..b3c94fcc90 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -2604,7 +2604,7 @@ void async_signalhandler ( Int sigNo, tid, VG_UCONTEXT_INSTR_PTR(uc), sres, - !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART), + !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART) || VG_(is_in_kernel_restart_syscall)(tid), uc ); diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h index 3966cfa604..461019ad7b 100644 --- a/coregrind/m_syswrap/priv_types_n_macros.h +++ b/coregrind/m_syswrap/priv_types_n_macros.h @@ -185,6 +185,7 @@ typedef #define SfPollAfter (1 << 3) /* poll for signals on completion */ #define SfYieldAfter (1 << 4) /* yield on completion */ #define SfNoWriteResult (1 << 5) /* don't write result to guest state */ +#define SfKernelRestart (1 << 6) /* needs a manual restart */ /* --------------------------------------------------------------------- diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index 53d09f89f0..71443e399b 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -4253,8 +4253,9 @@ PRE(sys__umtx_op) struct umtx *, obj, int, op, unsigned long, id, size_t, timeout_size, struct vki_timespec *, timeout); PRE_MEM_READ( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); - if (ARG5) + if (ARG5) { PRE_MEM_READ( "_umtx_op_lock(timespec)", ARG5, ARG4 ); + } PRE_MEM_WRITE( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) ); *flags |= SfMayBlock; break; @@ -4279,6 +4280,8 @@ PRE(sys__umtx_op) if (ARG5) { PRE_MEM_READ( "_umtx_op_wait(timeout)", ARG5, ARG4 ); + } else { + *flags |= SfKernelRestart; } break; @@ -4294,9 +4297,11 @@ PRE(sys__umtx_op) struct umutex *, obj, int, op, unsigned long, noid, size_t, timeout_size, struct vki_timespec *, timeout); PRE_MEM_READ( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) ); - if (ARG5) + if (ARG5) { PRE_MEM_READ( "_umtx_op_mutex_trylock(timespec)", ARG5, ARG4 ); + } PRE_MEM_WRITE( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) ); + *flags |= SfMayBlock | SfKernelRestart; break; case VKI_UMTX_OP_MUTEX_LOCK: PRINT( "sys__umtx_op ( %#" FMT_REGWORD "x, MUTEX_LOCK, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x)", ARG1, ARG3, ARG4, ARG5); @@ -4304,10 +4309,11 @@ PRE(sys__umtx_op) struct umutex *, obj, int, op, unsigned long, noid, size_t, timeout_size, struct vki_timespec *, timeout); PRE_MEM_READ( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) ); - if (ARG5) + if (ARG5) { PRE_MEM_READ( "_umtx_op_mutex_lock(timespec)", ARG5, ARG4 ); + } PRE_MEM_WRITE( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) ); - *flags |= SfMayBlock; + *flags |= SfMayBlock | SfKernelRestart; break; case VKI_UMTX_OP_MUTEX_UNLOCK: PRINT( "sys__umtx_op ( %#" FMT_REGWORD "x, MUTEX_UNLOCK)", ARG1); @@ -4323,8 +4329,9 @@ PRE(sys__umtx_op) unsigned int *, old_ceiling); PRE_MEM_READ( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) ); PRE_MEM_WRITE( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) ); - if (ARG4) + if (ARG4) { PRE_MEM_WRITE( "_umtx_op_set_ceiling(old_ceiling)", ARG4, sizeof(vki_uint32_t) ); + } break; case VKI_UMTX_OP_CV_WAIT: PRINT( "sys__umtx_op ( %#" FMT_REGWORD "x, CV_WAIT, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x)", ARG1, ARG3, ARG4, ARG5); @@ -4335,8 +4342,9 @@ PRE(sys__umtx_op) PRE_MEM_WRITE( "_umtx_op_cv_wait(cond)", ARG1, sizeof(struct vki_ucond) ); PRE_MEM_READ( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) ); PRE_MEM_WRITE( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) ); - if (ARG5) + if (ARG5) { PRE_MEM_READ( "_umtx_op_cv_wait(timespec)", ARG5, sizeof(struct vki_timespec) ); + } *flags |= SfMayBlock; break; case VKI_UMTX_OP_CV_SIGNAL: @@ -4359,8 +4367,9 @@ PRE(sys__umtx_op) int *, obj, int, op, unsigned long, id, size_t, timeout_wait, struct vki_timespec *, timeout); PRE_MEM_READ( "_umtx_op_wait(uint)", ARG1, sizeof(int) ); - if (ARG5) + if (ARG5) { PRE_MEM_READ( "_umtx_op_wait(timespec)", ARG5, ARG4 ); + } *flags |= SfMayBlock; break; case VKI_UMTX_OP_RW_RDLOCK: @@ -4394,8 +4403,9 @@ PRE(sys__umtx_op) int *, obj, int, op, unsigned long, id, size_t, timeout_size, struct vki_timespec *, timeout); PRE_MEM_READ( "_umtx_op_wait_private(uint)", ARG1, sizeof(int) ); - if (ARG5) + if (ARG5) { PRE_MEM_READ( "_umtx_op_wait_private(umtx_time)", ARG5, ARG4 ); + } *flags |= SfMayBlock; break; case VKI_UMTX_OP_WAKE_PRIVATE: @@ -4426,8 +4436,9 @@ PRE(sys__umtx_op) size_t, timeout_size, struct vki_timespec *, timeout); PRE_MEM_READ( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) ); PRE_MEM_WRITE( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) ); - if (ARG5) + if (ARG5) { PRE_MEM_READ( "_umtx_op_sem_wait(umtx_time)", ARG5, ARG4 ); + } *flags |= SfMayBlock; break; case VKI_UMTX_OP_SEM_WAKE: @@ -4474,8 +4485,9 @@ PRE(sys__umtx_op) case VKI_UMTX_OP_ROBUST_LISTS: // val (ARG2) ought to be the same as sizeof(struct vki_umtx_robust_lists_params) // then the structure contains a pointer to mutex structures - if (ARG1 != sizeof(struct vki_umtx_robust_lists_params)) + if (ARG1 != sizeof(struct vki_umtx_robust_lists_params)) { SET_STATUS_Failure( VKI_ENOSYS ); + } PRINT( "sys__umtx_op ( %#" FMT_REGWORD "x, ROBUST_LISTS, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x)", ARG1, ARG3, ARG4, ARG5); PRE_REG_READ3(long, "_umtx_op_robust_lists", struct umtx_robust_lists_params *, obj, int, op, unsigned long, flags); diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index 5077a7da73..abd8472e92 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -2000,6 +2000,12 @@ Bool VG_(is_in_syscall) ( ThreadId tid ) return (syscallInfo && syscallInfo[tid].status.what != SsIdle); } +Bool VG_(is_in_kernel_restart_syscall) ( ThreadId tid ) +{ + vg_assert(tid >= 0 && tid < VG_N_THREADS); + return (syscallInfo && ((syscallInfo[tid].flags & SfKernelRestart) != 0)); +} + Word VG_(is_in_syscall_no) (ThreadId tid ) { vg_assert(tid >= 0 && tid < VG_N_THREADS); @@ -2302,7 +2308,7 @@ void VG_(client_syscall) ( ThreadId tid, UInt trc ) /* Check that the given flags are allowable: MayBlock, PollAfter and PostOnFail are ok. */ - vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter))); + vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter | SfKernelRestart))); if (sci->flags & SfMayBlock) { diff --git a/coregrind/pub_core_syswrap.h b/coregrind/pub_core_syswrap.h index a17620afc2..0b40b501d6 100644 --- a/coregrind/pub_core_syswrap.h +++ b/coregrind/pub_core_syswrap.h @@ -52,6 +52,8 @@ extern void VG_(clear_syscallInfo) ( ThreadId tid ); // Returns True if the given thread is currently in a system call extern Bool VG_(is_in_syscall) ( ThreadId tid ); +extern Bool VG_(is_in_kernel_restart_syscall) ( ThreadId tid ); + // If VG_(is_in_syscall) (tid), returns the sysno the given thread is in extern Word VG_(is_in_syscall_no) (ThreadId tid ); -- 2.47.2