commit f326d68d762edf4b0e9604daa446b6f8ca25725a Author: Mark Wielaard Date: Sun Jul 26 22:40:22 2020 +0200 epoll_ctl warns for uninitialized padding on non-amd64 64bit arches struct vki_epoll_event is packed on x86_64, but not on other 64bit arches. This means that on 64bit arches there can be padding in the epoll_event struct. Seperately the data field is only used by user space (which might not set the data field if it doesn't need to). Only check the events field on epoll_ctl. But assume both events and data are both written to by epoll_[p]wait (exclude padding). https://bugs.kde.org/show_bug.cgi?id=422623 diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 5b5b7eee6..929a4d9af 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -2099,8 +2099,29 @@ PRE(sys_epoll_ctl) SARG1, ( ARG2<3 ? epoll_ctl_s[ARG2] : "?" ), SARG3, ARG4); PRE_REG_READ4(long, "epoll_ctl", int, epfd, int, op, int, fd, struct vki_epoll_event *, event); - if (ARG2 != VKI_EPOLL_CTL_DEL) - PRE_MEM_READ( "epoll_ctl(event)", ARG4, sizeof(struct vki_epoll_event) ); + if (ARG2 != VKI_EPOLL_CTL_DEL) { + /* Just check the events field, the data field is for user space and + unused by the kernel. */ + struct vki_epoll_event *event = (struct vki_epoll_event *) ARG4; + PRE_MEM_READ( "epoll_ctl(event)", (Addr) &event->events, + sizeof(__vki_u32) ); + } +} + +/* RES event records have been written (exclude padding). */ +static void epoll_post_helper ( ThreadId tid, SyscallArgs* arrghs, + SyscallStatus* status ) +{ + vg_assert(SUCCESS); + if (RES > 0) { + Int i; + struct vki_epoll_event **events = (struct vki_epoll_event**)(Addr)ARG2; + for (i = 0; i < RES; i++) { + /* Assume both events and data are set (data is user space only). */ + POST_FIELD_WRITE(events[i]->events); + POST_FIELD_WRITE(events[i]->data); + } + } } PRE(sys_epoll_wait) @@ -2111,13 +2132,12 @@ PRE(sys_epoll_wait) PRE_REG_READ4(long, "epoll_wait", int, epfd, struct vki_epoll_event *, events, int, maxevents, int, timeout); + /* Assume all (maxevents) events records should be (fully) writable. */ PRE_MEM_WRITE( "epoll_wait(events)", ARG2, sizeof(struct vki_epoll_event)*ARG3); } POST(sys_epoll_wait) { - vg_assert(SUCCESS); - if (RES > 0) - POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ; + epoll_post_helper (tid, arrghs, status); } PRE(sys_epoll_pwait) @@ -2130,15 +2150,14 @@ PRE(sys_epoll_pwait) int, epfd, struct vki_epoll_event *, events, int, maxevents, int, timeout, vki_sigset_t *, sigmask, vki_size_t, sigsetsize); + /* Assume all (maxevents) events records should be (fully) writable. */ PRE_MEM_WRITE( "epoll_pwait(events)", ARG2, sizeof(struct vki_epoll_event)*ARG3); if (ARG5) PRE_MEM_READ( "epoll_pwait(sigmask)", ARG5, sizeof(vki_sigset_t) ); } POST(sys_epoll_pwait) { - vg_assert(SUCCESS); - if (RES > 0) - POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ; + epoll_post_helper (tid, arrghs, status); } PRE(sys_eventfd) commit b74f9f23c8758c77367f18368ea95baa858544cb Author: Mark Wielaard Date: Tue Aug 18 23:58:55 2020 +0200 Fix epoll_ctl setting of array event and data fields. Fix for https://bugs.kde.org/show_bug.cgi?id=422623 in commit ecf5ba119 epoll_ctl warns for uninitialized padding on non-amd64 64bit arches contained a bug. A pointer to an array is not a pointer to a pointer to an array. Found by a Fedora user: https://bugzilla.redhat.com/show_bug.cgi?id=1844778#c10 diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 0850487e9..3f488795a 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -2115,11 +2115,11 @@ static void epoll_post_helper ( ThreadId tid, SyscallArgs* arrghs, vg_assert(SUCCESS); if (RES > 0) { Int i; - struct vki_epoll_event **events = (struct vki_epoll_event**)(Addr)ARG2; + struct vki_epoll_event *events = (struct vki_epoll_event*)(Addr)ARG2; for (i = 0; i < RES; i++) { /* Assume both events and data are set (data is user space only). */ - POST_FIELD_WRITE(events[i]->events); - POST_FIELD_WRITE(events[i]->data); + POST_FIELD_WRITE(events[i].events); + POST_FIELD_WRITE(events[i].data); } } }