3

我正在读取另一个生成输出(缓慢且无限)的进程的输出。因为我想实时读取这些数据,所以我使用“stdbuf -oL”(行缓冲,数据是文本)。我无法控制生成过程,因此我无法修改源以强制刷新。

到目前为止 stdbuf 工作得很好,但是该进程使用 SOCK_RAW 并且需要以 root 身份运行,具有 setuid(0) 或cap_net_raw功能。当使用 setuid 或功能以非 root 身份运行时,stdbuf 似乎被忽略了。让我演示一下这个问题:

这是一个简单的作家:

#include <stdio.h>
#include <unistd.h>

int main(){
        int i;
        for ( i = 0;; i++){
                fprintf(stdout, "%d\n", i);
                sleep(1);
        }
}

和一个简单的读者:

#include <stdio.h>

int main(){
        char* line = NULL;
        size_t n = 0;
        while (getline(&line, &n, stdin) != -1 ) {
                fputs(line, stdout);
        }
}

正如预期的那样,./writer | ./reader在缓冲区填满之前,什么都不显示。前置stdbuf -oL启用行缓冲,我将这些行输入阅读器:

% stdbuf -oL ./writer | ./reader
0
1
2
...

但是,如果我添加cap_net_raw+ep它会停止工作:

% sudo setcap cap_net_raw+ep ./writer
% stdbuf -oL ./writer | ./reader
(no output)

使用 setuid 时观察到相同的行为:

% sudo chown root:root ./writer
% sudo chmod +s ./writer
% stdbuf -oL ./writer | ./reader
(no output)

我有兴趣了解为什么会发生这种情况以及如何在不以 root 身份运行的情况下继续使用 stdbuf。我承认我并不完全了解 setuid 在幕后所做的事情。

4

2 回答 2

3

通过查看stdbuf 源代码,它看起来可以通过设置 LD_PRELOAD 来工作。将 LD_PRELOAD 与 setuid 可执行文件或 sudo 一起使用当然存在安全问题。

我发现的一个建议是禁用可执行文件的 noatsecure selinux 属性

另一个更简单的选择是避免使用 stdbuf 并直接fflush(stdout)从您的源代码中调用。

于 2012-11-30T16:28:12.753 回答
2

没有解决方案LD_PRELOAD

您可以使用作为( ) 包unbuffer一部分的实用程序。是一个非常短的期望脚本。它不需要,因为它使用了另一个技巧。创建一个伪终端(如or ),因此使用执行的进程被愚弄认为它正在写入交互式设备,因此默认情况下它在.expectexpect-develunbufferLD_PRELOADexpectxtermsshunbufferstdout

在您的情况下使用:

unbuffer ./writer | ./reader

如果stdbuf与该程序一起使用,则unbuffer很有可能也可以使用。因为LD_PRELOAD提出了一些限制unbuffer,比stdbuf. 相反,stdbuf它将适用于这些类型的可执行文件:

  • 设置
  • 具有文件功能
  • 静态链接
  • 不使用标准libc
于 2013-09-04T21:33:58.403 回答