-
-
Notifications
You must be signed in to change notification settings - Fork 179
Description
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_bugExpected 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, forsethostname(), 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 checkuts_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:42returnsEINVALforlen >= MAXLENuts_namespace.rs:188returnsENAMETOOLONGforlen >= MAXLEN
The syscall-level check takes precedence, so ENAMETOOLONG is never returned. This inconsistency should be resolved (Linux uses EINVAL).
Severity
- Critical - System crash/hang
- High - Wrong behavior, security issue
- Medium - Incorrect return value
- Low - Minor inconsistency
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.