C

socat:EXEC 沒有正確中繼

  • December 27, 2021

我有一個小程序,它首先向使用者輸出一個字元串,然後接受一個輸入。相反,我希望程序通過從埠發送和接收來工作。為了嘗試實現這一點,我執行了命令socat TCP4-LISTEN:1337,reuseaddr,fork EXEC:./program。通過這個命令,我希望能夠執行nc 127.0.0.1 1337並期望程序:

  1. 接收來自程序的消息
  2. 能夠提供輸入
  3. 失去聯繫

但是,當使用socat它執行程序時,就像這樣

  1. 提供輸入
  2. 從程序收到的消息
  3. 給另一個輸入
  4. 失去了連接

我不明白為什麼會這樣。我使用該socat命令有什麼問題嗎?如果是,請告訴我缺少/錯誤的內容。

這是程序。

#include <stdio.h>

void vuln(void) {
   printf("Input\n");
   char buffer[256];
   gets(buffer); // potential buffer overflow
}

int main(void) {
   vuln();
   return 0;
}

在 C 中,printf是緩衝 I/O 庫的一部分——寫入流的數據在記憶體中“緩衝”(即,不直接寫入核心)。

預設情況下,stdoutprintf寫入數據的流)是行緩衝流,這意味著字節儲存在記憶體緩衝區中,直到將換行符寫入流(或者其他一些甚至觸髮刷新的事件)。

如果標準輸出不與終端相關聯,stdout則為塊緩衝流,這意味著字節儲存在記憶體緩衝區中,直到緩衝區變滿。

當您在終端執行程序時,'\n'呼叫中的printf觸髮刷新(因為它是行緩衝的):

$ ./a.out
Input
whatever-you-type
$

如果將輸出重定向到文件,您將看到不同的行為:

Terminal 1               Terminal 2
--------------------     --------------------
$ ./a.out > /tmp/out
                        $ cat /tmp/out
                        $
type-input
$
                        $ cat /tmp/out
                        Input
                        $ 

當你沒有執行socatpts,輸出流處於塊緩沖模式;當您使用pts輸出流執行它時,它處於行緩沖模式。

如果您想覆蓋該行為,您有幾個選擇。您可以呼叫函式來顯式刷新任何緩衝數據:

printf("Input\n");
fflush(stdout);

或者,您可以在呼叫之前顯式設置輸出流的緩沖模式printf

setvbuf(stdout, NULL, _IONBF, 0); // _IONBF = Unbuffered
printf("Input\n");

有關更詳細的解釋,請參閱 Robert Love 的書Linux System Programming的第 3 章。

引用自:https://unix.stackexchange.com/questions/680406