From 1730250a86f5231e2136113597ad01131ed57dde Mon Sep 17 00:00:00 2001 From: Vladimir Stoilov Date: Wed, 5 Jun 2024 14:57:22 +0300 Subject: [PATCH] [windows_kext] Remove inbound ALE layer --- windows_kext/driver/src/ale_callouts.rs | 57 ++++++------------- windows_kext/driver/src/callouts.rs | 18 ------ windows_kext/driver/src/packet_callouts.rs | 44 ++++++-------- .../wdk/src/filter_engine/callout_data.rs | 9 +-- 4 files changed, 35 insertions(+), 93 deletions(-) diff --git a/windows_kext/driver/src/ale_callouts.rs b/windows_kext/driver/src/ale_callouts.rs index 4d4e8a7e..8e4d3070 100644 --- a/windows_kext/driver/src/ale_callouts.rs +++ b/windows_kext/driver/src/ale_callouts.rs @@ -7,10 +7,7 @@ use smoltcp::wire::{ IpAddress, IpProtocol, Ipv4Address, Ipv6Address, IPV4_HEADER_LEN, IPV6_HEADER_LEN, }; use wdk::filter_engine::callout_data::CalloutData; -use wdk::filter_engine::layer::{ - self, FieldsAleAuthConnectV4, FieldsAleAuthConnectV6, FieldsAleAuthRecvAcceptV4, - FieldsAleAuthRecvAcceptV6, ValueType, -}; +use wdk::filter_engine::layer::{self, FieldsAleAuthConnectV4, FieldsAleAuthConnectV6, ValueType}; use wdk::filter_engine::net_buffer::NetBufferList; use wdk::filter_engine::packet::{Injector, TransportPacketList}; @@ -87,24 +84,6 @@ pub fn ale_layer_connect_v4(data: CalloutData) { ale_layer_auth(data, ale_data); } -pub fn ale_layer_accept_v4(data: CalloutData) { - type Fields = FieldsAleAuthRecvAcceptV4; - let ale_data = AleLayerData { - is_ipv6: false, - reauthorize: data.is_reauthorize(Fields::Flags as usize), - process_id: data.get_process_id().unwrap_or(0), - protocol: get_protocol(&data, Fields::IpProtocol as usize), - direction: Direction::Inbound, - local_ip: get_ipv4_address(&data, Fields::IpLocalAddress as usize), - local_port: data.get_value_u16(Fields::IpLocalPort as usize), - remote_ip: get_ipv4_address(&data, Fields::IpRemoteAddress as usize), - remote_port: data.get_value_u16(Fields::IpRemotePort as usize), - interface_index: data.get_value_u32(Fields::InterfaceIndex as usize), - sub_interface_index: data.get_value_u32(Fields::SubInterfaceIndex as usize), - }; - ale_layer_auth(data, ale_data); -} - pub fn ale_layer_connect_v6(data: CalloutData) { type Fields = FieldsAleAuthConnectV6; @@ -125,24 +104,6 @@ pub fn ale_layer_connect_v6(data: CalloutData) { ale_layer_auth(data, ale_data); } -pub fn ale_layer_accept_v6(data: CalloutData) { - type Fields = FieldsAleAuthRecvAcceptV6; - let ale_data = AleLayerData { - is_ipv6: true, - reauthorize: data.is_reauthorize(Fields::Flags as usize), - process_id: data.get_process_id().unwrap_or(0), - protocol: get_protocol(&data, Fields::IpProtocol as usize), - direction: Direction::Inbound, - local_ip: get_ipv6_address(&data, Fields::IpLocalAddress as usize), - local_port: data.get_value_u16(Fields::IpLocalPort as usize), - remote_ip: get_ipv6_address(&data, Fields::IpRemoteAddress as usize), - remote_port: data.get_value_u16(Fields::IpRemotePort as usize), - interface_index: data.get_value_u32(Fields::InterfaceIndex as usize), - sub_interface_index: data.get_value_u32(Fields::SubInterfaceIndex as usize), - }; - ale_layer_auth(data, ale_data); -} - fn ale_layer_auth(mut data: CalloutData, ale_data: AleLayerData) { let Some(device) = crate::entry::get_device() else { return; @@ -287,7 +248,21 @@ fn save_packet( ale_data: &AleLayerData, pend: bool, ) -> Result { - let packet_list = create_packet_list(device, callout_data, ale_data); + let mut packet_list = None; + let mut save_packet_list = true; + match ale_data.protocol { + IpProtocol::Tcp => { + if let Direction::Outbound = ale_data.direction { + // Only time a packet data is missing is during connect state of outbound TCP connection. + // Don't save packet list only if connection is outbound, reauthorize is false and the protocol is TCP. + save_packet_list = ale_data.reauthorize; + } + } + _ => {} + }; + if save_packet_list { + packet_list = create_packet_list(device, callout_data, ale_data); + } if pend && matches!(ale_data.protocol, IpProtocol::Tcp | IpProtocol::Udp) { match callout_data.pend_operation(packet_list) { Ok(classify_defer) => Ok(Packet::AleLayer(classify_defer)), diff --git a/windows_kext/driver/src/callouts.rs b/windows_kext/driver/src/callouts.rs index 71701692..0999a707 100644 --- a/windows_kext/driver/src/callouts.rs +++ b/windows_kext/driver/src/callouts.rs @@ -20,15 +20,6 @@ pub fn get_callout_vec() -> Vec { FilterType::Resettable, ale_callouts::ale_layer_connect_v4, ), - Callout::new( - "AleLayerInboundV4", - "ALE layer for inbound connections for ipv4", - 0xc6021395_0724_4e2c_ae20_3dde51fc3c68, - Layer::AleAuthRecvAcceptV4, - consts::FWP_ACTION_CALLOUT_TERMINATING, - FilterType::Resettable, - ale_callouts::ale_layer_accept_v4, - ), Callout::new( "AleLayerOutboundV6", "ALE layer for outbound connections for ipv6", @@ -38,15 +29,6 @@ pub fn get_callout_vec() -> Vec { FilterType::Resettable, ale_callouts::ale_layer_connect_v6, ), - Callout::new( - "AleLayerInboundV6", - "ALE layer for inbound connections for ipv6", - 0xd24480da_38fa_4099_9383_b5c83b69e4f2, - Layer::AleAuthRecvAcceptV6, - consts::FWP_ACTION_CALLOUT_TERMINATING, - FilterType::Resettable, - ale_callouts::ale_layer_accept_v6, - ), // ----------------------------------------- // ALE connection end layers Callout::new( diff --git a/windows_kext/driver/src/packet_callouts.rs b/windows_kext/driver/src/packet_callouts.rs index 6736a628..f4491092 100644 --- a/windows_kext/driver/src/packet_callouts.rs +++ b/windows_kext/driver/src/packet_callouts.rs @@ -13,7 +13,6 @@ use crate::connection_cache::ConnectionCache; use crate::connection_map::Key; use crate::device::{Device, Packet}; use crate::packet_util::{get_key_from_nbl_v4, get_key_from_nbl_v6, Redirect}; -use crate::{err, warn}; // IP packet layers pub fn ip_packet_layer_outbound_v4(data: CalloutData) { @@ -141,7 +140,7 @@ fn ip_packet_layer( } { Ok(key) => key, Err(err) => { - warn!("failed to get key from nbl: {}", err); + crate::warn!("failed to get key from nbl: {}", err); return; } }; @@ -151,7 +150,7 @@ fn ip_packet_layer( return; } - let mut is_tmp_verdict = false; + let mut send_request_to_portmaster = true; let mut process_id = 0; if matches!( @@ -164,13 +163,17 @@ fn ip_packet_layer( process_id = conn_info.process_id; // Check if there is action for this connection. match conn_info.verdict { - Verdict::Undecided | Verdict::Accept | Verdict::Block | Verdict::Drop => { - is_tmp_verdict = true + Verdict::Undecided | Verdict::Accept | Verdict::Block | Verdict::Drop => {} + Verdict::PermanentAccept => { + send_request_to_portmaster = false; + data.action_permit(); + } + Verdict::PermanentBlock => { + send_request_to_portmaster = false; + data.action_block(); } - Verdict::PermanentAccept => data.action_permit(), - Verdict::PermanentBlock => data.action_block(), Verdict::Undeterminable | Verdict::PermanentDrop | Verdict::Failed => { - data.block_and_absorb() + data.block_and_absorb(); } Verdict::RedirectNameServer | Verdict::RedirectTunnel => { if let Some(redirect_info) = conn_info.redirect_info.take() { @@ -186,10 +189,10 @@ fn ip_packet_layer( Ok(mut packet) => { let _ = packet.redirect(redirect_info); if let Err(err) = device.inject_packet(packet, false) { - err!("failed to inject packet: {}", err); + crate::err!("failed to inject packet: {}", err); } } - Err(err) => err!("failed to clone packet: {}", err), + Err(err) => crate::err!("failed to clone packet: {}", err), } } @@ -198,25 +201,11 @@ fn ip_packet_layer( continue; } } - } else { - // TCP and UDP always need to go through ALE layer first. - if matches!(direction, Direction::Inbound) { - // If it's an inbound packet and the connection is not found, we need to continue to ALE layer - data.action_permit(); - return; - } else { - // This happens sometimes. Leave the decision for portmaster. TODO(vladimir): Find out why. - err!("Invalid state for: {}", key); - is_tmp_verdict = true; - } } - } else { - // Every other protocol treat as a tmp verdict. - is_tmp_verdict = true; } - // Clone packet and send to Portmaster if it's a temporary verdict. - if is_tmp_verdict { + // Clone packet and send to Portmaster. + if send_request_to_portmaster { let packet = match clone_packet( device, nbl, @@ -228,7 +217,7 @@ fn ip_packet_layer( ) { Ok(p) => p, Err(err) => { - err!("failed to clone packet: {}", err); + crate::err!("failed to clone packet: {}", err); return; } }; @@ -236,6 +225,7 @@ fn ip_packet_layer( let info = device .packet_cache .push((key, packet), process_id, direction, false); + // Send to Portmaster if let Some(info) = info { let _ = device.event_queue.push(info); diff --git a/windows_kext/wdk/src/filter_engine/callout_data.rs b/windows_kext/wdk/src/filter_engine/callout_data.rs index 82039e47..c09be368 100644 --- a/windows_kext/wdk/src/filter_engine/callout_data.rs +++ b/windows_kext/wdk/src/filter_engine/callout_data.rs @@ -32,13 +32,8 @@ impl ClassifyDefer { unsafe { match self { ClassifyDefer::Initial(context, packet_list) => { - if let Some(packet) = packet_list { - FwpsCompleteOperation0(context, packet.net_buffer_list.nbl as _); - return Ok(Some(packet)); - } else { - FwpsCompleteOperation0(context, core::ptr::null_mut()); - } - return Ok(None); + FwpsCompleteOperation0(context, core::ptr::null_mut()); + return Ok(packet_list); } ClassifyDefer::Reauthorization(_callout_id, packet_list) => { // There is no way to reset single filter. If another request for filter reset is trigger at the same time it will fail.