The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=46d1758aa7a2af37a356a93812b492a406c6ffd4
commit 46d1758aa7a2af37a356a93812b492a406c6ffd4 Author: Baptiste Daroussin <[email protected]> AuthorDate: 2026-06-04 18:26:49 +0000 Commit: Baptiste Daroussin <[email protected]> CommitDate: 2026-06-04 18:26:49 +0000 nuageinit: add hostname validation (RFC 952/1123) to sethostname() Validate hostnames before writing them: - Reject empty hostnames - Reject hostnames longer than 253 characters - Reject hostnames with invalid characters - Reject hostnames starting or ending with dot/hyphen - Reject labels longer than 63 characters - Reject labels starting or ending with hyphen Expand the sethostname test to cover all rejection cases. Update nuage.sh sethostname_body to ignore stderr (warnings). --- libexec/nuageinit/nuage.lua | 27 +++++++++++++ libexec/nuageinit/tests/nuage.sh | 2 +- libexec/nuageinit/tests/sethostname.lua | 68 +++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/libexec/nuageinit/nuage.lua b/libexec/nuageinit/nuage.lua index 4f25e79ccefc..a491ca8d9df6 100644 --- a/libexec/nuageinit/nuage.lua +++ b/libexec/nuageinit/nuage.lua @@ -119,6 +119,33 @@ local function sethostname(hostname) if hostname == nil then return end + -- Basic hostname validation (RFC 952/1123) + if #hostname == 0 then + warnmsg("hostname is empty, ignoring") + return + end + if #hostname > 253 then + warnmsg("hostname too long (" .. #hostname .. " > 253), ignoring") + return + end + if hostname:match("[^a-zA-Z0-9%.%-]") then + warnmsg("hostname contains invalid characters: " .. hostname) + return + end + if hostname:match("^[%.%-]") or hostname:match("[%.%-]$") then + warnmsg("hostname must not start or end with a dot or hyphen: " .. hostname) + return + end + for label in hostname:gmatch("[^.]+") do + if #label > 63 then + warnmsg("hostname label too long (" .. #label .. " > 63): " .. label) + return + end + if label:match("^-") or label:match("-$") then + warnmsg("hostname label starts or ends with hyphen: " .. label) + return + end + end local root = os.getenv("NUAGE_FAKE_ROOTDIR") if not root then root = "" diff --git a/libexec/nuageinit/tests/nuage.sh b/libexec/nuageinit/tests/nuage.sh index 348a8d93ba09..97c5224c7813 100644 --- a/libexec/nuageinit/tests/nuage.sh +++ b/libexec/nuageinit/tests/nuage.sh @@ -29,7 +29,7 @@ settimezone_body() sethostname_body() { - atf_check /usr/libexec/flua $(atf_get_srcdir)/sethostname.lua + atf_check -e ignore /usr/libexec/flua $(atf_get_srcdir)/sethostname.lua if [ ! -f etc/rc.conf.d/hostname ]; then atf_fail "hostname not written" fi diff --git a/libexec/nuageinit/tests/sethostname.lua b/libexec/nuageinit/tests/sethostname.lua index 47632497b545..0bc7eb2c4475 100644 --- a/libexec/nuageinit/tests/sethostname.lua +++ b/libexec/nuageinit/tests/sethostname.lua @@ -1,5 +1,73 @@ #!/usr/libexec/flua +--- +-- SPDX-License-Identifier: BSD-2-Clause +-- +-- Copyright (c) 2026 Baptiste Daroussin <[email protected]> local n = require("nuage") +local root = os.getenv("NUAGE_FAKE_ROOTDIR") +if not root then + root = "" +end + +local hostnamepath = root .. "/etc/rc.conf.d/hostname" + +local function check_hostname(expected) + local f = io.open(hostnamepath, "r") + if not f then + n.err("hostname file not found, expected: " .. expected) + end + local content = f:read("*a") + f:close() + local expected_content = 'hostname="' .. expected:gsub('"', '\\"') .. '"\n' + if content ~= expected_content then + n.err("hostname mismatch: got '" .. content .. + "', expected '" .. expected_content .. "'") + end +end + +local function check_no_hostname() + if io.open(hostnamepath, "r") then + n.err("hostname file should not exist") + end +end + +-- nil hostname: no-op +n.sethostname(nil) +check_no_hostname() + +-- Empty hostname: invalid +n.sethostname("") +check_no_hostname() + +-- Hostname too long (>253 chars): invalid +n.sethostname(string.rep("a", 254)) +check_no_hostname() + +-- Invalid characters: invalid +n.sethostname("host;name") +check_no_hostname() + +-- Starts with dot: invalid +n.sethostname(".hostname") +check_no_hostname() + +-- Ends with hyphen: invalid +n.sethostname("hostname-") +check_no_hostname() + +-- Label too long (>63 chars): invalid +n.sethostname(string.rep("a", 64) .. ".example.com") +check_no_hostname() + +-- Label starts with hyphen: invalid +n.sethostname("myhost.-label.com") +check_no_hostname() + +-- Valid simple hostname +n.sethostname("myhostname") +check_hostname("myhostname") + +-- Final: set a valid hostname for the shell test n.sethostname("myhostname")
