Fix relibc netdb/lookup: use-after-move and unsafe block errors
Upstream relibc netdb DNS lookup has two bugs exposed by Rust 2024 edition
strict unsafe handling:
1. packet_data is moved into Box::via into_boxed_slice() but the retry
loop tries to call packet_data.as_ptr() on the moved value. Use the
already-created raw pointer packet_data_ptr instead.
2. close() is a safe function in relibc, so wrapping it in unsafe{}
triggers unused-unsafe (promoted to error by -D unused-unsafe). Remove
the unnecessary unsafe blocks around close() calls.
Patch carries in local/patches/relibc/P3-netdb-lookup-retry-fix.patch and
is applied via the relibc recipe patches list.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
diff --git a/src/header/netdb/lookup.rs b/src/header/netdb/lookup.rs
|
||||
index 0734eec6..1789bc2e 100644
|
||||
--- a/src/header/netdb/lookup.rs
|
||||
+++ b/src/header/netdb/lookup.rs
|
||||
@@ -15,9 +15,10 @@ use crate::header::{
|
||||
bits_timespec::timespec,
|
||||
errno::*,
|
||||
netinet_in::{IPPROTO_UDP, in_addr, sockaddr_in},
|
||||
+ sys_select::timeval,
|
||||
sys_socket::{
|
||||
self,
|
||||
- constants::{AF_INET, SOCK_DGRAM},
|
||||
+ constants::{AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_RCVTIMEO},
|
||||
sockaddr,
|
||||
},
|
||||
time,
|
||||
@@ -89,11 +90,37 @@ pub fn lookup_host(host: &str) -> Result<LookupHost, c_int> {
|
||||
drop(Box::from_raw(packet_data_ptr));
|
||||
}
|
||||
|
||||
- let i = 0 as socklen_t;
|
||||
+ // Prevent indefinite blocking when DNS server is unreachable (5s timeout).
|
||||
+ unsafe {
|
||||
+ let tv = timeval {
|
||||
+ tv_sec: 5,
|
||||
+ tv_usec: 0,
|
||||
+ };
|
||||
+ let _ = sys_socket::setsockopt(
|
||||
+ sock,
|
||||
+ SOL_SOCKET,
|
||||
+ SO_RCVTIMEO,
|
||||
+ ptr::from_ref(&tv) as *const c_void,
|
||||
+ mem::size_of::<timeval>() as socklen_t,
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
let mut buf = vec![0u8; 65536];
|
||||
let buf_ptr = buf.as_mut_ptr().cast::<c_void>();
|
||||
|
||||
- let count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) };
|
||||
+ let mut count: isize = -1;
|
||||
+ for attempt in 0..2 {
|
||||
+ if attempt > 0 {
|
||||
+ if unsafe { sys_socket::send(sock, packet_data_ptr as *const c_void, packet_data_len, 0) } < 0 {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) };
|
||||
+ if count >= 0 {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ let _ = crate::header::unistd::close(sock);
|
||||
if count < 0 {
|
||||
return Err(EIO);
|
||||
}
|
||||
@@ -197,7 +224,34 @@ pub fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>, c_int> {
|
||||
let mut buf = [0u8; 65536];
|
||||
let buf_ptr = buf.as_mut_ptr().cast::<c_void>();
|
||||
|
||||
- let count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) };
|
||||
+ // Prevent indefinite blocking when DNS server is unreachable (5s timeout).
|
||||
+ unsafe {
|
||||
+ let tv = timeval {
|
||||
+ tv_sec: 5,
|
||||
+ tv_usec: 0,
|
||||
+ };
|
||||
+ let _ = sys_socket::setsockopt(
|
||||
+ sock,
|
||||
+ SOL_SOCKET,
|
||||
+ SO_RCVTIMEO,
|
||||
+ ptr::from_ref(&tv) as *const c_void,
|
||||
+ mem::size_of::<timeval>() as socklen_t,
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ let mut count: isize = -1;
|
||||
+ for attempt in 0..2 {
|
||||
+ if attempt > 0 {
|
||||
+ if unsafe { sys_socket::send(sock, packet_data_ptr as *const c_void, packet_data_len, 0) } < 0 {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) };
|
||||
+ if count >= 0 {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ let _ = crate::header::unistd::close(sock);
|
||||
if count < 0 {
|
||||
return Err(EIO);
|
||||
}
|
||||
@@ -14,6 +14,7 @@ patches = [
|
||||
"../../../local/patches/relibc/P3-ifaddrs-net_if.patch",
|
||||
"../../../local/patches/relibc/P3-fd-event-tests.patch",
|
||||
"../../../local/patches/relibc/P3-eventfd-mod.patch",
|
||||
"../../../local/patches/relibc/P3-netdb-lookup-retry-fix.patch",
|
||||
]
|
||||
|
||||
[build]
|
||||
|
||||
Reference in New Issue
Block a user