Skip to content

Commit

Permalink
Handle posix hostname edge cases (#14)
Browse files Browse the repository at this point in the history
* Handle extra nul byte

HOST_NAME_MAX is the maximum allowed hostname excluding the terminating
nul byte. This means that HOST_NAME_MAX + 1 must be used for gethostname
call. Otherwise -1 may be returned, e.g. by glibc's gethostname.

How to reproduce on Linux with glibc:
- Set hostname to a 64 character long string
- Try to retrieve hostname

* Handle posix systems without HOST_NAME_MAX limits

If sysconf returns -1 this either means that an error occurred or that
no limit exists. Casting -1 to size_t leads to a huge number, so only
use the returned limit if it is not -1.

If sysconf returned an error or no limit exists, use 255.

* Fail if hostname is too long

Invalid hostnames supplied to set should be rejected. Otherwise it
could happen that on FreeBSD a partial hostname is set.
  • Loading branch information
stoeckmann authored Sep 19, 2023
1 parent 7e930e9 commit 4a178ed
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/nix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ use std::os::unix::ffi::OsStringExt;

use libc;

const _POSIX_HOST_NAME_MAX: libc::c_long = 255;

pub fn get() -> io::Result<OsString> {
// According to the POSIX specification,
// host names are limited to `HOST_NAME_MAX` bytes
//
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html
let size =
unsafe { libc::sysconf(libc::_SC_HOST_NAME_MAX) as libc::size_t };
let limit = unsafe { libc::sysconf(libc::_SC_HOST_NAME_MAX) };
let size = libc::c_long::max(limit, _POSIX_HOST_NAME_MAX) as usize;

let mut buffer = vec![0u8; size];
// Reserve additional space for terminating nul byte.
let mut buffer = vec![0u8; size + 1];

let result = unsafe {
libc::gethostname(buffer.as_mut_ptr() as *mut libc::c_char, size)
Expand Down Expand Up @@ -58,6 +61,10 @@ pub fn set(hostname: &OsStr) -> io::Result<()> {
#[allow(non_camel_case_types)]
type hostname_len_t = libc::c_int;

if hostname.len() > hostname_len_t::MAX {
return Err(io::Error::new(io::ErrorKind::Other, "hostname too long"));
}

let size = hostname.len() as hostname_len_t;

let result = unsafe {
Expand Down

0 comments on commit 4a178ed

Please sign in to comment.