Skip to content
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

Add linux_raw opt-in backend #572

Merged
merged 10 commits into from
Mar 3, 2025
Merged

Add linux_raw opt-in backend #572

merged 10 commits into from
Mar 3, 2025

Conversation

newpavlov
Copy link
Member

@newpavlov newpavlov commented Dec 23, 2024

This PR replaces the linux_rustix opt-in backend introduced in #520 with linux_raw opt-in backend based raw syscalls implemented using asm!. It noticeably reduces dependency footprint of the crate (see concerns raised in #433). Unfortunately, it means that we have to implement the raw syscalls ourselves.

This PR implements linux_raw support only for target arches with stable asm!. Nightly-only support for other targets can be added in later PRs.

@newpavlov newpavlov requested a review from josephlr December 23, 2024 17:39
Copy link
Member

@josephlr josephlr left a comment

Choose a reason for hiding this comment

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

Personally, I think this seems like a lot of added complexity for a backend that is not enabled by default. I think that we should try to find some other way to solve the issues raised in #433, or just not have a rustix/raw-syscall backend right now.

Getting raw syscalls correct can be very complex if we want to support a range of targets, and I don't think we are well situated to maintain such things.

@newpavlov
Copy link
Member Author

newpavlov commented Dec 23, 2024

just not have a rustix/raw-syscall backend right now

Yes, it's a reasonable option. We can delay this backend until a later release.

But I believe we should eventually have a "raw Linux syscall" backend as it was requested several times (#401, #424).

Getting raw syscalls correct can be very complex if we want to support a range of targets, and I don't think we are well situated to maintain such things.

I do not agree with the "very complex" assessment. As mentioned in the comments, I've mostly copied the battle-tested code from rustix, intentionally limited the set of supported targets and did not include any vDSO complexity.

Ideally, I would prefer to have the syscall stuff in a separate lean crate, but, unfortunately, rustix/linux-raw-sys developers weren't open to such changes. I could create my own fork of linux-raw-sys, but would it be really better than the current solution?

josephlr pushed a commit that referenced this pull request Jan 3, 2025
As suggested
[here](#572 (review))
it may be worth to remove `linux_rustix` from the v0.3.0 release.

We probably will either return it in v0.3.1, or will introduce a
different `linux_raw` opt-in backend (see #572).
@josephlr josephlr added this to the Post 0.3 Release milestone Jan 3, 2025
@newpavlov newpavlov removed this from the Post 0.3 Release milestone Jan 27, 2025
@newpavlov newpavlov changed the title Replace linux_rustix opt-in backend with linux_raw Add linux_raw opt-in backend Feb 3, 2025
@newpavlov newpavlov requested a review from josephlr February 3, 2025 10:53
@newpavlov
Copy link
Member Author

this seems like a lot of added complexity for a backend that is not enabled by default

Note that I plan to use this backend to support the *-linux-none targets by default. I think it's better to do it in a separate PR.

@newpavlov
Copy link
Member Author

@josephlr
I would like to add this backend and support of *-linux-none in the next release. WDYT?

Copy link
Member

@josephlr josephlr left a comment

Choose a reason for hiding this comment

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

Sorry for the delay in reviewing this. I think this is a fine idea, but I'm not sure if we want to bother supporting the more "difficult" targets where syscalls are more complicated than a single instruction.


pub use crate::util::{inner_u32, inner_u64};

#[cfg(not(any(target_os = "android", target_os = "linux")))]
Copy link
Member

Choose a reason for hiding this comment

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

I'm trying to figure out what the constraints are around directly invoking syscalls on Android. I can try to check with some people at work, but it's unclear if bionic libc (the libc shipped with Android) does any special handling for syscalls. If the only demand for this is on linux targets, it might just be best to initially exclude Android.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it would be nice to verify that raw syscalls work on Android without any surprises.

Here is a relevant rustix discussion: bytecodealliance/rustix#1095 No one has mentioned any fundamental technical obstacles to using raw syscalls and it looks like some people use them in practice.

Copy link
Member Author

Choose a reason for hiding this comment

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

Since users have to explicitly enable the backend, I think we can leave it as-is and potentially disable it later if it will be found problematic on Android for some reason.

in("a2") flags,
options(nostack, preserves_flags)
);
} else if #[cfg(target_arch = "x86")] {
Copy link
Member

Choose a reason for hiding this comment

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

Give that there is no i686-unknown-linux-none target and invoking raw syscalls on x86 is a notorious foot-gun, could we just not support 32-bit x86? It seems easier and then we don't have to have warnings saying "you probably shouldn't use this backend"

Copy link
Member Author

Choose a reason for hiding this comment

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

IIRC the only problem with int 0x80 is its performance, otherwise it works fine. So I think it's fine to have support for it for completeness sake despite its suboptimality.

Copy link
Member Author

Choose a reason for hiding this comment

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

I tweaked the warning a bit. Now it notes that linux_raw may be slower than libc::getrandom-based backends in general, not just on x86.

core::arch::asm!(
"mov {tmp}, r7",
"mov r7, {nr}",
"svc 0",
Copy link
Member

Choose a reason for hiding this comment

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

Looking at the syscall(2) documentation it seems like there (might) be a difference between EABI / OABI targets for 32-bit arm. Also, that documentation suggests that 32-bit arm should use the swi instruction.

Personally, I would be fine omitting 32-bit arm support (similar to x86 support). It's more complicated, and there isn't a 32-bit -unknown-linux-none target.

Copy link
Member

@josephlr josephlr Feb 14, 2025

Choose a reason for hiding this comment

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

Looks like swi is the same as svc (https://developer.arm.com/documentation/ddi0406/cb/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/SVC--previously-SWI-?lang=en) I'm still confused about the EABI vs OABI stuff though.

I think this code would be fine provided we simply confirm (via cfgs) that we are targeting eabi.

Copy link
Member Author

Choose a reason for hiding this comment

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

This code is based on rustix and it does not look like they differentiate between EABI / OABI: https://github.com/bytecodealliance/rustix/blob/main/src/backend/linux_raw/arch/mod.rs#L27-L28

After a brief search I couldn't find any relevant information about OABI support in Rust. Are you sure that Rust supports it in the first place? For example, it looks like GCC has dropped OABI support completely.

@newpavlov newpavlov merged commit 3be979b into master Mar 3, 2025
67 checks passed
@newpavlov newpavlov deleted the linux_raw branch March 3, 2025 11:27
@newpavlov newpavlov mentioned this pull request Mar 7, 2025
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants