如何确定 Rust 中进程的有效用户 ID?

Posted

技术标签:

【中文标题】如何确定 Rust 中进程的有效用户 ID?【英文标题】:How to determine the effective user id of a process in Rust? 【发布时间】:2020-01-16 23:57:42 【问题描述】:

在 Linux 和其他 POSIX 系统上,程序可以在另一个用户的身份下执行(即euid)。通常,您会调用geteuid 和朋友来可靠地确定进程的当前身份。但是,我无法找到一种可靠的方法来仅使用 rust 的标准库来确定这些身份。

我发现唯一接近的是std::os::unix::MetadataExt

目前是否可以使用 rust 的标准库来确定进程的euid(和其他 ID)?是否有我缺少的功能或特征?

【问题讨论】:

也许doc.rust-lang.org/1.9.0/libc/fn.geteuid.html ? 【参考方案1】:

这将依赖于特定于操作系统的依赖项,因为对于您可以为其构建 rust 代码的大多数目标,该概念不存在(或做您认为会做的事!)。特别是,您会在libc crate 中找到它,顾名思义,它是libc 的一个非常小的包装器。

std::os 命名空间通常被限制在最低限度,以使 std::processstd::threadstd::fs 模块的进程和 FS 功能可用。因此,它不会在那里。出于类似的原因,MetadataExt 的目标是文件系统的使用。

正如您所料,调用本身就是geteuid

这是一个不安全的 extern 导入,因此您必须将其包装在 unsafe 块中。

【讨论】:

是的,Rust 似乎还没有公开这些信息。我会接受你的回答,并在下面添加一个不依赖于 crates.io 的答案。【参考方案2】:

Rust 1.46.0 似乎没有在标准库中公开此功能。如果您使用的是 POSIX 系统并且不想依赖额外的依赖项,您有四个选择:

    你可以直接使用libc:

    #[link(name = "c")]
    extern "C" 
        fn geteuid() -> u32;
        fn getegid() -> u32;
    
    

    如果您特别使用 GNU/Linux,则根本不需要链接到 libc,因为系统调用符号会通过 VDSO 自动提供给您的程序。换句话说,您可以使用没有link 属性的普通extern 块。

    阅读/proc/self/status(可能仅限Linux?)。此文件包含以Uid: 开头的行。此行列出了真实用户 ID、有效用户 ID 以及您可能还认为相关的其他信息。更多信息请参考man proc

    如果您使用的是普通的 GNU/Linux 系统,则可以访问 /proc/self 目录本身的元数据。作为pointed out in this question,此目录的所有者应与进程的有效用户标识匹配。您可以通过以下方式获取euid:

    use std::os::unix::fs::MetadataExt;
    println!("metadata for :?", std::fs::metadata("/proc/self").map(|m| m.uid()));
    

    这种方法提供的一个好处是,与选项 #2 相比,它相对便宜,因为它只是一个 stat 系统调用(而不是打开文件并读取/解析其内容)。

    如果您使用的不是普通的 GNU/Linux 系统,您可能会成功创建一个新的虚拟文件并正常通过 Metadata 获取所有者 ID。

【讨论】:

以上是关于如何确定 Rust 中进程的有效用户 ID?的主要内容,如果未能解决你的问题,请参考以下文章

Linux进程的实际用户ID和有效用户ID

进程控制

如何中止 Rust 进程?

进程控制---更改进程的用户ID和组ID

linux进程标识符具体解释1

在 Rust 中写入子进程的标准输入?