Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
R
relibc
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 33
    • Issues 33
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 18
    • Merge Requests 18
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • redox-os
  • relibc
  • Issues
  • #159

Closed
Open
Opened Oct 23, 2019 by Boqin Qin@BurtonQin

Use After Free Bugs in netdb

Following #130 (closed) That bug is briefed as follows:

  1. Create a local vector host_alias
  2. Call as_mut_slice() and then as_mut_ptr(), to get the ptr
  3. Store the ptr to a global struct HOST_ENTRY.
  4. host_alias is out of scope and is dropped.
  5. Now The ptr inside HOST_ENTRY is dangling!

The fix is to store the local variable to a global variable _HOST_ALIASES = Some(host_aliases) to prevent dropping of host_alias.

Based on the pattern of that bug, I searched the whole project and found 4 more similar bugs. All of them are in src/header/netdb/mod.rs.

  1. In function gethostbyaddr()

https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/header/netdb/mod.rs#L218-242

    let mut host_aliases: Vec<*mut i8> = Vec::new();
    host_aliases.push(ptr::null_mut());
    HOST_ALIASES = Some(_host_aliases);  // You did not store host_aliases, but _host_aliases!
...
            HOST_ENTRY = hostent {
                h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
                h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8  // Store ptr to HOST_ENTRY
...
// host_aliases is droped, HOST_ENTRY.h_aliases dangles!
  1. In function gethostbyname()

https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/header/netdb/mod.rs#L322-336

    let mut host_aliases: Vec<*mut i8> = Vec::new();
    host_aliases.push(ptr::null_mut());
    host_aliases.push(ptr::null_mut());
    HOST_ALIASES = Some(_host_aliases);  // You did not store host_aliases, but _host_aliases!

    HOST_ENTRY = hostent {
        h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
        h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,  // Store ptr to HOST_ENTRY
        h_addrtype: AF_INET,
        h_length: 4,
        h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
    };
...
// host_aliases is dropped, HOST_ENTRY.h_aliases dangles!
  1. In function getprotoent()

https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/header/netdb/mod.rs#L443-456

    let mut proto_aliases: Vec<*mut i8> = _proto_aliases
        .iter_mut()
        .map(|x| x.as_mut_ptr() as *mut i8)
        .collect();
    proto_aliases.push(ptr::null_mut());

    PROTO_ALIASES = Some(_proto_aliases);  // You did not store proto_aliases, but _proto_aliases!
    PROTO_NAME = Some(proto_name);

    PROTO_ENTRY = protoent {
        p_name: PROTO_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
        p_aliases: proto_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,  // Store ptr to PROTO_ENTRY
        p_proto: PROTO_NUM.unwrap(),
    };
...
// proto_aliases is dropped, PROTO_ENTRY.p_aliases dangles!
  1. In function getservent()

https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/header/netdb/mod.rs#L587-600

        let mut serv_aliases: Vec<*mut i8> = Vec::new();
        serv_aliases.push(ptr::null_mut());
        serv_aliases.push(ptr::null_mut());

        SERV_ALIASES = Some(_serv_aliases);  // You did not store serv_aliases, but _serv_aliases!
        SERV_NAME = Some(serv_name);
        SERV_PROTO = Some(proto);

        SERV_ENTRY = servent {
            s_name: SERV_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
            s_aliases: serv_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,  // Store ptr to SERV_ENTRY
            s_port: SERV_PORT.unwrap(),
            s_proto: SERV_PROTO.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
        };
...
// s_aliases is dropped, SERV_ENTRY.s_aliases dangles!
Edited Apr 23, 2020 by Boqin Qin
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: redox-os/relibc#159