]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix 376956 syswrap of SNDDRV and DRM_IOCTL_VERSION causing some addresses
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Wed, 15 Mar 2017 19:35:29 +0000 (19:35 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Wed, 15 Mar 2017 19:35:29 +0000 (19:35 +0000)
        to be wrongly marked as addressable

Patch from Daniel Glöckner, slightly modified.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16274

NEWS
coregrind/m_syswrap/syswrap-linux.c
include/pub_tool_basics.h

diff --git a/NEWS b/NEWS
index 8f97b9e7b4cfc181b2dd794f0a894b853d9b2d39..f063378c8ab5dee7eafea39f5b33d99d73f5e5b3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -142,6 +142,8 @@ where XXXXXX is the bug number as listed below.
 376611  ppc64 and arm64 don't know about prlimit64 syscall
 376729  PPC64, remove R2 from the clobber list
         == 371668
+376956  syswrap of SNDDRV and DRM_IOCTL_VERSION causing some addresses
+        to be wrongly marked as addressable
 377427  PPC64, lxv instruction failing on odd destination register 
 377478  PPC64: ISA 3.0 setup fixes
 
index 5a79930aa36ce6e6e85eaf3c8763b5604f1d2c46..a739a5d9dd25f65803120f303e7a202c2ba0780c 100644 (file)
@@ -6069,6 +6069,11 @@ POST(sys_fcntl64)
    ioctl wrappers
    ------------------------------------------------------------------ */
 
+struct vg_drm_version_info {
+   struct vki_drm_version data;
+   struct vki_drm_version *orig; // Original ARG3 pointer value at syscall entry.
+};
+
 PRE(sys_ioctl)
 {
    *flags |= SfMayBlock;
@@ -7686,7 +7691,8 @@ PRE(sys_ioctl)
 
    case VKI_DRM_IOCTL_VERSION:
       if (ARG3) {
-         struct vki_drm_version *data = (struct vki_drm_version *)ARG3;
+         struct vki_drm_version* data = (struct vki_drm_version *)ARG3;
+         struct vg_drm_version_info* info;
         PRE_MEM_WRITE("ioctl(DRM_VERSION).version_major", (Addr)&data->version_major, sizeof(data->version_major));
          PRE_MEM_WRITE("ioctl(DRM_VERSION).version_minor", (Addr)&data->version_minor, sizeof(data->version_minor));
          PRE_MEM_WRITE("ioctl(DRM_VERSION).version_patchlevel", (Addr)&data->version_patchlevel, sizeof(data->version_patchlevel));
@@ -7699,6 +7705,10 @@ PRE(sys_ioctl)
          PRE_MEM_READ("ioctl(DRM_VERSION).desc_len", (Addr)&data->desc_len, sizeof(data->desc_len));
          PRE_MEM_READ("ioctl(DRM_VERSION).desc", (Addr)&data->desc, sizeof(data->desc));
          PRE_MEM_WRITE("ioctl(DRM_VERSION).desc", (Addr)data->desc, data->desc_len);
+         info = VG_(malloc)("syswrap.ioctl.1", sizeof(*info));
+         info->data = *data;
+         info->orig = data;
+         ARG3 = (Addr)&info->data;
       }
       break;
    case VKI_DRM_IOCTL_GET_UNIQUE:
@@ -10174,16 +10184,24 @@ POST(sys_ioctl)
 
    case VKI_DRM_IOCTL_VERSION:
       if (ARG3) {
-         struct vki_drm_version *data = (struct vki_drm_version *)ARG3;
+         struct vki_drm_version* data = (struct vki_drm_version *)ARG3;
+         struct vg_drm_version_info* info = container_of(data, struct vg_drm_version_info, data);
+         const vki_size_t orig_name_len = info->orig->name_len;
+         const vki_size_t orig_date_len = info->orig->date_len;
+         const vki_size_t orig_desc_len = info->orig->desc_len;
+         *info->orig = info->data;
+         ARG3 = (Addr)info->orig;
+         data = info->orig;
+         VG_(free)(info);
         POST_MEM_WRITE((Addr)&data->version_major, sizeof(data->version_major));
          POST_MEM_WRITE((Addr)&data->version_minor, sizeof(data->version_minor));
          POST_MEM_WRITE((Addr)&data->version_patchlevel, sizeof(data->version_patchlevel));
          POST_MEM_WRITE((Addr)&data->name_len, sizeof(data->name_len));
-         POST_MEM_WRITE((Addr)data->name, data->name_len);
+         POST_MEM_WRITE((Addr)data->name, VG_MIN(data->name_len, orig_name_len));
          POST_MEM_WRITE((Addr)&data->date_len, sizeof(data->date_len));
-         POST_MEM_WRITE((Addr)data->date, data->date_len);
+         POST_MEM_WRITE((Addr)data->date, VG_MIN(data->date_len, orig_date_len));
          POST_MEM_WRITE((Addr)&data->desc_len, sizeof(data->desc_len));
-         POST_MEM_WRITE((Addr)data->desc, data->desc_len);
+         POST_MEM_WRITE((Addr)data->desc, VG_MIN(data->desc_len, orig_desc_len));
       }
       break;
    case VKI_DRM_IOCTL_GET_UNIQUE:
index 4712c117cf951fff0934e59d45d034fe32b2e2c9..ebed99123a0c213df36d1a03bf5fe44a3c4a6ee5 100644 (file)
@@ -396,6 +396,10 @@ static inline Bool sr_EQ ( UInt sysno, SysRes sr1, SysRes sr2 ) {
 #   define offsetof(type,memb) ((SizeT)(HWord)&((type*)0)->memb)
 #endif
 
+#if !defined(container_of)
+#   define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
+#endif
+
 /* Alignment */
 /* We use a prefix vg_ for vg_alignof as its behaviour slightly
    differs from the standard alignof/gcc defined __alignof__