aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYuchen Wu <[email protected]>2024-06-12 12:39:28 -0700
committerMatthew (mbg) <[email protected]>2024-06-21 09:54:09 -0700
commit708e03211d8d33b68ffa672fb7c68f1bebd6d08b (patch)
treee2fcc4e3ada25d25217e6bbf3c6b0e9a6650bb9b
parentbf07ed3f10be667b8206a122e28c7f75d7eb3599 (diff)
downloadpingora-708e03211d8d33b68ffa672fb7c68f1bebd6d08b.tar.gz
pingora-708e03211d8d33b68ffa672fb7c68f1bebd6d08b.zip
Auto generate the size and verify it for setsockops calls
This avoids human error with stronger validation.
-rw-r--r--.bleep2
-rw-r--r--pingora-core/src/protocols/l4/ext.rs60
2 files changed, 23 insertions, 39 deletions
diff --git a/.bleep b/.bleep
index 2d45003..ca85d11 100644
--- a/.bleep
+++ b/.bleep
@@ -1 +1 @@
-f9ccfca0b81e38f866d5264559337e474e3fc4d4 \ No newline at end of file
+0061d912ea6f21c2ce205bfa49d4721cbd2aba7f \ No newline at end of file
diff --git a/pingora-core/src/protocols/l4/ext.rs b/pingora-core/src/protocols/l4/ext.rs
index 90ad9ac..5efb1f3 100644
--- a/pingora-core/src/protocols/l4/ext.rs
+++ b/pingora-core/src/protocols/l4/ext.rs
@@ -132,6 +132,24 @@ fn get_opt<T>(
}
#[cfg(target_os = "linux")]
+fn get_opt_sized<T>(sock: c_int, opt: c_int, val: c_int) -> io::Result<T> {
+ let mut payload = mem::MaybeUninit::zeroed();
+ let expected_size = mem::size_of::<T>() as socklen_t;
+ let mut size = expected_size;
+ get_opt(sock, opt, val, &mut payload, &mut size)?;
+
+ if size != expected_size {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "get_opt size mismatch",
+ ));
+ }
+ // Assume getsockopt() will set the value properly
+ let payload = unsafe { payload.assume_init() };
+ Ok(payload)
+}
+
+#[cfg(target_os = "linux")]
fn cvt_linux_error(t: i32) -> io::Result<i32> {
if t == -1 {
Err(io::Error::last_os_error())
@@ -198,22 +216,7 @@ fn set_keepalive(_fd: RawFd, _ka: &TcpKeepalive) -> io::Result<()> {
/// Get the kernel TCP_INFO for the given FD.
#[cfg(target_os = "linux")]
pub fn get_tcp_info(fd: RawFd) -> io::Result<TCP_INFO> {
- let mut tcp_info = unsafe { TCP_INFO::new() };
- let mut data_len: socklen_t = TCP_INFO::len();
- get_opt(
- fd,
- libc::IPPROTO_TCP,
- libc::TCP_INFO,
- &mut tcp_info,
- &mut data_len,
- )?;
- if data_len != TCP_INFO::len() {
- return Err(std::io::Error::new(
- std::io::ErrorKind::Other,
- "TCP_INFO struct size mismatch",
- ));
- }
- Ok(tcp_info)
+ get_opt_sized(fd, libc::IPPROTO_TCP, libc::TCP_INFO)
}
#[cfg(not(target_os = "linux"))]
@@ -235,20 +238,11 @@ pub fn set_recv_buf(_fd: RawFd, _: usize) -> Result<()> {
#[cfg(target_os = "linux")]
pub fn get_recv_buf(fd: RawFd) -> io::Result<usize> {
- let mut recv_size: c_int = 0;
- let mut size = std::mem::size_of::<c_int>() as u32;
- get_opt(
- fd,
- libc::SOL_SOCKET,
- libc::SO_RCVBUF,
- &mut recv_size,
- &mut size,
- )?;
- Ok(recv_size as usize)
+ get_opt_sized::<c_int>(fd, libc::SOL_SOCKET, libc::SO_RCVBUF).map(|v| v as usize)
}
#[cfg(not(target_os = "linux"))]
-pub fn get_recv_buf(_fd: RawFd) -> Result<usize> {
+pub fn get_recv_buf(_fd: RawFd) -> io::Result<usize> {
Ok(0)
}
@@ -283,17 +277,7 @@ pub fn set_tcp_fastopen_backlog(_fd: RawFd, _backlog: usize) -> Result<()> {
#[cfg(target_os = "linux")]
pub fn get_socket_cookie(fd: RawFd) -> io::Result<u64> {
- let mut cookie: c_ulonglong = 0;
- let mut size = std::mem::size_of_val(&cookie) as socklen_t;
- get_opt(
- fd,
- libc::SOL_SOCKET,
- libc::SO_COOKIE,
- &mut cookie,
- &mut size,
- )?;
-
- Ok(cookie as u64)
+ get_opt_sized::<c_ulonglong>(fd, libc::SOL_SOCKET, libc::SO_COOKIE)
}
#[cfg(not(target_os = "linux"))]