Skip to content

proc_self_*() functions can open the wrong process's files #854

@LegionMammal978

Description

@LegionMammal978

Presumably to avoid issues from dereferencing a bind-mounted /proc/self symlink that points somewhere incorrect, the proc_self_*() functions instead open the /proc/{getpid()} directory. However, the /proc/{pid} directories refer to PIDs relative to the /proc mount's PID namespace. Thus, using getpid() can result in the wrong directory if the calling process is in a different PID namespace. For instance, this program prints the contents of /proc/1/status, which is actually the status file of the global PID 1 (systemd on my system):

// rustix = { version = "=0.38.14", features = ["procfs", "thread"] }
use rustix::thread::UnshareFlags;
use std::{fs::File, io, os::unix::process::CommandExt, process::Command};

fn main() -> io::Result<()> {
    rustix::thread::unshare(UnshareFlags::NEWUSER | UnshareFlags::NEWPID)?;
    let mut command = Command::new("");
    unsafe {
        command.pre_exec(|| {
            let mut status = File::from(rustix::procfs::proc_self_status()?);
            io::copy(&mut status, &mut io::stdout())?;
            Err(io::ErrorKind::Other.into())
        });
    }
    let _ = command.spawn();
    Ok(())
}

One solution would be to parse the integer from the /proc/self symlink, then open /proc/{integer} as before. As noted in pid_namespaces(7), it will always point to the current process in the /proc mount's PID namespace (assuming it hasn't been bind-mounted):

Calling readlink(2) on the path /proc/self yields the process ID of the caller in the PID namespace of the procfs mount (i.e., the PID namespace of the process that mounted the procfs). This can be useful for introspection purposes, when a process wants to discover its PID in other namespaces.

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