pub(super) fn open_mem_fd<T: Task>(task: &mut T) -> bool {
    // Use ptrace to read/write during open_mem_fd
    task.vm().set_mem_fd(ScopedFd::new());

    if !task.is_stopped {
        log!(
            LogWarn,
            "Can't retrieve mem fd for {}; process not stopped, racing with exec?",
            task.tid
        );
        return false;
    }

    // We could try opening /proc/<pid>/mem directly first and
    // only do this dance if that fails. But it's simpler to
    // always take this path, and gives better test coverage. On Ubuntu
    // the child has to open its own mem file (unless rr is root).
    let path = CStr::from_bytes_with_nul(b"/proc/self/mem\0").unwrap();

    let arch = task.arch();
    let mut remote = AutoRemoteSyscalls::new(task);
    let remote_fd: i32;
    {
        let mut remote_path: AutoRestoreMem = AutoRestoreMem::push_cstr(&mut remote, path);
        if remote_path.get().is_some() {
            let remote_arch = remote_path.arch();
            let remote_addr = remote_path.get().unwrap();

            // AutoRestoreMem DerefMut-s to AutoRemoteSyscalls
            // skip leading '/' since we want the path to be relative to the root fd
            remote_fd = rd_syscall!(
                remote_path,
                syscall_number_for_openat(remote_arch),
                RD_RESERVED_ROOT_DIR_FD,
                // Skip the leading '/' in the path as this is a relative path.
                (remote_addr + 1usize).as_usize(),
                libc::O_RDWR
            ) as i32;
        } else {
            remote_fd = -ESRCH;
        }
    }
    let mut fd: ScopedFd = ScopedFd::new();
    if remote_fd != -ESRCH {
        if remote_fd < 0 {
            // This can happen when a process fork()s after setuid; it can no longer
            // open its own /proc/self/mem. Hopefully we can read the child's
            // mem file in this case (because rd is probably running as root).
            let buf: String = format!("/proc/{}/mem", remote.task().tid);
            fd = ScopedFd::open_path(Path::new(&buf), OFlag::O_RDWR);
        } else {
            fd = rd_arch_function!(remote, retrieve_fd_arch, arch, remote_fd);
            // Leak fd if the syscall fails due to the task being SIGKILLed unexpectedly
            rd_syscall!(remote, syscall_number_for_close(remote.arch()), remote_fd);
        }
    }
    if !fd.is_open() {
        log!(
            LogInfo,
            "Can't retrieve mem fd for {}; process no longer exists?",
            remote.task().tid
        );
        return false;
    }
    remote.task().vm().set_mem_fd(fd.try_into().unwrap());
    true
}
/// Forwarded method definition
///
/// Open /proc/{tid}/mem fd for our AddressSpace, closing the old one
/// first. If necessary we force the tracee to open the file
/// itself and smuggle the fd back to us.
/// Returns false if the process no longer exists.
Forwarded method definition
Open /proc/{tid}/mem fd for our AddressSpace, closing the old one
first. If necessary we force the tracee to open the file
itself and smuggle the fd back to us.
Returns false if the process no longer exists.
Forwarded method definition Open / proc / { tid } / mem fd for our AddressSpace closing the old one first . If necessary we force the tracee to open the file itself and smuggle the fd back to us . Returns false if the process no longer exists .
pub(super) fn open_mem_fd<T: Task>(task: &mut T) -> bool {
    // Use ptrace to read/write during open_mem_fd
    task.vm().set_mem_fd(ScopedFd::new());
    if !task.is_stopped {
        log!(
            LogWarn,
            "Can't retrieve mem fd for {}; process not stopped, racing with exec?",
            task.tid
        );
        return false;
    }
    // We could try opening /proc/<pid>/mem directly first and
    // only do this dance if that fails. But it's simpler to
    // always take this path, and gives better test coverage. On Ubuntu
    // the child has to open its own mem file (unless rr is root).
    let path = CStr::from_bytes_with_nul(b"/proc/self/mem\0").unwrap();
    let arch = task.arch();
    let mut remote = AutoRemoteSyscalls::new(task);
    let remote_fd: i32;
    {
        let mut remote_path: AutoRestoreMem = AutoRestoreMem::push_cstr(&mut remote, path);
        if remote_path.get().is_some() {
            let remote_arch = remote_path.arch();
            let remote_addr = remote_path.get().unwrap();
            // AutoRestoreMem DerefMut-s to AutoRemoteSyscalls
            // skip leading '/' since we want the path to be relative to the root fd
            remote_fd = rd_syscall!(
                remote_path,
                syscall_number_for_openat(remote_arch),
                RD_RESERVED_ROOT_DIR_FD,
                // Skip the leading '/' in the path as this is a relative path.
                (remote_addr + 1usize).as_usize(),
                libc::O_RDWR
            ) as i32;
        } else {
            remote_fd = -ESRCH;
        }
    }
    let mut fd: ScopedFd = ScopedFd::new();
    if remote_fd != -ESRCH {
        if remote_fd < 0 {
            // This can happen when a process fork()s after setuid; it can no longer
            // open its own /proc/self/mem. Hopefully we can read the child's
            // mem file in this case (because rd is probably running as root).
            let buf: String = format!("/proc/{}/mem", remote.task().tid);
            fd = ScopedFd::open_path(Path::new(&buf), OFlag::O_RDWR);
        } else {
            fd = rd_arch_function!(remote, retrieve_fd_arch, arch, remote_fd);
            // Leak fd if the syscall fails due to the task being SIGKILLed unexpectedly
            rd_syscall!(remote, syscall_number_for_close(remote.arch()), remote_fd);
        }
    }
    if !fd.is_open() {
        log!(
            LogInfo,
            "Can't retrieve mem fd for {}; process no longer exists?",
            remote.task().tid
        );
        return false;
    }
    remote.task().vm().set_mem_fd(fd.try_into().unwrap());
    true
}
pub ( super ) fn open_mem_fd < T : Task > ( task : & mut T ) -> bool { // Use ptrace to read/write during open_mem_fd task . vm ( ) . set_mem_fd ( ScopedFd :: new ( ) ) ; if ! task . is_stopped { log ! ( LogWarn " " task tid ) ; return false ; } // We could try opening /proc/<pid>/mem directly first and // only do this dance if that fails. But it's simpler to // always take this path, and gives better test coverage. On Ubuntu // the child has to open its own mem file (unless rr is root). let path = CStr :: from_bytes_with_nul ( b" \0 " ) . unwrap ( ) ; let arch = task . arch ( ) ; let mut remote = AutoRemoteSyscalls :: new ( task ) ; let remote_fd : i32 ; { let mut remote_path : AutoRestoreMem = AutoRestoreMem :: push_cstr ( & mut remote , path ) ; if remote_path . get ( ) . is_some ( ) { let remote_arch = remote_path . arch ( ) ; let remote_addr = remote_path . get ( ) . unwrap ( ) ; // AutoRestoreMem DerefMut-s to AutoRemoteSyscalls // skip leading '/' since we want the path to be relative to the root fd remote_fd = rd_syscall ! ( remote_path syscall_number_for_openat ( remote_arch ) RD_RESERVED_ROOT_DIR_FD // Skip the leading '/' in the path as this is a relative path. ( remote_addr 1usize ) as_usize ( ) libc O_RDWR ) as i32 ; } else { remote_fd = - ESRCH ; } } let mut fd : ScopedFd = ScopedFd :: new ( ) ; if remote_fd != - ESRCH { if remote_fd < 0 { // This can happen when a process fork()s after setuid; it can no longer // open its own /proc/self/mem. Hopefully we can read the child's // mem file in this case (because rd is probably running as root). let buf : String = format ! ( " " remote task ( ) tid ) ; fd = ScopedFd :: open_path ( Path :: new ( & buf ) , OFlag :: O_RDWR ) ; } else { fd = rd_arch_function ! ( remote retrieve_fd_arch arch remote_fd ) ; // Leak fd if the syscall fails due to the task being SIGKILLed unexpectedly rd_syscall ! ( remote syscall_number_for_close ( remote arch ( ) ) remote_fd ) ; } } if ! fd . is_open ( ) { log ! ( LogInfo " " remote task ( ) tid ) ; return false ; } remote . task ( ) . vm ( ) . set_mem_fd ( fd . try_into ( ) . unwrap ( ) ) ; true }
Forwarded method definition
Open /proc/{tid}/mem fd for our AddressSpace, closing the old one
first.
Forwarded method definition Open / proc / { tid } / mem fd for our AddressSpace closing the old one first .
task
&mut T