如何欺騙進程認為文件不存在?

如何欺騙進程認為文件不存在?

我有一個程式儲存其設置,~/.config/myprogram我可以互動式地使用該程式並與批次排隊系統一起使用。當交互運行時,我希望這個程式使用我的設定檔(它確實如此)。但在批次模式下運行時,不需要配置文件,因為我指定了覆蓋所有相關設定的命令列選項。此外,透過網路存取設定檔會使程式的啟動時間增加幾秒鐘;如果檔案不存在,程式啟動速度會更快(因為每個作業只需要大約一分鐘,這對批次作業吞吐量有重大影響)。但因為我也以互動方式使用該程序,所以我不想一直移動/刪除我的設定檔。根據我的批次作業在叢集上安排的時間(基於其他使用者的使用情況),我可能希望以互動方式使用該程序,同時作為批次作業的一部分。

(旁白:網路檔案效能如此緩慢可能是個錯誤,但我只是叢集的用戶,所以我只能解決它,而不能修復它。)

我可以建立一個不讀取設定檔(或具有不讀取設定檔的命令列選項)的程式版本以供批次使用,但該程式的建置環境設計不佳且難以設定。我更喜歡使用透過系統的套件管理器安裝的二進位檔案。

如何欺騙該程式的特定實例假裝我的設定檔不存在(無需修改程式)?我希望有一個 form 的包裝器 pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...,但我對其他解決方案持開放態度。

答案1

該程式可能會解析從 到該檔案的路徑$HOME/.config/myprogram。所以你可以告訴它你的主目錄在其他地方,例如:

HOME=/nowhere your-program

現在,也許您的程式需要主目錄中的一些其他資源。如果您知道它們是什麼,您可以為您的程式準備一個假主頁,其中包含指向該程式所需資源的連結。

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram

答案2

如果所有其他方法都失敗,請編寫您將注入的包裝器庫,LD_PRELOAD以便攔截調用open("/home/you/my-program/config.interactive"),但任何其他調用都會通過。這適用於任何類型的程序,甚至是 shell 腳本,因為它會過濾系統呼叫。

extern int errno;

int open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    return get_real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}

注意:我尚未測試此程式碼,而且我不能 100% 確定該errno部分是否有效。

看看怎麼樣fakerootgetuid(2)對於和等調用執行此操作stat(2)

基本上,連結器會將該應用程式連結到您的庫,從而覆寫該open符號。由於您不能使用您自己的庫中命名的兩個不同的函數open,因此您必須將其分隔在第二部分(例如get_real_open)中,該部分將依次連結到原始open呼叫。

原來的:./Application

Application -----> libc.so
            open()

攔截:LD_PRELOAD=yourlib_wrap.so ./Application

Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
            open()                 get_real_open()                 open()

編輯:顯然您可以啟用一個ld標誌 ( --wrap <symbol>),它允許您編寫包裝器而不必求助於雙重連結:

/* yourlib.c */
#include <stdio.h>

int __real_open(const char *pathname, int flags)

int __wrap_open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    /* the undefined reference here will resolve to "open" at linking time */
    return __real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1; 
  }
}

答案3

將設定檔移開,並為互動式用例編寫一個 shell 腳本包裝器,將檔案複製到其正常目標,運行程序,並在退出時將其刪除。

答案4

將設定檔重命名為例如config.interactive.建立另一個名為 例如 的空檔案config.script

config現在,建立一個名為(或應用程式期望的設定檔的任何內容)的軟連結到您需要的任何實際配置並運行您的應用程式。

ln -s config.interactive config

請記住事後整理您的連結。

相關內容