]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
readlink[at] syswrap: limit copy to bufsiz when path is proc self exe
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 3 Jan 2026 20:17:00 +0000 (21:17 +0100)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 3 Jan 2026 20:17:00 +0000 (21:17 +0100)
.gitignore
coregrind/m_syswrap/syswrap-generic.c
coregrind/m_syswrap/syswrap-linux.c
none/tests/bug514094.c
none/tests/linux/Makefile.am

index 5ac1f3cb995abe3c126a65de4bfb77497873f361..5754f271f8a22c1c5905291e0e5739bcdf6317dd 100644 (file)
 /none/tests/linux/mremap6
 /none/tests/linux/open_client
 /none/tests/linux/pthread-stack
+/none/tests/linux/readlinkat_self
 /none/tests/linux/stack-overflow
 /none/tests/linux/getdents_filter
 
index c0e717d27641c56ede1d6651bc31cea271c8d590..406e6960b0bb7f76f9b2a151d462247c1b93d9c7 100644 (file)
@@ -5095,6 +5095,7 @@ PRE(sys_readlink)
           && (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, SELF_EXEPATH))) {
          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);
          fuse_may_block = False;
index 10e63348d91ba3f86eebf68b619e32b87e3b43c5..53b620585b5d3d58bc4cd8e7995d5b5d7f991e6b 100644 (file)
@@ -6684,14 +6684,10 @@ PRE(sys_readlinkat)
    ML_(fd_at_check_allowed)(SARG1, (const HChar*)ARG2, "readlinkat", tid, status);
    PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
    PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
-}
 
-POST(sys_readlinkat)
-{
+   Bool fuse_may_block = True;
    HChar name[30];       // large enough
-   Word  saved = SYSNO;
 
-   // @todo PJF why is this done in POST and not in PRE?
    /*
     * Handle the case where readlinkat is looking at /proc/self/exe or
     * /proc/<pid>/exe.
@@ -6700,13 +6696,21 @@ POST(sys_readlinkat)
    if (ML_(safe_to_deref)((void*)(Addr)ARG2, 1)
        && (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0
            || VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/exe") == 0)) {
-      VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
-      SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, (UWord)name, 
-                                               ARG3, ARG4));
+       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);
+       fuse_may_block = False;
    }
 
-   if (SUCCESS && RES > 0)
-      POST_MEM_WRITE( ARG3, RES );
+   if (fuse_may_block)
+      FUSE_COMPATIBLE_MAY_BLOCK();
+}
+
+POST(sys_readlinkat)
+{
+   POST_MEM_WRITE( ARG3, RES );
 }
 
 PRE(sys_fchmodat)
index d5fcd299a70d66cb00f2aa4496c4141ce6423d16..848db1d82ea71004a2382f1c66aa1d1ae0e08fac 100644 (file)
@@ -24,5 +24,17 @@ 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[11];
+   memset(small_buf, '#', 11);
+#if defined(VGO_solaris)
+   ret = readlink("/proc/self/path/a.out", small_buf, 10);
+#else
+   ret = readlink("/proc/self/exe", small_buf, 10);
+#endif
+   assert(strncmp(resolved, small_buf, 10) == 0);
+   assert(small_buf[10] == '#');
+
 }
 
index 519eb7dd6c28f88b7244249c2b5c23d0d59cacfa..20540247f3e09a2221d60b085fc5e0f70c92dcf4 100644 (file)
@@ -20,6 +20,7 @@ EXTRA_DIST = \
        mremap6.stderr.exp mremap6.vgtest \
        open_client.stderr.exp open_client.vgtest \
        pthread-stack.stderr.exp pthread-stack.vgtest \
+       readlinkat_self.stderr.exp readlinkat_self.vgtest \
        stack-overflow.stderr.exp stack-overflow.vgtest
 
 check_PROGRAMS = \
@@ -36,6 +37,7 @@ check_PROGRAMS = \
        mremap5 \
        mremap6 \
        pthread-stack \
+       readlinkat_self \
        stack-overflow
 
 if HAVE_OPENAT2