From a836d219b74dee5f9d024f8cece27c55a2e2d6dd Mon Sep 17 00:00:00 2001 From: Paul Floyd Date: Thu, 8 Feb 2024 08:34:42 +0100 Subject: [PATCH] FreeBSD _umtx_op: fix bad wrapper for robust lists Was a half-baked copy and paste from the mutex version. --- coregrind/m_syswrap/syswrap-freebsd.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index 18717a8972..d211684332 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -4696,15 +4696,19 @@ PRE(sys__umtx_op) void *, obj, int, op, unsigned long, val, void*, uaddr); break; 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)) { - SET_STATUS_Failure( VKI_ENOSYS ); + // strangely the obj pointer ARG1 isn't used, for instance lin libc + // libthr/thread/thr_mutex.c: _umtx_op(NULL, UMTX_OP_ROBUST_LISTS, sizeof(rb), &rb, NULL); + // val (ARG3) ought to be the same as sizeof(struct vki_umtx_robust_lists_params) + // strangely the kernel returns EINVAL if size is larger than sizeof(struct vki_umtx_robust_lists_params) + // (which seems relatively harmless) + // but not if it is smaller (definitely dangerous, probably an overrun) + if (ARG3 < sizeof(struct vki_umtx_robust_lists_params)) { + VG_(umsg)("WARNING: _umtx_op_tobust_lists size is smaller than sizeof(struct umtx_robust_lists_params).\n"); } 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); - PRE_MEM_READ( "_umtx_op_robust_lists(mutex)", ARG3, sizeof(struct vki_umtx_robust_lists_params) ); + PRE_REG_READ4(long, "_umtx_op_robust_lists", + void*, obj, int, op, unsigned long, val, struct umtx_robust_lists*, uaddr); + PRE_MEM_READ( "_umtx_op_robust_lists(robust_lists)", ARG4, ARG3 ); break; #if (FREEBSD_VERS >= FREEBSD_13_3) case VKI_UMTX_OP_GET_MIN_TIMEOUT: -- 2.43.5