2010-05-30 93 views
2

作爲this one的後續問題,我想到了另一種方法,它構建了@ caf的答案,用於我想要附加到文件name的情況,並在不存在的情況下創建它。模擬O_NOFOLLOW(2):這種其他方法安全嗎?

這裏是我想出了:

  1. 在系統臨時目錄在同一文件系統的文件name創建模式0700的臨時目錄。
  2. 打開文件name只讀和O_CREAT。如果它是符號鏈接,則操作系統可能會遵循name

    使用mkstemp在臨時目錄中創建一個臨時文件,並嘗試renamemkstemp創建的臨時文件到name

    打開文件name僅供閱讀和O_CREAT | O_EXCL
  3. 以臨時目錄中的臨時名稱迭代嘗試建立到name的硬鏈接。如果由於除「鏈接目標存在」(錯誤號碼EEXIST)之外的錯誤導致link呼叫失敗,請退出。 (也許有人來過並刪除了文件name,誰知道?)
  4. 使用lstattemp_name(硬鏈接)。如果S_ISLNK(lst.st_mode),則退出。
  5. opentemp_name寫作&附加(O_WRONLY | O_APPEND)。
  6. 把一切寫出來。關閉文件描述符。
  7. unlink硬鏈接。
  8. 刪除臨時目錄。

(所有這一切,順便說一下,是一個open source project是我的工作。你可以查看我的實現這種方法here的來源。)

這是程序安全對符號鏈接攻擊?例如,是否有可能惡意進程確保name的inode代表lstat檢查期間的常規文件,然後使inode成爲指向新的符號鏈接的硬鏈接的符號鏈接?

我假設惡意進程不會影響temp_name

編輯:link不會覆蓋目標,因此創建一個「佔位符」臨時文件是不是我想要做的。之後我更新了代碼並更新了上述步驟。

EDIT2:我現在使用的是備用程序步驟2中,如果不存在的話,我不認爲是易受this problem創建文件name

EDIT3:比重命名一個臨時的,空的,常規文件name,其中也有取消鏈接name然後重命名的效果更妙的是,我可以打開該文件O_RDONLY | O_CREAT | O_EXCL

open狀態POSIX標準:

如果O_EXCLO_CREAT設置,並path名的符號鏈接,open()失敗,將設置errnoEEXIST,不管符號鏈接的內容。

+0

您的最終POSIX引用看起來像一個答案。如果是這樣,爲什麼不把它作爲答案並接受它,所以這個問題不再顯示爲「未答覆」? – 2010-08-08 04:59:38

+0

@ R。抱歉。我已經接受了我的回答。 – 2010-08-08 17:50:47

回答

0

那麼,有一個問題,第2步(「打開文件name僅作O_CREAT讀書。操作系統可以跟隨name,如果它是一個符號鏈接。」),如果充分利用,可以允許非特權處理到基本touch文件系統中的任何路徑。其後果包括強制磁盤檢查下次重新啓動(通過觸摸/forcefsck)以及其他更具破壞性的事情。例如,在從Debian Lenny升級到Squeeze時,dbus和內核映像必須同時升級,因爲每個相應的軟件包都依賴於其他軟件包(新的dbus不適用於舊的內核和舊的dbus不適用於新內核)。管理員繞過這種循環依賴的方式是通過touch指定一個特定路徑,該路徑通知新的dbus軟件包在下次重新啓動之前內核映像將被升級。但是,如果在從Lenny升級到Squeeze期間,第一次升級&重新啓動之前惡意進程管理到touch該路徑,則系統可能無法啓動。如果我記得正確的話,第一次升級會安裝新的dbus,但您必須重新升級才能安裝新的內核映像。 其中一個升級,然後重新啓動可能會導致系統崩潰。

通過source of GNU Coreutils' touch來看,似乎他們只設置文件的時間戳,但不創建文件,如果它不存在,當touch傳遞的--no-dereference選項。他們使用gnulib中的效用函數lutimens進行此操作,該函數包裝Linux的utimensat,允許符號鏈接文件本身的時間戳(如果是這種情況)在Linux> = 2.6.22時更新。