Skip to content

[BUG REPORT] sethostname: Incorrectly Rejects len=0 with EINVAL #1753

@fslongjin

Description

@fslongjin

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:

  1. sys_sethostname.rs:37-39 - First CAP_SYS_ADMIN check
  2. 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

  • 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:

  1. ✅ Compiles successfully on both Linux and DragonOS
  2. ✅ Runs successfully on Linux (Ubuntu 24.04)
  3. ❌ Fails on DragonOS with EINVAL for len=0
  4. ✅ 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bug fixA bug is fixed in this pull requestbug-report这是一个bug报告(如果确认是一个bug,请管理人员添加`bug` label)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions