Skip to content

Commit dc56e0f

Browse files
authored
Fix panic on dropping RecvAncillaryBuffer after failed recvmsg (#676)
* Fix panic on dropping `RecvAncillaryBuffer` after failed `recvmsg` Calling drain on `RecvAncillaryBuffer`, including in its `Drop` implementation was failing, with an "attempted to subtract with overflow" error in `cvt_msg`. If `recvmsg` returns `-1`, `msg_controllen` will not be updated by the call. So it had a non-zero value as passed into the function, despite there not being any control messages to parse. * Clear any messages from `RecvAncillaryBuffer` at start of recv This should prevent leaks of file descriptors if the `RecvAncillaryBuffer` is re-used for multiple reads.
1 parent 1caf903 commit dc56e0f

File tree

3 files changed

+24
-11
lines changed

3 files changed

+24
-11
lines changed

src/backend/libc/net/msghdr.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::super::c;
77
use super::super::conv::{msg_control_len, msg_iov_len};
88
use super::super::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
99

10-
use crate::io::{IoSlice, IoSliceMut};
10+
use crate::io::{self, IoSlice, IoSliceMut};
1111
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6};
1212
use crate::utils::as_ptr;
1313

@@ -19,8 +19,10 @@ pub(crate) fn with_recv_msghdr<R>(
1919
name: &mut MaybeUninit<c::sockaddr_storage>,
2020
iov: &mut [IoSliceMut<'_>],
2121
control: &mut RecvAncillaryBuffer<'_>,
22-
f: impl FnOnce(&mut c::msghdr) -> R,
23-
) -> R {
22+
f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
23+
) -> io::Result<R> {
24+
control.clear();
25+
2426
let namelen = size_of::<c::sockaddr_storage>() as c::socklen_t;
2527
let mut msghdr = {
2628
let mut h: c::msghdr = unsafe { zeroed() };
@@ -36,8 +38,10 @@ pub(crate) fn with_recv_msghdr<R>(
3638
let res = f(&mut msghdr);
3739

3840
// Reset the control length.
39-
unsafe {
40-
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
41+
if res.is_ok() {
42+
unsafe {
43+
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
44+
}
4145
}
4246

4347
res

src/backend/linux_raw/net/msghdr.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use super::super::c;
99
use super::super::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
1010

11-
use crate::io::{IoSlice, IoSliceMut};
11+
use crate::io::{self, IoSlice, IoSliceMut};
1212
use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6};
1313
use crate::utils::as_ptr;
1414

@@ -31,8 +31,10 @@ pub(crate) fn with_recv_msghdr<R>(
3131
name: &mut MaybeUninit<c::sockaddr_storage>,
3232
iov: &mut [IoSliceMut<'_>],
3333
control: &mut RecvAncillaryBuffer<'_>,
34-
f: impl FnOnce(&mut c::msghdr) -> R,
35-
) -> R {
34+
f: impl FnOnce(&mut c::msghdr) -> io::Result<R>,
35+
) -> io::Result<R> {
36+
control.clear();
37+
3638
let namelen = size_of::<c::sockaddr_storage>() as c::c_int;
3739
let mut msghdr = c::msghdr {
3840
msg_name: name.as_mut_ptr().cast(),
@@ -49,8 +51,10 @@ pub(crate) fn with_recv_msghdr<R>(
4951
let res = f(&mut msghdr);
5052

5153
// Reset the control length.
52-
unsafe {
53-
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
54+
if res.is_ok() {
55+
unsafe {
56+
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
57+
}
5458
}
5559

5660
res

src/net/send_recv/msg.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ impl<'buf> RecvAncillaryBuffer<'buf> {
248248
self.read = 0;
249249
}
250250

251+
/// Delete all messages from the buffer.
252+
pub(crate) fn clear(&mut self) {
253+
self.drain().for_each(drop);
254+
}
255+
251256
/// Drain all messages from the buffer.
252257
pub fn drain(&mut self) -> AncillaryDrain<'_> {
253258
AncillaryDrain {
@@ -260,7 +265,7 @@ impl<'buf> RecvAncillaryBuffer<'buf> {
260265

261266
impl Drop for RecvAncillaryBuffer<'_> {
262267
fn drop(&mut self) {
263-
self.drain().for_each(drop);
268+
self.clear();
264269
}
265270
}
266271

0 commit comments

Comments
 (0)