diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h index 2ae844201..c09dc103a 100644 --- a/coregrind/m_syswrap/priv_syswrap-linux.h +++ b/coregrind/m_syswrap/priv_syswrap-linux.h @@ -295,6 +295,7 @@ extern void ML_(linux_PRE_sys_msgctl) ( TId, UW, UW, UW ); extern void ML_(linux_POST_sys_msgctl) ( TId, UW, UW, UW, UW ); extern void ML_(linux_PRE_sys_getsockopt) ( TId, UW, UW, UW, UW, UW ); extern void ML_(linux_POST_sys_getsockopt) ( TId, SR, UW, UW, UW, UW, UW ); +extern void ML_(linux_PRE_sys_setsockopt) ( TId, UW, UW, UW, UW, UW ); // Linux-specific (but non-arch-specific) ptrace wrapper helpers extern void ML_(linux_PRE_getregset) ( ThreadId, long, long ); diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index a4e4bb773..e73c9855d 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -3842,8 +3842,8 @@ PRE(sys_socketcall) /* int setsockopt(int s, int level, int optname, const void *optval, int optlen); */ PRE_MEM_READ_ef( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) ); - ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2, - ARG2_3, ARG2_4 ); + ML_(linux_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2, + ARG2_3, ARG2_4 ); break; case VKI_SYS_GETSOCKOPT: @@ -4021,7 +4021,7 @@ PRE(sys_setsockopt) PRE_REG_READ5(long, "setsockopt", int, s, int, level, int, optname, const void *, optval, int, optlen); - ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5); + ML_(linux_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5); } PRE(sys_getsockopt) @@ -7771,6 +7771,57 @@ ML_(linux_POST_sys_getsockopt) ( ThreadId tid, } } +void +ML_(linux_PRE_sys_setsockopt) ( ThreadId tid, + UWord arg0, UWord arg1, UWord arg2, + UWord arg3, UWord arg4 ) +{ + /* int setsockopt(int s, int level, int optname, + const void *optval, socklen_t optlen); */ + Addr optval_p = arg3; + if (optval_p != (Addr)NULL) { + /* + * OK, let's handle at least some setsockopt levels and options + * ourselves, so we don't get false claims of references to + * uninitialized memory (such as padding in structures) and *do* + * check what pointers in the argument point to. + */ + if (arg1 == VKI_SOL_SOCKET && arg2 == VKI_SO_ATTACH_FILTER) + { + struct vki_sock_fprog *fp = (struct vki_sock_fprog *)optval_p; + + /* + * struct sock_fprog has a 16-bit count of instructions, + * followed by a pointer to an array of those instructions. + * There's padding between those two elements. + * + * So that we don't bogusly complain about the padding bytes, + * we just report that we read len and and filter. + * + * We then make sure that what filter points to is valid. + */ + PRE_MEM_READ( "setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, &optval.len)", + (Addr)&fp->len, sizeof(fp->len) ); + PRE_MEM_READ( "setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, &optval.filter)", + (Addr)&fp->filter, sizeof(fp->filter) ); + + /* len * sizeof (*filter) */ + if (fp->filter != NULL) + { + PRE_MEM_READ( "setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, optval.filter)", + (Addr)(fp->filter), + fp->len * sizeof(*fp->filter) ); + } + } + else + { + PRE_MEM_READ( "socketcall.setsockopt(optval)", + arg3, /* optval */ + arg4 /* optlen */ ); + } + } +} + /* --------------------------------------------------------------------- ptrace wrapper helpers ------------------------------------------------------------------ */ diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index c9aa0477a..63cd50149 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -680,8 +680,11 @@ __KINLINE struct vki_cmsghdr * vki_cmsg_nxthdr (struct vki_msghdr *__msg, struct #define VKI_MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */ +#define VKI_SOL_SOCKET 1 #define VKI_SOL_SCTP 132 +#define VKI_SO_ATTACH_FILTER 26 + //---------------------------------------------------------------------- // From linux-2.6.8.1/include/linux/in.h //---------------------------------------------------------------------- @@ -3139,6 +3142,22 @@ struct vki_file_handle { unsigned char f_handle[0]; }; +//---------------------------------------------------------------------- +// From linux-3.2.0/include/linux/filter.h +//---------------------------------------------------------------------- + +struct vki_sock_filter { + __vki_u16 code; /* Actual filter code */ + __vki_u8 jt; /* Jump true */ + __vki_u8 jf; /* Jump false */ + __vki_u32 k; /* Generic multiuse field */ +}; + +struct vki_sock_fprog { + __vki_u16 len; /* actually unsigned short */ + struct vki_sock_filter *filter; +}; + #endif // __VKI_LINUX_H /*--------------------------------------------------------------------*/