From: Paul Floyd Date: Wed, 6 Mar 2024 20:19:23 +0000 (+0100) Subject: FreeBSD syscall: fixes for semctl X-Git-Tag: VALGRIND_3_23_0~127 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d6abe92a9b97506fd9997dbbe7526c6e49884626;p=thirdparty%2Fvalgrind.git FreeBSD syscall: fixes for semctl On FreeBSD, the libc semctl function takes a union semun argument for commands that take 4 arguments. It then gets that argument via va_args and takes a pointer to it. That's what gets passed to the sysctl - a pointer to union semun. Previously we were handling the 4th argument as if it were directly a union semun. This seems to have worked OK for years, possibly due to luck concerning the way that va_args works and/or the fact that the union is basically a union of pointers. Recently I've been working on arm64 and there it most definitely does not work. --- diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index d21168433..5f12ef062 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -2186,38 +2186,38 @@ PRE(sys_futimes) // int semctl(int semid, int semnum, int cmd, ...); PRE(sys_freebsd7___semctl) { + union vki_semun* semun; switch (ARG3) { - case VKI_IPC_INFO: - case VKI_SEM_INFO: - PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); - PRE_REG_READ4(int, "semctl", - int, semid, int, semnum, int, cmd, struct seminfo *, arg); - break; case VKI_IPC_STAT: case VKI_SEM_STAT: case VKI_IPC_SET: - PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); - PRE_REG_READ4(int, "semctl", - int, semid, int, semnum, int, cmd, struct vki_semid_ds_old *, arg); - break; case VKI_GETALL: case VKI_SETALL: - PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); + PRINT("sys_freebsd7___semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); PRE_REG_READ4(int, "semctl", - int, semid, int, semnum, int, cmd, unsigned short *, arg); + int, semid, int, semnum, int, cmd, union vki_semun *, arg); + PRE_MEM_READ("sys_freebsd7___semctl(arg)", ARG4, sizeof(union vki_semun)); + semun = (union vki_semun*)ARG4; + if (ML_(safe_to_deref)(semun, sizeof(*semun))) { + ARG4 = (RegWord)semun; + ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); + } break; default: - PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u )",ARG1,ARG2,ARG3); + PRINT("sys_freebsd7___semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u )",ARG1,ARG2,ARG3); PRE_REG_READ3(long, "semctl", int, semid, int, semnum, int, cmd); break; } - ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); } POST(sys_freebsd7___semctl) { - ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4); + union vki_semun* semun = (union vki_semun*)ARG4; + if (ML_(safe_to_deref)(semun, sizeof(*semun))) { + ARG4 = (RegWord)semun; + ML_(generic_POST_sys_semctl)(tid, RES, ARG1,ARG2,ARG3,ARG4); + } } // SYS_semget 221 @@ -5647,25 +5647,23 @@ PRE(sys_closefrom) // int __semctl(int semid, int semnum, int cmd, _Inout_ union semun *arg); PRE(sys___semctl) { + union vki_semun* semun; + switch (ARG3) { - case VKI_IPC_INFO: - case VKI_SEM_INFO: - PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); - PRE_REG_READ4(int, "semctl", - int, semid, int, semnum, int, cmd, struct seminfo *, arg); - break; case VKI_IPC_STAT: case VKI_SEM_STAT: case VKI_IPC_SET: - PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); - PRE_REG_READ4(long, "semctl", - int, semid, int, semnum, int, cmd, struct semid_ds *, arg); - break; case VKI_GETALL: case VKI_SETALL: - PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); + PRINT("sys___semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3,ARG4); PRE_REG_READ4(long, "semctl", - int, semid, int, semnum, int, cmd, unsigned short *, arg); + int, semid, int, semnum, int, cmd, union vki_semun *, arg); + PRE_MEM_READ("sys___sysctl(arg)", ARG4, sizeof(union vki_semun)); + semun = (union vki_semun*)ARG4; + if (ML_(safe_to_deref)(semun, sizeof(*semun))) { + ARG4 = (RegWord)semun; + ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); + } break; default: PRINT("sys_semctl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u )",ARG1,ARG2,ARG3); @@ -5673,12 +5671,15 @@ PRE(sys___semctl) int, semid, int, semnum, int, cmd); break; } - ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); } POST(sys___semctl) { - ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4); + union vki_semun* semun = (union vki_semun*)ARG4; + if (ML_(safe_to_deref)(semun, sizeof(*semun))) { + ARG4 = (RegWord)semun; + ML_(generic_POST_sys_semctl)(tid, RES, ARG1,ARG2,ARG3,ARG4); + } } // SYS_msgctl 511 diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index d5159e790..8f94b172f 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -1825,7 +1825,7 @@ UInt get_sem_count( Int semid ) # elif defined(__NR___semctl) /* FreeBSD */ struct vki_semid_ds buf; arg.buf = &buf; - res = VG_(do_syscall4)(__NR___semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg); + res = VG_(do_syscall4)(__NR___semctl, semid, 0, VKI_IPC_STAT, (RegWord)&arg); if (sr_isError(res)) return 0; diff --git a/include/vki/vki-freebsd.h b/include/vki/vki-freebsd.h index 1267eb3b3..0cf17cc7b 100644 --- a/include/vki/vki-freebsd.h +++ b/include/vki/vki-freebsd.h @@ -1270,7 +1270,7 @@ struct vki_utsname { #define VKI_IPC_RMID 0 /* remove resource */ #define VKI_IPC_SET 1 /* set ipc_perm options */ #define VKI_IPC_STAT 2 /* get ipc_perm options */ -#define VKI_IPC_INFO 3 /* see ipcs */ +#define VKI_IPC_INFO 3 /* only used by Linux compatibilty shm_ctl */ //---------------------------------------------------------------------- // From sys/ipc.h diff --git a/memcheck/tests/freebsd/scalar.c b/memcheck/tests/freebsd/scalar.c index 3518f361a..40479dcbb 100644 --- a/memcheck/tests/freebsd/scalar.c +++ b/memcheck/tests/freebsd/scalar.c @@ -793,8 +793,8 @@ int main(void) } /* SYS_freebsd7___semctl 220 */ - GO(SYS_freebsd7___semctl, "(IPC_INFO) 4s 1m"); - SY(SYS_freebsd7___semctl, x0, x0, x0+IPC_INFO, x0+1); FAIL; + GO(SYS_freebsd7___semctl, "(IPC_STAT) 4s 1m"); + SY(SYS_freebsd7___semctl, x0, x0, x0+IPC_STAT, x0+1); FAIL; GO(SYS_freebsd7___semctl, "(bogus cmd) 3s 0m"); SY(SYS_freebsd7___semctl, x0, x0, x0-1, x0+1); FAIL; @@ -1787,8 +1787,8 @@ int main(void) #endif /* SYS___semctl 510 */ - GO(SYS___semctl, "(IPC_INFO) 4s 1m"); - SY(SYS___semctl, x0, x0, x0+IPC_INFO, x0+1); FAIL; + GO(SYS___semctl, "(IPC_STAT) 4s 1m"); + SY(SYS___semctl, x0, x0, x0+IPC_STAT, x0+1); FAIL; GO(SYS___semctl, "(other) 3s 0m"); SY(SYS___semctl, x0, x0, x0+3000, x0+1); FAIL; diff --git a/memcheck/tests/freebsd/scalar.stderr.exp b/memcheck/tests/freebsd/scalar.stderr.exp index 38d2380f7..5ea7543b6 100644 --- a/memcheck/tests/freebsd/scalar.stderr.exp +++ b/memcheck/tests/freebsd/scalar.stderr.exp @@ -1560,7 +1560,7 @@ Syscall param poll(ufds.events) points to uninitialised byte(s) Address 0x........ is on thread 1's stack --------------------------------------------------------- -220: SYS_freebsd7___semctl (IPC_INFO) 4s 1m +220: SYS_freebsd7___semctl (IPC_STAT) 4s 1m --------------------------------------------------------- Syscall param semctl(semid) contains uninitialised byte(s) ... @@ -1574,7 +1574,7 @@ Syscall param semctl(cmd) contains uninitialised byte(s) Syscall param semctl(arg) contains uninitialised byte(s) ... -Syscall param semctl(IPC_INFO, arg.buf) points to unaddressable byte(s) +Syscall param sys_freebsd7___semctl(arg) points to unaddressable byte(s) ... Address 0x........ is not stack'd, malloc'd or (recently) free'd @@ -4399,7 +4399,7 @@ Syscall param closefrom(lowfd) contains uninitialised byte(s) ... --------------------------------------------------------- -510: SYS___semctl (IPC_INFO) 4s 1m +510: SYS___semctl (IPC_STAT) 4s 1m --------------------------------------------------------- Syscall param semctl(semid) contains uninitialised byte(s) ... @@ -4413,7 +4413,7 @@ Syscall param semctl(cmd) contains uninitialised byte(s) Syscall param semctl(arg) contains uninitialised byte(s) ... -Syscall param semctl(IPC_INFO, arg.buf) points to unaddressable byte(s) +Syscall param sys___sysctl(arg) points to unaddressable byte(s) ... Address 0x........ is not stack'd, malloc'd or (recently) free'd diff --git a/memcheck/tests/freebsd/scalar.stderr.exp-x86 b/memcheck/tests/freebsd/scalar.stderr.exp-x86 index cdb0825ca..106381e11 100644 --- a/memcheck/tests/freebsd/scalar.stderr.exp-x86 +++ b/memcheck/tests/freebsd/scalar.stderr.exp-x86 @@ -1560,7 +1560,7 @@ Syscall param poll(ufds.events) points to uninitialised byte(s) Address 0x........ is on thread 1's stack --------------------------------------------------------- -220: SYS_freebsd7___semctl (IPC_INFO) 4s 1m +220: SYS_freebsd7___semctl (IPC_STAT) 4s 1m --------------------------------------------------------- Syscall param semctl(semid) contains uninitialised byte(s) ... @@ -1574,7 +1574,7 @@ Syscall param semctl(cmd) contains uninitialised byte(s) Syscall param semctl(arg) contains uninitialised byte(s) ... -Syscall param semctl(IPC_INFO, arg.buf) points to unaddressable byte(s) +Syscall param sys_freebsd7___semctl(arg) points to unaddressable byte(s) ... Address 0x........ is not stack'd, malloc'd or (recently) free'd @@ -4430,7 +4430,7 @@ Syscall param closefrom(lowfd) contains uninitialised byte(s) ... --------------------------------------------------------- -510: SYS___semctl (IPC_INFO) 4s 1m +510: SYS___semctl (IPC_STAT) 4s 1m --------------------------------------------------------- Syscall param semctl(semid) contains uninitialised byte(s) ... @@ -4444,7 +4444,7 @@ Syscall param semctl(cmd) contains uninitialised byte(s) Syscall param semctl(arg) contains uninitialised byte(s) ... -Syscall param semctl(IPC_INFO, arg.buf) points to unaddressable byte(s) +Syscall param sys___sysctl(arg) points to unaddressable byte(s) ... Address 0x........ is not stack'd, malloc'd or (recently) free'd