Skip to content

Commit 13f6ea3

Browse files
author
Bryant Mairs
committed
Fix UB in epoll_ctl
When passing None as an argument to `epoll_ctl`, UB is elicited within the `Into<&EpollEvent>` impl because it passes a null pointer as a `&mut EpollEvent`. Instead we remove that implementation completely and handle this case directly within the `epoll_ctl` function. Thanks to Arnavion for helping to debug this.
1 parent edf1bac commit 13f6ea3

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

src/sys/epoll.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,6 @@ impl EpollEvent {
6565
}
6666
}
6767

68-
impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
69-
#[inline]
70-
fn into(self) -> &'a mut EpollEvent {
71-
match self {
72-
Some(epoll_event) => epoll_event,
73-
None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
74-
}
75-
}
76-
}
77-
7868
#[inline]
7969
pub fn epoll_create() -> Result<RawFd> {
8070
let res = unsafe { libc::epoll_create(1024) };
@@ -91,13 +81,19 @@ pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
9181

9282
#[inline]
9383
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
94-
where T: Into<&'a mut EpollEvent>
84+
where T: Into<Option<&'a mut EpollEvent>>
9585
{
96-
let event: &mut EpollEvent = event.into();
97-
if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
86+
let mut event: Option<&mut EpollEvent> = event.into();
87+
if event.is_none() && op != EpollOp::EpollCtlDel {
9888
Err(Error::Sys(Errno::EINVAL))
9989
} else {
100-
let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
90+
let res = unsafe {
91+
if let Some(ref mut event) = event {
92+
libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
93+
} else {
94+
libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
95+
}
96+
};
10197
Errno::result(res).map(drop)
10298
}
10399
}

0 commit comments

Comments
 (0)