From: Paul Floyd Date: Sun, 4 Jan 2026 08:34:54 +0000 (+0100) Subject: syswrap readlink and linux readlinkat: check that buf is accessible for proc self... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d8023d107699c7c2d97acf2dcb77bae71c0b1cf;p=thirdparty%2Fvalgrind.git syswrap readlink and linux readlinkat: check that buf is accessible for proc self exe case Also update the t testcases to cover this. --- diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 406e6960b..aa4a0caf1 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -5096,8 +5096,12 @@ PRE(sys_readlink) HChar* out_name = (HChar*)ARG2; SizeT res = VG_(strlen)(VG_(resolved_exename)); res = VG_MIN(res, ARG3); - VG_(strncpy)(out_name, VG_(resolved_exename), res); - SET_STATUS_Success(res); + if (ML_(safe_to_deref)(out_name, res)) { + VG_(strncpy)(out_name, VG_(resolved_exename), res); + SET_STATUS_Success(res); + } else { + SET_STATUS_Failure(VKI_EFAULT); + } fuse_may_block = False; } } diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 53b620585..6853e5e94 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -6699,8 +6699,12 @@ PRE(sys_readlinkat) HChar* out_name = (HChar*)ARG3; SizeT res = VG_(strlen)(VG_(resolved_exename)); res = VG_MIN(res, ARG4); - VG_(strncpy)(out_name, VG_(resolved_exename), res); - SET_STATUS_Success(res); + if (ML_(safe_to_deref)(out_name, res)) { + VG_(strncpy)(out_name, VG_(resolved_exename), res); + SET_STATUS_Success(res); + } else { + SET_STATUS_Failure(VKI_EFAULT); + } fuse_may_block = False; } diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am index 4b9b1fe94..51b5a5b17 100644 --- a/none/tests/Makefile.am +++ b/none/tests/Makefile.am @@ -392,6 +392,7 @@ bug290061_LDFLAGS = @FLAG_PIE@ bug491394_LDADD = -lc bug491394_LDFLAGS = -nostdlib -static bug491394_CFLAGS = ${AM_CFLAGS} -Os +bug514094_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_STRINGOP_OVERFLOW@ execve_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NONNULL@ if VGCONF_OS_IS_SOLARIS fcntl_setown_LDADD = -lsocket -lnsl diff --git a/none/tests/bug514094.c b/none/tests/bug514094.c index 5010272cb..a62a6406b 100644 --- a/none/tests/bug514094.c +++ b/none/tests/bug514094.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "../../config.h" int main(int argc, char** argv) @@ -36,5 +37,12 @@ int main(int argc, char** argv) assert(strncmp(resolved, small_buf, 10) == 0); assert(small_buf[10] == '#'); +#if defined(VGO_solaris) + ret = readlink("/proc/self/path/a.out", (char*)1, 100); +#else + ret = readlink("/proc/self/exe", (char*)1, 100); +#endif + assert(ret == -1); + assert(errno = EFAULT); } diff --git a/none/tests/linux/Makefile.am b/none/tests/linux/Makefile.am index 20540247f..a1389fe0d 100644 --- a/none/tests/linux/Makefile.am +++ b/none/tests/linux/Makefile.am @@ -59,6 +59,7 @@ open_client_SOURCES = open_client.cpp endif clonev_LDADD = -lpthread pthread_stack_LDADD = -lpthread +readlinkat_self_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_STRINGOP_OVERFLOW@ stack_overflow_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@ \ @FLAG_W_NO_INFINITE_RECURSION@ diff --git a/none/tests/linux/readlinkat_self.c b/none/tests/linux/readlinkat_self.c index 5a36d55d8..586581a0d 100644 --- a/none/tests/linux/readlinkat_self.c +++ b/none/tests/linux/readlinkat_self.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "../../config.h" int main(int argc, char** argv) @@ -18,5 +19,16 @@ int main(int argc, char** argv) char resolved[PATH_MAX]; realpath(argv[0], resolved); assert(strcmp(resolved, buf) == 0); + + const size_t small_buf_size = 11; + char small_buf[small_buf_size]; + memset(small_buf, '#', small_buf_size); + ret = readlinkat(100, "/proc/self/exe", small_buf, 10); + assert(strncmp(resolved, small_buf, 10) == 0); + assert(small_buf[10] == '#'); + + ret = readlinkat(101, "/proc/self/exe", (char*)1, 100); + assert(ret == -1); + assert(errno = EFAULT); }