Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stdbuf with setuid/capabilities

I am reading output from another process which generates output (slow and infinite). Because I want to read this data in real-time I use "stdbuf -oL" (line-buffered, data is text). I do not have control of the generating process so I cannot modify the source to force flushing.

So far stdbuf works just fine, however the process uses SOCK_RAW and needs either to be run as root, have setuid(0) or the cap_net_raw capability. When running as non-root with setuid or capabilities stdbuf seems to be ignored. Let me demonstrate the problem:

This is a simple writer:

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

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

And a simple reader:

#include <stdio.h>

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

As expected, by executing ./writer | ./reader nothing shows up until the buffer is filled. Prepending stdbuf -oL enables line-buffering and I get the lines into the reader:

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

But if I add cap_net_raw+ep it stops working:

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

The same behaviour is observed when using setuid:

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

I'm interested in understanding why this happens and how I can continue to use stdbuf without running as root. I admit that I do not fully understand what setuid is doing behind the scenes.

like image 563
ext Avatar asked Sep 14 '25 22:09

ext


1 Answers

From looking at the stdbuf source code it looks like it works by setting LD_PRELOAD. There are of course security concerns using LD_PRELOAD with setuid executables or sudo.

One suggestion I found was to disable the noatsecure selinux attribute for your executable.

Another, simpler, option would be to avoid stdbuf and simply call fflush(stdout) from your source code directly.

like image 86
Ben Kelly Avatar answered Sep 17 '25 13:09

Ben Kelly