From: Paul Floyd Date: Fri, 16 May 2025 05:58:02 +0000 (+0200) Subject: Bug 504265 - FreeBSD: missing syscall wrappers for fchroot and setcred X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4f3f688a31ef1a213bd1a3a9e897e99cfe3950f6;p=thirdparty%2Fvalgrind.git Bug 504265 - FreeBSD: missing syscall wrappers for fchroot and setcred --- diff --git a/.gitignore b/.gitignore index 962c97606..be8c1a268 100644 --- a/.gitignore +++ b/.gitignore @@ -1435,6 +1435,7 @@ /memcheck/tests/freebsd/eventfd2 /memcheck/tests/freebsd/extattr /memcheck/tests/freebsd/fbsd278566 +/memcheck/tests/freebsd/fchroot /memcheck/tests/freebsd/fexecve /memcheck/tests/freebsd/file_locking_wait6 /memcheck/tests/freebsd/get_set_context @@ -1461,6 +1462,7 @@ /memcheck/tests/freebsd/scalar_vfork /memcheck/tests/freebsd/sctp /memcheck/tests/freebsd/sctp2 +/memcheck/tests/freebsd/setcred /memcheck/tests/freebsd/setproctitle /memcheck/tests/freebsd/sigwait /memcheck/tests/freebsd/stat diff --git a/NEWS b/NEWS index a1a5fa24d..bae5f6fcf 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 504101 Add a "vgstack" script 504177 FILE DESCRIPTORS banner shows when closing some inherited fds 501741 syscall cachestat not wrapped +504265 FreeBSD: missing syscall wrappers for fchroot and setcred To see details of a given bug, visit https://bugs.kde.org/show_bug.cgi?id=XXXXXX diff --git a/configure.ac b/configure.ac index 00cf62d47..caa79c014 100755 --- a/configure.ac +++ b/configure.ac @@ -5006,7 +5006,9 @@ AC_CHECK_FUNCS([ \ fdatasync \ getrandom \ getrlimitusage \ - timer_delete + timer_delete \ + fchroot \ + setcred ]) # AC_CHECK_LIB adds any library found to the variable LIBS, and links these @@ -5064,6 +5066,10 @@ AM_CONDITIONAL([HAVE_GETRLIMITUSAGE], [test x$ac_cv_func_getrlimitusage = xyes]) AM_CONDITIONAL([HAVE_TIMER_DELETE], [test x$ac_cv_func_timer_delete = xyes]) +AM_CONDITIONAL([HAVE_FCHROOT], + [test x$ac_cv_func_fchroot = xyes]) +AM_CONDITIONAL([HAVE_SETCRED], + [test x$ac_cv_func_setcred = xyes]) if test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \ diff --git a/coregrind/m_syswrap/priv_syswrap-freebsd.h b/coregrind/m_syswrap/priv_syswrap-freebsd.h index 8b78c5d74..f8d404239 100644 --- a/coregrind/m_syswrap/priv_syswrap-freebsd.h +++ b/coregrind/m_syswrap/priv_syswrap-freebsd.h @@ -538,7 +538,10 @@ DECL_TEMPLATE(freebsd, sys_timerfd_settime) // 587 // __FreeBSD_version 1400507 and 1500012 DECL_TEMPLATE(freebsd, sys_kcmp) // 588 + DECL_TEMPLATE(freebsd, sys_getrlimitusage) // 589 +DECL_TEMPLATE(freebsd, sys_fchroot) // 590 +DECL_TEMPLATE(freebsd, sys_setcred) // 591 DECL_TEMPLATE(freebsd, sys_fake_sigreturn) diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index 41cd07561..8fcfe1090 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -7001,6 +7001,28 @@ POST(sys_getrlimitusage) } } +// SYS_fchroot 590 +// int fchroot(int fd); +PRE(sys_fchroot) +{ + PRINT("sys_fchroot(%ld)", ARG1); + PRE_REG_READ1(int, "fchroot", int, fd); + + /* Be strict. */ + if (!ML_(fd_allowed)(ARG1, "fchroot", tid, False)) + SET_STATUS_Failure(VKI_EBADF); +} + +// SYS_setcred +// int setcred(u_int flags, const struct setcred *wcred, size_t size); +PRE(sys_setcred) +{ + PRINT("sys_setcred(%ld, %#" FMT_REGWORD "x, %lu)", ARG1, ARG2, ARG3); + PRE_REG_READ3(int, "setcred", u_int, flags, const struct setcred*, wcred, size_t, size); + PRE_MEM_READ("setcred(wcred)", ARG2, sizeof(struct vki_setcred)); +} + + #undef PRE #undef POST @@ -7694,6 +7716,9 @@ const SyscallTableEntry ML_(syscall_table)[] = { BSDX_(__NR_kcmp, sys_kcmp), // 588 BSDXY(__NR_getrlimitusage, sys_getrlimitusage), // 589 + BSDX_(__NR_fchroot, sys_fchroot), // 590 + BSDX_(__NR_setcred, sys_setcred), // 591 + BSDX_(__NR_fake_sigreturn, sys_fake_sigreturn), // 1000, fake sigreturn }; diff --git a/include/vki/vki-freebsd.h b/include/vki/vki-freebsd.h index b870025f0..253997999 100644 --- a/include/vki/vki-freebsd.h +++ b/include/vki/vki-freebsd.h @@ -3257,6 +3257,23 @@ union vki_ccb { #define VKI_CAMIOCOMMAND _VKI_IOWR(VKI_CAM_VERSION, 2, union vki_ccb) +//---------------------------------------------------------------------- +// From cam/scsi/scsi_all.h +//---------------------------------------------------------------------- +struct vki_setcred { + vki_uid_t sc_uid; /* effective user id */ + vki_uid_t sc_ruid; /* real user id */ + vki_uid_t sc_svuid; /* saved user id */ + vki_gid_t sc_gid; /* effective group id */ + vki_gid_t sc_rgid; /* real group id */ + vki_gid_t sc_svgid; /* saved group id */ + vki_u_int sc_pad; /* see 32-bit compat structure */ + vki_u_int sc_supp_groups_nb; /* number of supplementary groups */ + vki_gid_t *sc_supp_groups; /* supplementary groups */ + struct vki_mac *sc_label; /* MAC label */ +}; + + /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/include/vki/vki-scnums-freebsd.h b/include/vki/vki-scnums-freebsd.h index 098b722f4..a92abb9a1 100644 --- a/include/vki/vki-scnums-freebsd.h +++ b/include/vki/vki-scnums-freebsd.h @@ -627,6 +627,8 @@ #define __NR_kcmp 588 #define __NR_getrlimitusage 589 +#define __NR_fchroot 590 +#define __NR_setcred 591 #define __NR_fake_sigreturn 1000 diff --git a/memcheck/tests/freebsd/Makefile.am b/memcheck/tests/freebsd/Makefile.am index b362d6148..091d05678 100644 --- a/memcheck/tests/freebsd/Makefile.am +++ b/memcheck/tests/freebsd/Makefile.am @@ -53,6 +53,8 @@ EXTRA_DIST = \ extattr.stderr.exp \ fbsd278566.vgtest \ fbsd278566.stderr.exp \ + fchroot.vgtest \ + fchroot.stderr.exp \ fexecve.vgtest \ fexecve.stderr.exp \ file_locking_wait6.vgtest \ @@ -109,6 +111,8 @@ EXTRA_DIST = \ sctp2.vgtest \ sctp2.stderr.exp \ sctp2.stdout.exp \ + setcred.vgtest \ + setcred.stderr.exp \ setproctitle.vgtest \ setproctitle.stderr.exp \ setproctitle.stdout.exp \ @@ -176,6 +180,11 @@ if HAVE_AIO_READV check_PROGRAMS += aiov endif +if HAVE_FCHROOT +check_PROGRAMS += fchroot +fchroot_SOURCES = fchroot.cpp +endif + if HAVE_GETRLIMITUSAGE check_PROGRAMS += getrlimitusage endif @@ -203,6 +212,12 @@ if FREEBSD_KQUEUEX_SYSCALL check_PROGRAMS += kqueuex endif +if HAVE_SETCRED +check_PROGRAMS += setcred +setcred_SOURCES = setcred.cpp +setcred_CXXFLAGS = ${AM_CXXFLAGS} @FLAG_W_NO_UNINITIALIZED@ +endif + if FREEBSD_TIMERFD_SYSCALL check_PROGRAMS += timerfd timerfd_LDFLAGS = -lm diff --git a/memcheck/tests/freebsd/fchroot.cpp b/memcheck/tests/freebsd/fchroot.cpp new file mode 100644 index 000000000..84b7ee7ad --- /dev/null +++ b/memcheck/tests/freebsd/fchroot.cpp @@ -0,0 +1,17 @@ +#include +#include + +int main() +{ + int fd1; + int* fd2{new int}; + + fd1 = open("..", O_DIRECTORY | O_RDONLY); + // will fail unless run as root + fchroot(fd1); + + fchroot(*fd2); + + delete fd2; +} + diff --git a/memcheck/tests/freebsd/fchroot.stderr.exp b/memcheck/tests/freebsd/fchroot.stderr.exp new file mode 100644 index 000000000..938d3474f --- /dev/null +++ b/memcheck/tests/freebsd/fchroot.stderr.exp @@ -0,0 +1,4 @@ +Syscall param fchroot(fd) contains uninitialised byte(s) + at 0x........: fchroot (in /...libc...) + by 0x........: main (fchroot.cpp:13) + diff --git a/memcheck/tests/freebsd/fchroot.vgtest b/memcheck/tests/freebsd/fchroot.vgtest new file mode 100644 index 000000000..a07103eed --- /dev/null +++ b/memcheck/tests/freebsd/fchroot.vgtest @@ -0,0 +1,3 @@ +prereq: test -e ./fchroot +prog: fchroot +vgopts: -q diff --git a/memcheck/tests/freebsd/scalar.c b/memcheck/tests/freebsd/scalar.c index 65348c232..eddde2f42 100644 --- a/memcheck/tests/freebsd/scalar.c +++ b/memcheck/tests/freebsd/scalar.c @@ -2450,7 +2450,37 @@ int main(void) FAKE_SY(" ...\n"); FAKE_SY(" Address 0x........ is not stack'd, malloc'd or (recently) free'd\n"); FAKE_SY("\n"); -#endif +#endif + +#if defined(SYS_fchroot) + GO(SYS_fchroot, "1s, 0m"); + SY(SYS_fchroot, x0+1000); +#else + FAKE_GO("590: SYS_fchroot 1s, 0m"); + FAKE_SY("Syscall param fchroot(fd) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); +#endif + +#if defined(SYS_setcred) + GO(SYS_setcred, "3s, 1m"); + SY(SYS_setcred, x0+100, x0+3, x0+50); +#else + FAKE_GO("591: SYS_setcred 3s, 1m"); + FAKE_SY("Syscall param setcred(flags) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param setcred(wcred) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param setcred(size) contains uninitialised byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY("\n"); + FAKE_SY("Syscall param setcred(wcred) points to unaddressable byte(s)\n"); + FAKE_SY(" ...\n"); + FAKE_SY(" Address 0x........ is not stack'd, malloc'd or (recently) free'd\n"); + FAKE_SY("\n"); +#endif /* SYS_exit 1 */ GO(SYS_exit, "1s 0m"); diff --git a/memcheck/tests/freebsd/scalar.stderr.exp b/memcheck/tests/freebsd/scalar.stderr.exp index 0e47fe1aa..59ed18524 100644 --- a/memcheck/tests/freebsd/scalar.stderr.exp +++ b/memcheck/tests/freebsd/scalar.stderr.exp @@ -5740,6 +5740,28 @@ Syscall param getrlimitusage(res) points to unaddressable byte(s) ... Address 0x........ is not stack'd, malloc'd or (recently) free'd +--------------------------------------------------------- +590: SYS_fchroot 1s, 0m +--------------------------------------------------------- +Syscall param fchroot(fd) contains uninitialised byte(s) + ... + +--------------------------------------------------------- +591: SYS_setcred 3s, 1m +--------------------------------------------------------- +Syscall param setcred(flags) contains uninitialised byte(s) + ... + +Syscall param setcred(wcred) contains uninitialised byte(s) + ... + +Syscall param setcred(size) contains uninitialised byte(s) + ... + +Syscall param setcred(wcred) points to unaddressable byte(s) + ... + Address 0x........ is not stack'd, malloc'd or (recently) free'd + --------------------------------------------------------- 1: SYS_exit 1s 0m --------------------------------------------------------- diff --git a/memcheck/tests/freebsd/setcred.cpp b/memcheck/tests/freebsd/setcred.cpp new file mode 100644 index 000000000..7553599df --- /dev/null +++ b/memcheck/tests/freebsd/setcred.cpp @@ -0,0 +1,31 @@ +#include +#include + +int main() +{ + struct setcred cred1; + struct setcred* cred2; + int flags1{0}; + int flags2; + size_t size1{sizeof(cred1)}; + size_t size2; + + std::memset(&cred1, 250, sizeof(cred1)); + + // needs to be root to work correctly + setcred(flags1, &cred1, size1); + + // not accessible + setcred(flags1, nullptr, size1); + + // uninit + setcred(flags2, cred2, size2); + + cred2 = new struct setcred; + + // uninit memory + setcred(flags1, cred2, size1); + + delete cred2; +} + diff --git a/memcheck/tests/freebsd/setcred.stderr.exp b/memcheck/tests/freebsd/setcred.stderr.exp new file mode 100644 index 000000000..1d9cecf8e --- /dev/null +++ b/memcheck/tests/freebsd/setcred.stderr.exp @@ -0,0 +1,30 @@ +Syscall param setcred(wcred) points to unaddressable byte(s) + at 0x........: setcred (in /...libc...) + by 0x........: main (setcred.cpp:19) + Address 0x........ is not stack'd, malloc'd or (recently) free'd + +Syscall param setcred(flags) contains uninitialised byte(s) + at 0x........: setcred (in /...libc...) + by 0x........: main (setcred.cpp:22) + +Syscall param setcred(wcred) contains uninitialised byte(s) + at 0x........: setcred (in /...libc...) + by 0x........: main (setcred.cpp:22) + +Syscall param setcred(size) contains uninitialised byte(s) + at 0x........: setcred (in /...libc...) + by 0x........: main (setcred.cpp:22) + +Syscall param setcred(wcred) points to uninitialised byte(s) + at 0x........: setcred (in /...libc...) + by 0x........: main (setcred.cpp:22) + Address 0x........ is on thread 1's stack + in frame #2, created by __libc_start1 (???:) + +Syscall param setcred(wcred) points to uninitialised byte(s) + at 0x........: setcred (in /...libc...) + by 0x........: main (setcred.cpp:27) + Address 0x........ is 0 bytes inside a block of size 48 alloc'd + at 0x........: ...operator new... (vg_replace_malloc.c:...) + by 0x........: main (setcred.cpp:24) + diff --git a/memcheck/tests/freebsd/setcred.vgtest b/memcheck/tests/freebsd/setcred.vgtest new file mode 100644 index 000000000..8c4f4d36f --- /dev/null +++ b/memcheck/tests/freebsd/setcred.vgtest @@ -0,0 +1,3 @@ +prereq: test -e ./setcred +prog: setcred +vgopts: -q