以编程方式对 child 进程设置各种限制 (Linux)
Set various limits on child process programmatically (Linux)
我知道如何使用 setrlimit() 和 getrlimit() 系统调用。我试图对 child 进程施加一些限制。首先,我分叉了一个 child,然后我在 child 中设置了各种限制,之后我使用 exec 调用将过程映像替换为真实的 child(限制在 exec 调用后仍然存在).我有几个问题:
1.Limiting 内存使用 - 目前我还不清楚应该使用哪个标志。 RLIMIT_DATA 是一个控制 sbrk() 和 brk() 调用的方法,但我发现 glibc malloc 实现使用 mmap(),它由 RLIMIT_AS 标志控制。因此,如果我想将内存使用限制为 16MB,我应该调用:
struct rlimit mlimit;
mlimit.rlim_cur = 1 << 23;
mlimit.rlim_max = mlimit.rlim_cur;
::setrlimit(RLIMIT_DATA, &mlimit);
::setrlimit(RLIMIT_AS, &mlimit);
或者我应该只使用一个选项?
2.Limiting 打开文件描述符的数量 - 如果我想阻止 child 进程打开任何其他文件描述符,除了 stdin , stdout 和 stderr 然后我应该将 RLIMIT_NOFILE 设置为 4(该值比 man 中指定的最大文件描述符数大 1页)?
3.Limiting 文件写入总量 - 有一个 RLIMIT_FSIZE 标志,手册页中说明该标志具有下一个语义:
The maximum size of files that the process may create. Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal.
如果我理解正确的话,这个标志限制了单个文件的最大大小——而不是进程写入的所有文件的累积大小。因此问题是我应该将此标志与 RLIMIT_NOFILE 结合使用来限制总共可以写入磁盘的数据量,还是有更好的方法来做到这一点?
4.Preventing child 更改此限制 - 不受信任的代码将通过 exec 调用执行,所以我想知道此 child 进程是否有办法覆盖限制在 fork() 之后但在 exec 调用之前设置?如果可以做到,我该如何预防?我已经阅读了一些有关功能和 CAP_SYS_RESOURCE 的内容,但我不清楚如何正确地执行它。
这些限制并不准确,使用它们会导致很多问题。特别是:
当您使用 RLIMIT_AS
时,您限制了可以加载到进程中的共享库 - 如果您更新 Glibc,新的 Glibc 可能会超过限制的大小你的程序将不再 运行
对于文件描述符——进程总是可以关闭标准流描述符来打开更多,但是如果你给的太少,动态linker将无法link 在 C 库中。
RLIMIT_FSIZE
将 每个文件 ,如您所见。
setrlimit
文档说非特权进程只能降低硬限制,而不能增加它,因此当您设置硬限制时,该进程或其子进程不能增加它,除非他们有 CAP_SYS_RESOURCE
,默认情况下,非根进程不应该有。
我知道如何使用 setrlimit() 和 getrlimit() 系统调用。我试图对 child 进程施加一些限制。首先,我分叉了一个 child,然后我在 child 中设置了各种限制,之后我使用 exec 调用将过程映像替换为真实的 child(限制在 exec 调用后仍然存在).我有几个问题:
1.Limiting 内存使用 - 目前我还不清楚应该使用哪个标志。 RLIMIT_DATA 是一个控制 sbrk() 和 brk() 调用的方法,但我发现 glibc malloc 实现使用 mmap(),它由 RLIMIT_AS 标志控制。因此,如果我想将内存使用限制为 16MB,我应该调用:
struct rlimit mlimit;
mlimit.rlim_cur = 1 << 23;
mlimit.rlim_max = mlimit.rlim_cur;
::setrlimit(RLIMIT_DATA, &mlimit);
::setrlimit(RLIMIT_AS, &mlimit);
或者我应该只使用一个选项?
2.Limiting 打开文件描述符的数量 - 如果我想阻止 child 进程打开任何其他文件描述符,除了 stdin , stdout 和 stderr 然后我应该将 RLIMIT_NOFILE 设置为 4(该值比 man 中指定的最大文件描述符数大 1页)?
3.Limiting 文件写入总量 - 有一个 RLIMIT_FSIZE 标志,手册页中说明该标志具有下一个语义:
The maximum size of files that the process may create. Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal.
如果我理解正确的话,这个标志限制了单个文件的最大大小——而不是进程写入的所有文件的累积大小。因此问题是我应该将此标志与 RLIMIT_NOFILE 结合使用来限制总共可以写入磁盘的数据量,还是有更好的方法来做到这一点?
4.Preventing child 更改此限制 - 不受信任的代码将通过 exec 调用执行,所以我想知道此 child 进程是否有办法覆盖限制在 fork() 之后但在 exec 调用之前设置?如果可以做到,我该如何预防?我已经阅读了一些有关功能和 CAP_SYS_RESOURCE 的内容,但我不清楚如何正确地执行它。
这些限制并不准确,使用它们会导致很多问题。特别是:
当您使用
RLIMIT_AS
时,您限制了可以加载到进程中的共享库 - 如果您更新 Glibc,新的 Glibc 可能会超过限制的大小你的程序将不再 运行对于文件描述符——进程总是可以关闭标准流描述符来打开更多,但是如果你给的太少,动态linker将无法link 在 C 库中。
RLIMIT_FSIZE
将 每个文件 ,如您所见。
setrlimit
文档说非特权进程只能降低硬限制,而不能增加它,因此当您设置硬限制时,该进程或其子进程不能增加它,除非他们有 CAP_SYS_RESOURCE
,默认情况下,非根进程不应该有。