ioctl handling needs to do POST handling on generic ioctls and needs to handle BPF ioctls
bz#312989

Patch by Guy Harris <guy@alum.mit.edu>

On OS X 10.10

Before:

== 593 tests, 214 stderr failures, 10 stdout failures, 0 stderrB failures, 0 stdoutB failures, 30 post failures ==

After:

== 593 tests, 214 stderr failures, 10 stdout failures, 0 stderrB failures, 0 stdoutB failures, 30 post failures ==


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15451 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index f5a8043..6d95f95 100644
--- a/NEWS
+++ b/NEWS
@@ -121,6 +121,8 @@
 302630  Memcheck on multithreaded program fails with Assertion 
         'sizeof(UWord) == sizeof(UInt)' failed in m_syscall.c
         == 326797
+312989  ioctl handling needs to do POST handling on generic ioctls and
+        needs to handle BPF ioctls
 319274  Fix unhandled syscall: unix:410 (sigsuspend_nocancel) on OS X
 324181  mmap does not handle MAP_32BIT (handle it now, rather than fail it)
 327745  Fix valgrind 3.9.0 build fails on Mac OS X 10.6.8
diff --git a/coregrind/m_syswrap/syswrap-darwin.c b/coregrind/m_syswrap/syswrap-darwin.c
index d109d8a..0bb2600 100644
--- a/coregrind/m_syswrap/syswrap-darwin.c
+++ b/coregrind/m_syswrap/syswrap-darwin.c
@@ -1106,6 +1106,8 @@
    case VKI_TIOCPTYGRANT:
    case VKI_TIOCPTYUNLK:
    case VKI_DTRACEHIOC_REMOVE: 
+   case VKI_BIOCFLUSH:
+   case VKI_BIOCPROMISC:
       PRINT("ioctl ( %ld, 0x%lx )",ARG1,ARG2);
       PRE_REG_READ2(long, "ioctl",
                     unsigned int, fd, unsigned int, request);
@@ -1291,6 +1293,71 @@
    case VKI_FIONCLEX:
        break;
 
+       // net/bpf.h
+   case VKI_BIOCSETF:            /* set BPF filter               */
+      /*
+       * struct bpf_program has a 32-bit count of instructions,
+       * followed by a pointer to an array of those instructions.
+       * In 64-bit mode, there's padding between those two elements.
+       *
+       * So that we don't bogusly complain about the padding bytes,
+       * we just report that we read bf_len and and bf_insns.
+       *
+       * We then make sure that what bf_insns points to is valid.
+       */
+      PRE_MEM_READ( "ioctl(BIOCSETF)",
+                     (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_len,
+                     sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_len) );
+      PRE_MEM_READ( "ioctl(BIOCSETF)",
+                     (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_insns,
+                     sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_insns) );
+      if ( ARG3 ) {
+         /* bf_len * sizeof (*bf_insns) */
+         struct vki_bpf_program *bp = (struct vki_bpf_program *)ARG3;
+         if ( bp->bf_insns != NULL )
+           PRE_MEM_READ( "ioctl(BIOCSETF) points to a struct bpf_program whose bf_insns member",
+                          (Addr)(bp->vki_bf_insns),
+                          bp->vki_bf_len * sizeof(*bp->vki_bf_insns) );
+      }
+      break;
+   case VKI_BIOCSETIF:           /* set BPF interface            */
+      PRE_MEM_RASCIIZ( "ioctl(BIOCSETIF)",
+                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
+      break;
+   case VKI_BIOCSRTIMEOUT:       /* set BPF timeout              */
+      /*
+       * 64-bit struct timeval starts with a 64-bit "seconds since the
+       * Epoch" value, followed by a 32-bit microseconds value.  The
+       * resulting structure is padded to a multiple of 8 bytes, so
+       * there are 4 padding bytes at the end.
+       *
+       * So that we don't bogusly complain about the padding bytes,
+       * we just report that we read tv_sec and tv_usec.
+       */
+      PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
+                     (Addr)&((struct vki_timeval *)ARG3)->vki_tv_sec,
+                     sizeof(((struct vki_timeval *)ARG3)->vki_tv_sec) );
+      PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
+                     (Addr)&((struct vki_timeval *)ARG3)->vki_tv_usec,
+                     sizeof(((struct vki_timeval *)ARG3)->vki_tv_usec) );
+      break;
+   case VKI_BIOCGDLTLIST:        /* get list of BPF DLTs         */
+      PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
+                     (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list,
+                     sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list) );
+      if ( ARG3 ) {
+         /* bfl_len * sizeof (*bfl_list) */
+         struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
+         if ( bdl->bfl_list != NULL )
+           PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
+                          (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len,
+                          sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len) );
+           PRE_MEM_WRITE( "ioctl(BIOCGDLTLIST) points to a struct bpf_dltlist whose bfl_list member",
+                          (Addr)(bdl->vki_bfl_list),
+                          bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
+      }
+      break;
+
    default: 
       ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
       break;
@@ -1417,7 +1484,19 @@
    case VKI_TIOCPTYUNLK:
        break;
 
+       // bpf.h
+   case VKI_BIOCGDLTLIST:        /* get list of BPF DLTs         */
+      if (RES == 0 && ARG3 ) {
+         /* bfl_len * sizeof (*bfl_list) */
+         struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
+         if ( bdl->vki_bfl_list != NULL )
+           POST_MEM_WRITE( (Addr)(bdl->vki_bfl_list),
+                           bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
+      }
+      break;
+
    default:
+      ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
       break;
    }
 }
diff --git a/include/vki/vki-darwin.h b/include/vki/vki-darwin.h
index 7ff7c5b..e831b1b 100644
--- a/include/vki/vki-darwin.h
+++ b/include/vki/vki-darwin.h
@@ -112,6 +112,8 @@
 
 #define vki_timeval timeval
 #define vki_timeval32 timeval32
+#define vki_tv_sec tv_sec
+#define vki_tv_usec tv_usec
 #define vki_timespec timespec
 #define vki_itimerval itimerval
 #define vki_timezone timezone
@@ -1001,6 +1003,23 @@
 #define VKI_DTRACEHIOC_ADDDOF   DTRACEHIOC_ADDDOF
 
 
+#include <net/bpf.h>
+
+#define vki_bpf_program bpf_program
+#define vki_bf_len bf_len
+#define vki_bf_insns bf_insns
+#define vki_bpf_dltlist bpf_dltlist
+#define vki_bfl_len bfl_len
+#define vki_bfl_list bfl_list
+
+#define VKI_BIOCSETF        BIOCSETF
+#define VKI_BIOCFLUSH       BIOCFLUSH
+#define VKI_BIOCPROMISC     BIOCPROMISC
+#define VKI_BIOCSETIF       BIOCSETIF
+#define VKI_BIOCSRTIMEOUT   BIOCSRTIMEOUT
+#define VKI_BIOCGDLTLIST    BIOCGDLTLIST
+
+
 #include <sys/ucontext.h>
 
 /* quite why sys/ucontext.h provides a 'struct __darwin_ucontext'