/memcheck/tests/linux/dlclose_leak_so.so
/memcheck/tests/linux/getregset
/memcheck/tests/linux/ioctl-tiocsig
+/memcheck/tests/linux/ioctl_procmap_query
/memcheck/tests/linux/lsframe1
/memcheck/tests/linux/lsframe2
/memcheck/tests/linux/Makefile
508030 Add several missing syscall hooks to ppc64-linux
508093 VALGRIND_CLO_CHANGE does not update vex_control
508145 ppc64le needs ld.so hardwire for strcmp
+508328 Memory allegedly uninitialized after ioctl(PROCMAP_QUERY)
508154 PRE(sys_fchownat) not handling VKI_AT_FDCWD
508638 Self-hosting not working on FreeBSD
508777 amd64-linux: add minimal scalar test
AM_CONDITIONAL(HAVE_NR_IO_PGETEVENTS, [test x$ac_have_nr_io_pgetevents = xyes])
+AC_MSG_CHECKING([for PROCMAP_QUERY])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <linux/fs.h>
+]], [[
+return PROCMAP_QUERY
+]])], [
+ac_have_procmap_query=yes
+AC_MSG_RESULT([yes])
+], [
+ac_have_procmap_query=no
+AC_MSG_RESULT([no])
+])
+
+AM_CONDITIONAL(HAVE_PROCMAP_QUERY, [test x$ac_have_procmap_query = xyes])
+
#----------------------------------------------------------------------------
# Checking for supported compiler flags.
#----------------------------------------------------------------------------
case VKI_EVIOCGRAB:
/* This just takes an int argument. */
break;
+ case VKI_PROCMAP_QUERY: {
+ /* https://www.kernel.org/doc/html/latest/filesystems/proc.html */
+ /* linux source: include/uapi/linux/fs.h:561 */
+ struct vki_procmap_query *pq =
+ (struct vki_procmap_query *)(Addr)ARG3;
+ if (!ML_(safe_to_deref) (pq, sizeof(struct vki_procmap_query)))
+ break;
+ PRE_FIELD_READ("ioctl(PROCMAP_QUERY).size", pq->size);
+ PRE_FIELD_READ("ioctl(PROCMAP_QUERY).query_flags", pq->query_flags);
+ PRE_FIELD_READ("ioctl(PROCMAP_QUERY).query_addr", pq->query_addr);
+ PRE_FIELD_READ("ioctl(PROCMAP_QUERY).vma_name_size", pq->vma_name_size);
+ PRE_FIELD_READ("ioctl(PROCMAP_QUERY).vma_name_addr", pq->vma_name_addr);
+ PRE_FIELD_READ("ioctl(PROCMAP_QUERY).build_id_size", pq->build_id_size);
+ PRE_FIELD_READ("ioctl(PROCMAP_QUERY).build_id_addr", pq->build_id_addr);
+ if (pq->vma_name_size > 0)
+ PRE_MEM_WRITE("ioctl(PROCMAP_QUERY)", (Addr)pq->vma_name_addr, pq->vma_name_size);
+ if (pq->build_id_size > 0)
+ PRE_MEM_WRITE("ioctl(PROCMAP_QUERY)", (Addr)pq->build_id_addr, pq->build_id_size);
+ break;
+ }
default:
/* EVIOC* are variable length and return size written on success */
case VKI_PTP_ENABLE_PPS:
case VKI_PTP_PIN_SETFUNC:
break;
+ case VKI_PROCMAP_QUERY: {
+ /* https://www.kernel.org/doc/html/latest/filesystems/proc.html */
+ /* linux source: include/uapi/linux/fs.h:561 */
+ struct vki_procmap_query *pq =
+ (struct vki_procmap_query *)(Addr)ARG3;
+ if (pq->vma_name_size > 0)
+ POST_MEM_WRITE(pq->vma_name_addr, pq->vma_name_size);
+ if (pq->build_id_size > 0)
+ POST_MEM_WRITE(pq->build_id_addr, pq->build_id_size);
+ /* assume everything is written/defined with POST_MEM_WRITE */
+ /* instead of doing individual POST_FIELD_WRITEs */
+ POST_MEM_WRITE((Addr)pq, pq->size);
+ break;
+ }
default:
/* EVIOC* are variable length and return size written on success */
#define VKI_ION_IOC_CUSTOM \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 6, struct vki_ion_custom_data)
+struct vki_procmap_query {
+ __vki_u64 size;
+ __vki_u64 query_flags; /* in */
+ __vki_u64 query_addr; /* in */
+ __vki_u64 vma_start; /* out */
+ __vki_u64 vma_end; /* out */
+ __vki_u64 vma_flags; /* out */
+ __vki_u64 vma_page_size; /* out */
+ __vki_u64 vma_offset; /* out */
+ __vki_u64 inode; /* out */
+ __vki_u32 dev_major; /* out */
+ __vki_u32 dev_minor; /* out */
+ __vki_u32 vma_name_size; /* in/out */
+ __vki_u32 build_id_size; /* in/out */
+ __vki_u64 vma_name_addr; /* in */
+ __vki_u64 build_id_addr; /* in */
+};
+
+// linux/fs.h
+#define VKI_PROCFS_IOCTL_MAGIC 'f'
+
+#define VKI_PROCMAP_QUERY \
+ _VKI_IOWR(VKI_PROCFS_IOCTL_MAGIC, 17, struct vki_procmap_query)
+
//----------------------------------------------------------------------
// From include/uapi/linux/sync_file.h 6.10.3
//----------------------------------------------------------------------
include $(top_srcdir)/Makefile.tool-tests.am
-dist_noinst_SCRIPTS = filter_stderr
+dist_noinst_SCRIPTS = filter_stderr \
+ filter_ioctl_procmap_query
EXTRA_DIST = \
aligned_alloc.vgtest aligned_alloc.stderr.exp \
dlclose_leak-no-keep.vgtest \
dlclose_leak.stderr.exp dlclose_leak.stdout.exp \
dlclose_leak.vgtest \
+ ioctl_procmap_query.stderr.exp \
+ ioctl_procmap_query.stdout.exp \
+ ioctl_procmap_query.vgtest \
ioctl-tiocsig.vgtest ioctl-tiocsig.stderr.exp \
lsframe1.vgtest lsframe1.stdout.exp lsframe1.stderr.exp \
lsframe2.vgtest lsframe2.stdout.exp lsframe2.stderr.exp \
enomem \
memalign
+if HAVE_PROCMAP_QUERY
+check_PROGRAMS += ioctl_procmap_query
+endif
+
if HAVE_OPENSSL
check_PROGRAMS += bug480706
endif
--- /dev/null
+#! /bin/sh
+
+# drop the 3rd (last) line of the output, since it's a
+# binary blob (build_id) which needs to be printed but
+# not checked
+/usr/bin/head -2
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <unistd.h>
+#include <string.h>
+
+int main(int argc, char** argv)
+{
+ char name[256];
+ char buildid[256];
+ char cwd[256];
+ getcwd(cwd, sizeof(cwd));
+
+ struct procmap_query pq = {
+ .size = sizeof(pq), .query_addr = (uintptr_t)main,
+ .vma_name_size = 256, .vma_name_addr = (uintptr_t)name,
+ .build_id_size = 256, .build_id_addr = (uintptr_t)buildid
+ };
+ int fd = open("/proc/self/maps", O_RDONLY);
+ ioctl(fd, PROCMAP_QUERY, &pq);
+ // print name but strip off the PWD prefix so that
+ // we always get a known output we can easily check
+ puts(name + strlen(cwd) + 1);
+ // buildid is a binary blob, not NUL terminated C string
+ buildid[pq.build_id_size-1] = '\0';
+ // make sure that kernel returned some reasonable build_id_size
+ if (pq.build_id_size > 0 && pq.build_id_size < 256)
+ puts("OK");
+ // print the buildid so that the bug can trigger
+ puts(buildid);
+}
+
--- /dev/null
+ioctl_procmap_query
+OK
--- /dev/null
+prog: ioctl_procmap_query
+vgopts: -q
+stdout_filter: filter_ioctl_procmap_query
+prereq: test -x ioctl_procmap_query