Summary
DragonOS's sethostname system call incorrectly returns EINVAL when called with len=0 (empty hostname). Linux allows setting an empty hostname with len=0, but DragonOS rejects it as invalid.
Environment
Git Commit ID:
546a9cad1454950776d9d0520b3434be6b808f0e - fix(process): 修复多线程exec的de_thread竞态与线程退出语义 (#1748)
DragonOS Version: 2026-02-02
Test Date: 2026-02-02
Test Case
Source Code
/**
* Simple test for sethostname len=0 bug
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main(void) {
printf("TEST START\n");
fflush(stdout);
/* Test 1: sethostname with len=0 */
printf("Test 1: sethostname with len=0\n");
fflush(stdout);
int ret = sethostname("", 0);
fflush(stdout);
if (ret == 0) {
printf("Result: SUCCESS\n");
fflush(stdout);
} else {
printf("Result: FAILED, errno=%d\n", errno);
fflush(stdout);
if (errno == EINVAL) {
printf("BUG: DragonOS returns EINVAL for len=0\n");
fflush(stdout);
}
}
printf("TEST END\n");
fflush(stdout);
return 0;
}
Compilation
# DragonOS (automatically built)
make user
make write_diskimage
# Linux (Ubuntu 24.04)
gcc -Wall -O2 -static test_sethostname_bug.c -o test_sethostname_bug
Expected Behavior (Linux)
When running on Linux (Ubuntu 24.04 with privileged container):
Linux Command:
docker run --rm --privileged -v "$(pwd):/dragonos" ubuntu:24.04 bash -c "
cd /dragonos
apt-get update -qq && apt-get install -y gcc > /dev/null 2>&1
gcc -Wall -O2 -static user/apps/c_unitest/test_sethostname_bug.c -o test_sethostname_bug
./test_sethostname_bug
"
Linux Output:
TEST START
Test 1: sethostname with len=0
Result: SUCCESS
TEST END
Linux man page (sethostname(2)) states:
EINVAL - len is negative or, for sethostname(), len is larger than the maximum allowed size.
Linux does NOT mention that len=0 should return EINVAL. Setting an empty hostname is valid.
Actual Behavior (DragonOS)
When running on DragonOS:
DragonOS Command:
python3 dragonos_qemu_interactive.py --commands "/bin/test_sethostname_bug"
DragonOS Output:
TEST START
Test 1: sethostname with len=0
Result: FAILED, errno=22
BUG: DragonOS returns EINVAL for len=0
TEST END
Error Details:
- Return value:
-1
- errno:
22 (EINVAL - Invalid argument)
- System behavior: Call fails immediately without panic or crash
Analysis
Root Cause
The bug is in kernel/src/process/syscall/sys_sethostname.rs:42:
// Check length validation
if len == 0 || len >= NewUtsName::MAXLEN {
return Err(SystemError::EINVAL);
}
The check len == 0 incorrectly rejects empty hostnames. This check is not present in Linux's implementation.
Comparison
| Aspect |
Linux |
DragonOS |
sethostname("", 0) |
✅ Success (returns 0) |
❌ Fails with EINVAL |
sethostname("host", 4) |
✅ Success |
✅ Success |
sethostname(buf, 64) |
✅ Success |
✅ Success |
sethostname(buf, 65) |
❌ EINVAL |
❌ EINVAL |
Impact
- Compatibility: Applications that try to set an empty hostname will fail on DragonOS
- Correctness: Violates POSIX/Linux semantics for
sethostname()
- Severity: Low - edge case, unlikely to affect most applications
Related Files
- DragonOS implementation:
kernel/src/process/syscall/sys_sethostname.rs (line 42)
- Same issue in:
kernel/src/process/syscall/sys_setdomainname.rs (line 42)
- Linux reference:
man 2 sethostname - EINVAL only for negative or too-large len
Recommended Fix
Remove the len == 0 check from both syscalls:
// kernel/src/process/syscall/sys_sethostname.rs:42
-if len == 0 || len >= NewUtsName::MAXLEN {
+if len >= NewUtsName::MAXLEN {
return Err(SystemError::EINVAL);
}
// kernel/src/process/syscall/sys_setdomainname.rs:42
-if len == 0 || len >= NewUtsName::MAXLEN {
+if len >= NewUtsName::MAXLEN {
return Err(SystemError::EINVAL);
}
Note: The NewUtsName::MAXLEN is 65, which allows hostnames up to 64 characters (plus null terminator). This matches Linux's HOST_NAME_MAX of 64.
Additional Findings
Duplicate Permission Checks
The implementation has redundant permission checks:
sys_sethostname.rs:37-39 - First CAP_SYS_ADMIN check
uts_namespace.rs:193-196 - Second CAP_SYS_ADMIN check
The second check is unreachable due to the first check failing first. This doesn't cause bugs but adds unnecessary code.
Inconsistent Error Codes
sys_sethostname.rs:42 returns EINVAL for len >= MAXLEN
uts_namespace.rs:188 returns ENAMETOOLONG for len >= MAXLEN
The syscall-level check takes precedence, so ENAMETOOLONG is never returned. This inconsistency should be resolved (Linux uses EINVAL).
Severity
Severity Justification: Medium severity because it's a clear violation of Linux/POSIX semantics that could cause compatibility issues, but it's an edge case that won't affect most applications. No crash, security issue, or data loss.
Test Verification
Test file location: user/apps/c_unitest/test_sethostname_bug.c
The test clearly demonstrates:
- ✅ Compiles successfully on both Linux and DragonOS
- ✅ Runs successfully on Linux (Ubuntu 24.04)
- ❌ Fails on DragonOS with EINVAL for len=0
- ✅ No crashes, panics, or undefined behavior
Conclusion
DragonOS incorrectly rejects sethostname("", 0) with EINVAL, while Linux allows empty hostnames. The fix is simple: remove the len == 0 check from the validation logic in both sethostname and setdomainname syscalls.
Summary
DragonOS's
sethostnamesystem call incorrectly returnsEINVALwhen called withlen=0(empty hostname). Linux allows setting an empty hostname withlen=0, but DragonOS rejects it as invalid.Environment
Git Commit ID:
DragonOS Version: 2026-02-02
Test Date: 2026-02-02
Test Case
Source Code
Compilation
Expected Behavior (Linux)
When running on Linux (Ubuntu 24.04 with privileged container):
Linux Command:
Linux Output:
Linux man page (sethostname(2)) states:
Linux does NOT mention that
len=0should returnEINVAL. Setting an empty hostname is valid.Actual Behavior (DragonOS)
When running on DragonOS:
DragonOS Command:
python3 dragonos_qemu_interactive.py --commands "/bin/test_sethostname_bug"DragonOS Output:
Error Details:
-122(EINVAL - Invalid argument)Analysis
Root Cause
The bug is in
kernel/src/process/syscall/sys_sethostname.rs:42:The check
len == 0incorrectly rejects empty hostnames. This check is not present in Linux's implementation.Comparison
sethostname("", 0)sethostname("host", 4)sethostname(buf, 64)sethostname(buf, 65)Impact
sethostname()Related Files
kernel/src/process/syscall/sys_sethostname.rs(line 42)kernel/src/process/syscall/sys_setdomainname.rs(line 42)man 2 sethostname- EINVAL only for negative or too-large lenRecommended Fix
Remove the
len == 0check from both syscalls:Note: The
NewUtsName::MAXLENis 65, which allows hostnames up to 64 characters (plus null terminator). This matches Linux'sHOST_NAME_MAXof 64.Additional Findings
Duplicate Permission Checks
The implementation has redundant permission checks:
sys_sethostname.rs:37-39- First CAP_SYS_ADMIN checkuts_namespace.rs:193-196- Second CAP_SYS_ADMIN checkThe second check is unreachable due to the first check failing first. This doesn't cause bugs but adds unnecessary code.
Inconsistent Error Codes
sys_sethostname.rs:42returnsEINVALforlen >= MAXLENuts_namespace.rs:188returnsENAMETOOLONGforlen >= MAXLENThe syscall-level check takes precedence, so
ENAMETOOLONGis never returned. This inconsistency should be resolved (Linux usesEINVAL).Severity
Severity Justification: Medium severity because it's a clear violation of Linux/POSIX semantics that could cause compatibility issues, but it's an edge case that won't affect most applications. No crash, security issue, or data loss.
Test Verification
Test file location:
user/apps/c_unitest/test_sethostname_bug.cThe test clearly demonstrates:
Conclusion
DragonOS incorrectly rejects
sethostname("", 0)withEINVAL, while Linux allows empty hostnames. The fix is simple: remove thelen == 0check from the validation logic in bothsethostnameandsetdomainnamesyscalls.