Skip to content

Make common and guest libs portable #524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 23, 2025

Conversation

danbugs
Copy link
Contributor

@danbugs danbugs commented May 23, 2025

This PR changes our pointer usage in the guest and common lib to be portable (i.e., using u64s instead of usize or pointer types that vary between architectures).

Plus, I did some general housekeeping like removing legacy fields/comments, refactored the PEB structs to avoid code duplication, and madeour PEB related struct items snake case.

Reviews can be made commit-by-commit, if you preferred.

@danbugs danbugs force-pushed the common-lib-and-iostacks-cleanup branch from 4dec35f to 30dd928 Compare May 23, 2025 18:39
@danbugs danbugs added the kind/refactor For PRs that restructure or remove code without adding new functionality. label May 23, 2025
danbugs added 5 commits May 23, 2025 18:51
We no longer have kernel stack and boot stacks, so we can remove these fields. Also, removed some legacy
comment.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
If the guest and host are compiled for different architectures, there will be a mismatch in usage of the PEB.
Using u64s, just like we do for pCode, makes our PEB portable.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
It's useful for a library to provide implementaitons of these traits for its structures.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
- InputData, OutputData, and GuestHeapData were functionally the same and so they were combined into a single
GuestMemoryRegion struct.
- removed the allow_non_snake_case attribute.
- general housekeeping.

Signed-off-by: danbugs <danilochiarlone@gmail.com>
If we use usize and the guest and host are compiled for different architectures, there will be a mismatch
in sizing between the guest and host, so we should use u64s to address that (tested w/ Nanvix already).

Signed-off-by: danbugs <danilochiarlone@gmail.com>
@danbugs danbugs force-pushed the common-lib-and-iostacks-cleanup branch from 30dd928 to 0f91d6c Compare May 23, 2025 18:51
@jsturtevant
Copy link
Contributor

from one of the commits:

If we use usize and the guest and host are compiled for different architectures, there will be a mismatch
in sizing between the guest and host, so we should use u64s to address that (tested w/ Nanvix already).

What happens if one side is 32 bit? could a cast down to the smaller pointer lose information?

@jsturtevant
Copy link
Contributor

Reviews can be made commit-by-commit, if you preferred.

This made it really easy to review. Thanks!

@danbugs
Copy link
Contributor Author

danbugs commented May 23, 2025

from one of the commits:

If we use usize and the guest and host are compiled for different architectures, there will be a mismatch
in sizing between the guest and host, so we should use u64s to address that (tested w/ Nanvix already).

What happens if one side is 32 bit? could a cast down to the smaller pointer lose information?

We don't support 32-bit hosts currently, our shared-mem abstraction is built on the assumption of a 64-bit architecture. Currently, using usize on the guest can cause truncation if the guest is 32-bit, which is what this PR addresses.

Copy link
Contributor

@devigned devigned left a comment

Choose a reason for hiding this comment

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

LGTM.

I will reserve a bit of concern about the assumptions made in this PR about the host targeting u64 and casting into usize. We do not intend on targeting Hyperlight host to 32 bit. If we were to pursue that, this code would likely not work as intended.

@danbugs
Copy link
Contributor Author

danbugs commented May 23, 2025

LGTM.

I will reserve a bit of concern about the assumptions made in this PR about the host targeting u64 and casting into usize. We do not intend on targeting Hyperlight host to 32 bit. If we were to pursue that, this code would likely not work as intended.

Just to elaborate on this...

Before this PR, the guest writes a usize stack ptr and, regardless, the host always reads a u64 stack ptr. This works fine when both guest and host are compiled to a 64-bit architecture. But, if the guest is compiled to a 32-bit architecture, the guest will update the stack pointer incorrectly and the host will end up reading something beyond the stack ptr—potentially, part of a serialized flatbuffer structure.

W/ this PR in, regardless of architecture, the guest now also always writes a 64-bit stack ptr matching the expectation of the host.

The problem @devigned is pointing out occurs when we try to run a host on a 32-bit architecture. Currently, the host does this when reading the stack ptr:

let stack_pointer_rel = self.read::<u64>(buffer_start_offset)? as usize;

... which, on a 32-bit architecture, this could cause a silent truncation and UB.

That said, as things are currently, it's unlikely we could ever get any meaningful truncation because the ptr would have to be bigger than the maximum memory size we support. In any case, this is a good reminder we definitely don't support 32-bit hosts :)

@danbugs danbugs merged commit 0f91d6c into hyperlight-dev:main May 23, 2025
46 of 49 checks passed
@danbugs danbugs deleted the common-lib-and-iostacks-cleanup branch May 23, 2025 20:51
@jsturtevant
Copy link
Contributor

That said, as things are currently, it's unlikely we could ever get any meaningful truncation because the ptr would have to be bigger than the maximum memory size we support.

Thanks for this, I understand now these aren't actual stack pointers in the guest/host but addresses within a shared memory buffer for passing function information back and forth, such as a flatbuffer of GuestFunctionCall. Because the size of the shared memory maximum, the buffer will never have a pointer that would be in the higher end of the u64 and therefore not be truncated.

I guess it would be nice to make sure we have an invariant somewhere to force this incase somehow that assumption changes (maybe there already is?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/refactor For PRs that restructure or remove code without adding new functionality.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants