From cdc9aa06e3d6d826af2afd0087c9793257c0eecc Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Wed, 17 Jun 2020 18:50:24 +0200 Subject: [PATCH] Fix getpeername Rust's TcpListener fails because of the address format being wrong. The format comes from `accept`, but there we internally use this function. --- src/platform/redox/socket.rs | 43 +++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs index 01d6e8519..ab26d3694 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs @@ -1,4 +1,5 @@ -use core::{mem, ptr, slice, str}; +use alloc::vec::Vec; +use core::{cmp, mem, ptr, slice, str}; use syscall::{self, flag::*, Result}; use super::{ @@ -6,8 +7,9 @@ use super::{ e, Sys, }; use crate::header::{ - netinet_in::{in_port_t, sockaddr_in}, - sys_socket::{constants::*, sockaddr, socklen_t}, + arpa_inet::inet_aton, + netinet_in::{in_port_t, sockaddr_in, in_addr}, + sys_socket::{constants::*, sa_family_t, sockaddr, socklen_t}, sys_time::timeval, sys_un::sockaddr_un, }; @@ -92,7 +94,7 @@ unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut so mem::size_of_val(&data.sun_path), ); - let len = path.len().min(buf.len()); + let len = cmp::min(path.len(), buf.len()); path[..len].copy_from_slice(&buf[..len]); *address_len = len as socklen_t; @@ -109,20 +111,31 @@ unsafe fn inner_af_inet( // Skip the remote part parts.next(); } - let part = parts.next().expect("Invalid reply from netstack"); + let mut unparsed_addr = Vec::from(parts.next().expect("missing address")); - trace!("path: {}", ::core::str::from_utf8_unchecked(&part)); + let sep = memchr::memchr(b':', &unparsed_addr).expect("missing port"); + let (raw_addr, rest) = unparsed_addr.split_at_mut(sep); + let (colon, raw_port) = rest.split_at_mut(1); + let port = str::from_utf8(raw_port).expect("non-utf8 port").parse().expect("invalid port"); - (*address).sa_family = AF_INET as c_ushort; + // Make address be followed by a NUL-byte + colon[0] = b'\0'; - let data = slice::from_raw_parts_mut( - &mut (*address).sa_data as *mut _ as *mut u8, - (*address).sa_data.len(), - ); + trace!("address: {:?}, port: {:?}", str::from_utf8(&raw_addr), port); + + let mut addr = in_addr::default(); + assert_eq!(inet_aton(raw_addr.as_ptr() as *mut i8, &mut addr), 1, "inet_aton might be broken, failed to parse netstack address"); + + let ret = sockaddr_in { + sin_family: AF_INET as sa_family_t, + sin_port: port, + sin_addr: addr, - let len = data.len().min(part.len()); - data[..len].copy_from_slice(&part[..len]); + ..sockaddr_in::default() + }; + let len = cmp::min(*address_len as usize, mem::size_of_val(&ret)); + ptr::copy_nonoverlapping(&ret as *const _ as *const u8, address as *mut u8, len); *address_len = len as socklen_t; } @@ -333,10 +346,10 @@ impl PalSocket for Sys { } eprintln!( - "setsockopt({}, {}, {}, {:p}, {})", + "setsockopt({}, {}, {}, {:p}, {}) - unknown option", socket, level, option_name, option_value, option_len ); - e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int + 0 } fn shutdown(socket: c_int, how: c_int) -> c_int { -- GitLab