The branch main has been updated by bapt:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=cf5722ed60cf271e516927684c90464debb37496

commit cf5722ed60cf271e516927684c90464debb37496
Author:     Baptiste Daroussin <[email protected]>
AuthorDate: 2026-06-04 19:06:35 +0000
Commit:     Baptiste Daroussin <[email protected]>
CommitDate: 2026-06-04 19:06:35 +0000

    nuageinit: fix TOCTOU in addsshkey, adddoas, addsudo
    
    Replace check-then-create patterns with direct creation:
    
    - addsshkey: check what exists before creation, use mkdir_p() for
      .ssh directory, handle errors with warnmsg() instead of assert().
      Apply chmod/chown only on newly created files/directories.
    
    - adddoas: same pattern for doas.conf and the etc directory.
    
    - addsudo: same pattern for the sudoers file and sudoers.d directory.
    
    All three functions now use warnmsg() for error handling instead of
    returning nil,err or using assert().
---
 libexec/nuageinit/nuage.lua | 92 +++++++++++++++++++++++++--------------------
 1 file changed, 52 insertions(+), 40 deletions(-)

diff --git a/libexec/nuageinit/nuage.lua b/libexec/nuageinit/nuage.lua
index 7e7b2a64305f..56d1ccf9d52e 100644
--- a/libexec/nuageinit/nuage.lua
+++ b/libexec/nuageinit/nuage.lua
@@ -349,25 +349,33 @@ local function addgroup(grp)
 end
 
 local function addsshkey(homedir, key)
-       local chownak = false
-       local chowndotssh = false
        local root = os.getenv("NUAGE_FAKE_ROOTDIR")
        if root then
                homedir = root .. "/" .. homedir
        end
        local ak_path = homedir .. "/.ssh/authorized_keys"
        local dotssh_path = homedir .. "/.ssh"
-       local dirattrs = lfs.attributes(ak_path)
-       if dirattrs == nil then
-               chownak = true
-               dirattrs = lfs.attributes(dotssh_path)
-               if dirattrs == nil then
-                       assert(lfs.mkdir(dotssh_path))
-                       chowndotssh = true
-                       dirattrs = lfs.attributes(homedir)
+
+       -- Check what already exists before creating anything
+       local ak_exists = lfs.attributes(ak_path) ~= nil
+       local dotssh_exists = lfs.attributes(dotssh_path) ~= nil
+
+       -- Ensure .ssh directory exists
+       if not dotssh_exists then
+               local r, err = mkdir_p(dotssh_path)
+               if not r then
+                       warnmsg("cannot create " .. dotssh_path .. ": " .. err)
+                       return
                end
        end
 
+       -- Get homedir attributes for ownership
+       local dirattrs = lfs.attributes(homedir)
+       if not dirattrs then
+               warnmsg("cannot get attributes for " .. homedir)
+               return
+       end
+
        local f = io.open(ak_path, "a")
        if not f then
                warnmsg("impossible to open " .. ak_path)
@@ -375,19 +383,19 @@ local function addsshkey(homedir, key)
        end
        f:write(key .. "\n")
        f:close()
-       if chownak then
+
+       -- Set permissions and ownership on newly created files/dirs
+       if not ak_exists then
                chmod(ak_path, "0600")
                chown(ak_path, dirattrs.uid, dirattrs.gid)
        end
-       if chowndotssh then
+       if not dotssh_exists then
                chmod(dotssh_path, "0700")
                chown(dotssh_path, dirattrs.uid, dirattrs.gid)
        end
 end
 
 local function adddoas(pwd)
-       local chmodetcdir = false
-       local chmoddoasconf = false
        local root = os.getenv("NUAGE_FAKE_ROOTDIR")
        local localbase = getlocalbase()
        local etcdir = localbase .. "/etc"
@@ -395,18 +403,19 @@ local function adddoas(pwd)
                etcdir= root .. etcdir
        end
        local doasconf = etcdir .. "/doas.conf"
-       local doasconf_attr = lfs.attributes(doasconf)
-       if doasconf_attr == nil then
-               chmoddoasconf = true
-               local dirattrs = lfs.attributes(etcdir)
-               if dirattrs == nil then
-                       local r, err = mkdir_p(etcdir)
-                       if not r then
-                               return nil, err .. " (creating " .. etcdir .. 
")"
-                       end
-                       chmodetcdir = true
+
+       local doasconf_exists = lfs.attributes(doasconf) ~= nil
+       local etcdir_exists = lfs.attributes(etcdir) ~= nil
+
+       -- Ensure etc directory exists
+       if not etcdir_exists then
+               local r, err = mkdir_p(etcdir)
+               if not r then
+                       warnmsg("cannot create " .. etcdir .. ": " .. err)
+                       return
                end
        end
+
        local f = io.open(doasconf, "a")
        if not f then
                warnmsg("impossible to open " .. doasconf)
@@ -424,17 +433,17 @@ local function adddoas(pwd)
                end
        end
        f:close()
-       if chmoddoasconf then
+
+       -- Set permissions on newly created files/dirs
+       if not doasconf_exists then
                chmod(doasconf, "0640")
        end
-       if chmodetcdir then
+       if not etcdir_exists then
                chmod(etcdir, "0755")
        end
 end
 
 local function addsudo(pwd)
-       local chmodsudoersd = false
-       local chmodsudoers = false
        local root = os.getenv("NUAGE_FAKE_ROOTDIR")
        local localbase = getlocalbase()
        local sudoers_dir = localbase .. "/etc/sudoers.d"
@@ -442,18 +451,19 @@ local function addsudo(pwd)
                sudoers_dir= root .. sudoers_dir
        end
        local sudoers = sudoers_dir .. "/90-nuageinit-users"
-       local sudoers_attr = lfs.attributes(sudoers)
-       if sudoers_attr == nil then
-               chmodsudoers = true
-               local dirattrs = lfs.attributes(sudoers_dir)
-               if dirattrs == nil then
-                       local r, err = mkdir_p(sudoers_dir)
-                       if not r then
-                               return nil, err .. " (creating " .. sudoers_dir 
.. ")"
-                       end
-                       chmodsudoersd = true
+
+       local sudoers_exists = lfs.attributes(sudoers) ~= nil
+       local sudoers_dir_exists = lfs.attributes(sudoers_dir) ~= nil
+
+       -- Ensure sudoers.d directory exists
+       if not sudoers_dir_exists then
+               local r, err = mkdir_p(sudoers_dir)
+               if not r then
+                       warnmsg("cannot create " .. sudoers_dir .. ": " .. err)
+                       return
                end
        end
+
        local f = io.open(sudoers, "a")
        if not f then
                warnmsg("impossible to open " .. sudoers)
@@ -467,10 +477,12 @@ local function addsudo(pwd)
                end
        end
        f:close()
-       if chmodsudoers then
+
+       -- Set permissions on newly created files/dirs
+       if not sudoers_exists then
                chmod(sudoers, "0440")
        end
-       if chmodsudoersd then
+       if not sudoers_dir_exists then
                chmod(sudoers_dir, "0750")
        end
 end

Reply via email to