Skip to content

feat: prohibit guests from surpassing fd limits#1247

Draft
n0toose wants to merge 7 commits intohermit-os:mainfrom
n0toose:fd-limits
Draft

feat: prohibit guests from surpassing fd limits#1247
n0toose wants to merge 7 commits intohermit-os:mainfrom
n0toose:fd-limits

Conversation

@n0toose
Copy link
Copy Markdown
Member

@n0toose n0toose commented Feb 8, 2026

  • This allows Uhyve to gracefully handle file descriptor exhaustion
    which can be caused by a busy host or a malicious guest.
  • Introduction of a serial test (which also implicitly tests whether
    the errno provided by the host is 'parsed' properly). Not
    complete, but still something.
  • Dynamic calculation of available files for the guest (as in,
    files used by Uhyve are not included in the 'files left' variable).

Fixes #897
Depends on #1219


Currently Linux-only.

jounathaen and others added 6 commits February 8, 2026 11:56
Co-authored-by: Panagiotis "Ivory" Vasilopoulos <git@n0toose.net>
- bump uhyve-interface to 0.2.0
- perform virtaddr -> physaddr conversions in hermit for read, write.
- use adjust serial_port based on version of uhyve-interface used
- Exit hypercalls should encode the exit code instead of a pointer to
  the integer. ExitArgs has been removed.
- v2: add v2 support in src/stats.rs, futureproof
- v2: use u64, i64 instead of usize, isize
- v2: improve errno returns in read, write hypercalls with v1 compat
- v2: remove packed where unnecessary
- v2: return better error (codes) for write, read
- v2: return length of write for stdout, stderr prints
- adjust serial test for v2

uhyve-interface (v2) should now write to the rcx register before
triggering an IoOut hypercall on systems the x86_64 architecture so as
to allow for using pointers to 64-bit addresses (ports restrict us to
32-bit). This restriction should not apply for serial writes, although
it also remains possible for the kernel to print out messages.

Co-authored-by: Ellen Emilia Anna Zscheile <fogti+devel@ytrizja.de>
Co-authored-by: Jonathan Klimt <jonathan.klimt@eonerc.rwth-aachen.de>
... which causes excessive slowdowns at scale.
In some cases, the host may return errors that 'Hermit' doesn't "know
about". This warning intends to aid with the debugging process.
- write_to_fd test is now part of fs_tests
- standard streams' (written to by write_to_fd) output is checked
- generate_params now takes Option<PathBuf> as guest_path, as such a
  path may not always be necessary (like in the case of write_to_fd).
  A superfluous guest_path was also removed from mounts_test.
@n0toose n0toose requested review from fogti and jounathaen February 8, 2026 17:17
@n0toose n0toose added feature/file system feature/security Concerns security-related behavior, soundness, isolation or reliability. tests Integration and unit-tests verifying Uhyve's behavior labels Feb 8, 2026
- This allows Uhyve to gracefully handle file descriptor exhaustion
  which can be caused by a busy host or a malicious guest.
- Introduction of a serial test (which also implicitly tests whether
  the errno provided by the host is 'parsed' properly). Not
  complete, but still something.
- Dynamic calculation of available files for the guest (as in,
  files used by Uhyve are not included in the 'files left' variable).

Fixes hermit-os#897
@n0toose
Copy link
Copy Markdown
Member Author

n0toose commented Feb 8, 2026

No idea why the integration tests that run locally (after having close to an hour trying to "engineer" that) just don't feel like running on GitHub Actions right now.

@fogti
Copy link
Copy Markdown
Contributor

fogti commented Feb 8, 2026

Catching and handling the errors (taken from errno -l output):

ENFILE 23 Too many open files in system
EMFILE 24 Too many open files

Might be the cleaner solution, in particular because they aren't Linux-specific.
For Linux, we could still provide something linux-specific additional debug output, but the core functionality would optimally only depend on POSIX / UNIX,

@fogti
Copy link
Copy Markdown
Contributor

fogti commented Feb 8, 2026

Also, the amount of places where fd limits can be imposed is frightingly large: https://www.baeldung.com/linux/error-too-many-open-files . And Linux occasionally adds new ones.

@n0toose
Copy link
Copy Markdown
Member Author

n0toose commented Feb 8, 2026

I didn't find polling lsof or similar to be a good idea and explicitly did not touch anything involving setting those limitations

Might be the cleaner solution, in particular because they aren't Linux-specific.

Those were the codes I'd theoretically return, not part of the Hermit ABI.

handling the errors

One could do that (and I should've mentioned it earlier), but this limits the possibility of being able to define arbitrary limits (e.g. max open files, enforced by the kernel)—the idea would be useful for an "same process, many guests" approach later. This is not part of this PR, but that could change. It is in line with plans to decide whether errors cause crashes, or whether a host mount is read only.

It might make sense to do both, but not at the same time, to ensure that there is some parity e.g. on macOS. After all, it's better if Uhyve doesn't treat the underlying guests differently depending on the host OS—but it is completely fair for Uhyve to provide some additional features depending on the host OS (i.e. Landlock) or configuration (e.g. tracing).

@n0toose
Copy link
Copy Markdown
Member Author

n0toose commented Feb 8, 2026

It seems like the many methods effectively affect the same thing, like how sysctl may affect the same thing as a parameter passed to the kernel using a bootloader by GRUB.

Unless if I'm missing something (e.g. ulimit?), the primary thing that I don't do is use /proc/sys/fs/file-max, but I considered that reading it is wasteful compared to just setting a MAX value. One would get an error before you reach either of these values, unless if you decide to get Uhyve to run as the init system or something like that (other processes will use file descriptors and we don't know how many).

criterion = "0.8"
home = "0.5"
regex = { version = "1.12.2", default-features = false, features = ["unicode-perl"] }
serial_test = "3.3"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This is probably something for a separate PR
  2. I'm not decided if I prefer another dependency, or if we should just use a global Mutex here, similar to what is done in build_hermit_bin


[target.'cfg(target_os = "hermit")'.dependencies]
hermit = "0.12"
hermit = { path = "../../../hermit-rs/hermit" }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😉

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woooooops

@fogti
Copy link
Copy Markdown
Contributor

fogti commented Feb 9, 2026

I think on Linux it might make more sense to set ulimit explicitly inside of uhyve, and rely on the outer kernel for enforcement.

The errno codes mentioned are those that would be emitted by syscalls (e.g. open) to the outer kernel when trying to surpass limits.

@fogti
Copy link
Copy Markdown
Contributor

fogti commented Feb 9, 2026

btw. Mac OSX also supports ulimit afaik: https://wilsonmar.github.io/maximum-limits/

I don't think it makes sense to reinvent the wheel for stuff that can be done with standard UNIX utilities just fine.

@fogti
Copy link
Copy Markdown
Contributor

fogti commented Feb 9, 2026

Consider using https://docs.rs/rlimit/ instead of hacking around with non-portable /proc entries.
That can also be used to set resource limits.

@fogti
Copy link
Copy Markdown
Contributor

fogti commented Feb 9, 2026

After a guest has started running, do we even open any additional file handles which would necessitate such a paranoid implementation?

The main thing that we might want to fix is the handling of rftrace trace writing stuff, which afaik does open file descriptors in a manner that might fail under strict resource limits. Is there anything else that isn't guest-directed?

@n0toose
Copy link
Copy Markdown
Member Author

n0toose commented Feb 9, 2026

The main thing that we might want to fix is the handling of rftrace trace writing stuff, which afaik does open file descriptors in a manner that might fail under strict resource limits.

This has not been tested with rftrace, but the current implementation checks the current amount of open file descriptors while UhyveVm is being instantiated. The only negative aspect of this right now is that a refactor (e.g. closing the ELF header before UhyveFileMap is initialized) could break the logic.

ulimit

TBD, thanks. Will leave this on the backburner until v2 is merged.

@n0toose n0toose marked this pull request as draft February 17, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature/file system feature/security Concerns security-related behavior, soundness, isolation or reliability. tests Integration and unit-tests verifying Uhyve's behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make Uhyve aware of process-wide limits

3 participants