]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 514094 - readlink("/proc/self/exe") overwrites buffer beyond its return value
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 3 Jan 2026 12:48:50 +0000 (13:48 +0100)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 3 Jan 2026 17:52:59 +0000 (18:52 +0100)
Used the reproducer as the basis for a test on Solaris and Linux.

.gitignore
NEWS
coregrind/m_syswrap/syswrap-generic.c
none/tests/Makefile.am
none/tests/bug514094.c [new file with mode: 0644]
none/tests/bug514094.stderr.exp [new file with mode: 0644]
none/tests/bug514094.vgtest [new file with mode: 0644]

index 039ce52a9a6182ce3b3469d6d43d1d16433eaac0..5ac1f3cb995abe3c126a65de4bfb77497873f361 100644 (file)
 /none/tests/bug290061
 /none/tests/bug491394
 /none/tests/bug492678
+/none/tests/bug514094
 /none/tests/closeall
 /none/tests/coolo_sigaction
 /none/tests/coolo_strlen
diff --git a/NEWS b/NEWS
index e0bdc122c2ca0f2728ce3fddd54d0d935b4b5446..1da711b2698d7001435c3f63a45527e785a3a34f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -55,6 +55,7 @@ are not entered into bugzilla tend to get forgotten about or ignored.
 513522  m_libcassert.c: 'ordered comparison of pointer with integer zero'
         compiler warning
 513475  Add SSE4.1 PMULLD instruction for x86 32 bit
+514094  readlink("/proc/self/exe") overwrites buffer beyond its return value 
 
 To see details of a given bug, visit
   https://bugs.kde.org/show_bug.cgi?id=XXXXXX
index 2c113c69cfe28063eae2b0fe866ab333b3133cc0..c0e717d27641c56ede1d6651bc31cea271c8d590 100644 (file)
@@ -5065,20 +5065,16 @@ POST(sys_poll)
 
 PRE(sys_readlink)
 {
-   FUSE_COMPATIBLE_MAY_BLOCK();
    PRINT("sys_readlink ( %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x, %llu )",
          ARG1, (char*)(Addr)ARG1, ARG2, (ULong)ARG3);
    PRE_REG_READ3(long, "readlink",
                  const char *, path, char *, buf, int, bufsiz);
    PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
    PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
-}
 
-POST(sys_readlink)
-{
+   Bool fuse_may_block = True;
 #if defined(VGO_linux) || defined(VGO_solaris)
    {
-      Word saved = SYSNO;
 #if defined(VGO_linux)
 #define PID_EXEPATH  "/proc/%d/exe"
 #define SELF_EXEPATH "/proc/self/exe"
@@ -5097,14 +5093,22 @@ POST(sys_readlink)
       VG_(sprintf)(name, PID_EXEPATH, VG_(getpid)());
       if (ML_(safe_to_deref)(arg1s, 1)
           && (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, SELF_EXEPATH))) {
-         VG_(sprintf)(name, SELF_EXEFD, VG_(cl_exec_fd));
-         SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name, 
-                                                  ARG2, ARG3));
+         HChar* out_name = (HChar*)ARG2;
+         SizeT res = VG_(strlen)(VG_(resolved_exename));
+         VG_(strncpy)(out_name, VG_(resolved_exename), res);
+         SET_STATUS_Success(res);
+         fuse_may_block = False;
       }
    }
 #endif
-   if (SUCCESS && RES > 0)
-      POST_MEM_WRITE( ARG2, RES );
+
+   if (fuse_may_block)
+       FUSE_COMPATIBLE_MAY_BLOCK();
+}
+
+POST(sys_readlink)
+{
+   POST_MEM_WRITE( ARG2, RES );
 }
 
 PRE(sys_readv)
index 0cc4ca8b0dfa7443a88616a136800eea5f0a60c0..3147d784ce36d5c06b9e3f596ca563dac4018640 100644 (file)
@@ -111,6 +111,7 @@ EXTRA_DIST = \
        bug290061.vgtest bug290061.stderr.exp \
        bug491394.vgtest bug491394.stderr.exp \
        bug492678.vgtest bug492678.stderr.exp \
+       bug514094,vgtest bug514094.stderr.exp \
        closeall.stderr.exp closeall.vgtest \
        cmdline0.stderr.exp cmdline0.stdout.exp cmdline0.vgtest \
        cmdline1.stderr.exp cmdline1.stdout.exp cmdline1.vgtest \
@@ -285,6 +286,7 @@ check_PROGRAMS = \
        bug129866 bug234814 \
        bug290061 \
        bug492678 \
+       bug514094 \
        closeall coolo_strlen \
        discard exec-sigmask execve faultstatus fcntl_setown \
        fdleak_cmsg fdleak_creat fdleak_doubleclose0 fdleak_dup fdleak_dup2 \
diff --git a/none/tests/bug514094.c b/none/tests/bug514094.c
new file mode 100644 (file)
index 0000000..d5fcd29
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <limits.h>
+#include "../../config.h"
+
+int main(int argc, char** argv)
+{
+   char buf[PATH_MAX];
+   memset(buf, 0, PATH_MAX);
+#if defined(VGO_solaris)
+   int ret = readlink("/proc/self/path/a.out", buf, PATH_MAX);
+#else
+   // Linux, and maybe one day NetBSD
+   // other platforms excluded by .vgtest prereq
+   int ret = readlink("/proc/self/exe", buf, PATH_MAX);
+#endif
+   if (argc > 1) {
+      printf("ret = %d, buf = %.64s\n", ret, buf);
+   }
+   char resolved[PATH_MAX];
+   realpath(argv[0], resolved);
+   assert(strcmp(resolved, buf) == 0);
+}
+
diff --git a/none/tests/bug514094.stderr.exp b/none/tests/bug514094.stderr.exp
new file mode 100644 (file)
index 0000000..139597f
--- /dev/null
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/bug514094.vgtest b/none/tests/bug514094.vgtest
new file mode 100644 (file)
index 0000000..292428c
--- /dev/null
@@ -0,0 +1,2 @@
+prereq: ../../tests/os_test solaris || ../../tests/os_test linux
+prog: bug514094