Skip to content

Reachable unwrap() in resolve_unix_socket_addr when SocketNode downcast fails #231

@nuczyc

Description

@nuczyc

Describe the bug

A kernel panic occurs in modules/ruxnet/src/address.rs at line 84 when a user attempts to perform a Unix domain socket operation (e.g., connect) on a path that exists but is not a socket file (e.g., a regular file).

let socket_node = Arc::downcast::<SocketNode>(node.as_any_arc()).unwrap();

To Reproduce

  1. Compile the program and run.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>

/*
 * PoC for triggering unwrap() panic in resolve_unix_socket_addr
 * 
 * The crash occurs when:
 * 1. A Unix socket address is resolved
 * 2. The path lookup succeeds but returns a non-SocketNode
 * 3. Arc::downcast::<SocketNode>() fails and unwrap() panics
 * 
 * This PoC attempts to trigger the condition by:
 * 1. Creating a regular file at the socket path
 * 2. Attempting to connect to it as a Unix domain socket
 * 3. This should cause the lookup to succeed but downcast to fail
 */

int main() {
    const char *socket_path = "/tmp/test_socket";
    struct sockaddr_un addr;
    int sock;
    
    // Remove any existing file at the path
    unlink(socket_path);
    
    // Create a regular file at the socket path (not a socket)
    int fd = open(socket_path, O_CREAT | O_WRONLY, 0644);
    if (fd < 0) {
        perror("open");
        return 1;
    }
    write(fd, "not a socket", 12);
    close(fd);
    
    // Create a Unix domain socket
    sock = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        unlink(socket_path);
        return 1;
    }
    
    // Set up the address structure
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
    
    // Attempt to connect to the path
    // This should trigger resolve_unix_socket_addr in the kernel
    // The lookup will find our regular file, causing downcast to fail
    printf("Attempting to connect to regular file as Unix socket...\n");
    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("connect");
        // Expected to fail, but may trigger the panic first
    }
    
    close(sock);
    unlink(socket_path);
    
    printf("PoC completed\n");
    return 0;
}

2.features.txt

alloc
paging
net
multitask
irq
fs

Environment

Logs

SeaBIOS (version 1.16.3-debian-1.16.3-2)


iPXE (https://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+7EFCAA40+7EF0AA40 CA00
                                                                               


Booting from ROM..
Initialize IDT & GDT...

8888888b.                     .d88888b.   .d8888b.
888   Y88b                   d88P" "Y88b d88P  Y88b
888    888                   888     888 Y88b.
888   d88P 888  888 888  888 888     888  "Y888b.
8888888P"  888  888 `Y8bd8P' 888     888     "Y88b.
888 T88b   888  888   X88K   888     888       "888
888  T88b  Y88b 888 .d8""8b. Y88b. .d88P Y88b  d88P
888   T88b  "Y88888 888  888  "Y88888P"   "Y8888P"

arch = x86_64
platform = x86_64-qemu-q35
target = x86_64-unknown-none
smp = 1
build_mode = debug
log_level = warn

[  0.184992 0 axfs_ramfs::dir:68] AlreadyExists sys
Attempting to connect to regular file as Unix socket...
[  0.185845 0:1 ruxruntime::lang_items:14] panicked at modules/ruxnet/src/address.rs:84:82:
called `Result::unwrap()` on an `Err` value: Any { .. }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions