Skip to content

Implement support for NOEXEC #1073

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

bjorn3
Copy link
Collaborator

@bjorn3 bjorn3 commented Apr 15, 2025

This is using seccomp syscall filtering of the execve and execveat syscalls. Unlike the original sudo this does not depend on using LD_PRELOAD. Instead SECCOMP_RET_USER_NOTIF is used combined with a thread which allows the first exec (as done by sudo itself) and denies all further execs. This makes it robust against both statically linked executables and executables compiled for a different libc than sudo-rs itself. Sudo-rs just like original sudo does not protect against malicious programs with NOEXEC. It doesn't prevent mapping memory as executable, nor does it protect against future syscalls that do an exec like the planned io_uring exec opcode 1. And it also doesn't protect against honest programs that intentionally or not allow the user to write to /proc/self/mem for the same reasons as that it doesn't protect against malicious programs.

Fixes #1071
Fixes #1072

Footnotes

  1. https://lwn.net/Articles/1002371/

@bjorn3
Copy link
Collaborator Author

bjorn3 commented Apr 15, 2025

Looks like our MSRV doesn't support offset_of!(). Can we raise the MSRV to 1.77? Debian Trixie will have rustc 1.85 and Debian Bookworm already doesn't have a new enough rustc for us.

@squell
Copy link
Member

squell commented Apr 15, 2025

We can certainly consider that. How ugly is the workaround if we don't raise the MSRV to 1.77?

@bjorn3
Copy link
Collaborator Author

bjorn3 commented Apr 15, 2025

I believe it would be create a zeroed instance of seccomp_data, take the address of the start and the address of &val.nr and then subtract one from the other.

@squell squell added C-exec Execution component (interfacing with OS) msrv labels Apr 15, 2025
@squell
Copy link
Member

squell commented Apr 15, 2025

Going to 1.77 would also allow taking a second look at #976 and #755, so I think the time has come.

The reason for fixing 1.70 was because at that time Debian testing and Ubuntu LTS were stuck at 1.66 for a long time.

@bjorn3
Copy link
Collaborator Author

bjorn3 commented Apr 16, 2025

Looks like Ubuntu LTS is still stuck at rustc 1.75.

@bjorn3 bjorn3 force-pushed the noexec2 branch 3 times, most recently from c01b452 to 864b19e Compare April 16, 2025 08:58
@squell
Copy link
Member

squell commented Apr 17, 2025

Two general questions:

  • What would be the approach to take on FreeBSD? Presumable that would need the dynamic library trick? (This is not something that's in scope for merging this PR, but given that we have NOEXEC on Linux it just stands to reason we should want to have this on FreeBSD in the future)

  • What's the minimum Linux version that is needed to support this implementation? I think we already looked into that and it was OK at leasts even for the Linux kernels used by oldstable and 20.04, but can we double-check?

@bjorn3
Copy link
Collaborator Author

bjorn3 commented Apr 17, 2025

What would be the approach to take on FreeBSD? Presumable that would need the dynamic library trick? (This is not something that's in scope for merging this PR, but given that we have NOEXEC on Linux it just stands to reason we should want to have this on FreeBSD in the future)

FreeBSD doesn't have seccomp support at all AFAIK (or at least I couldn't find any man page for it), so we would indeed need a dynamic library there.

What's the minimum Linux version that is needed to support this implementation? I think we already looked into that and it was OK at leasts even for the Linux kernels used by oldstable and 20.04, but can we double-check?

Should be 5.0, but I don't have a VM ready to check.

@squell
Copy link
Member

squell commented Apr 17, 2025

What's the minimum Linux version that is needed to support this implementation? I think we already looked into that and it was OK at leasts even for the Linux kernels used by oldstable and 20.04, but can we double-check?

Should be 5.0, but I don't have a VM ready to check.

I recall that that was fine, nice!

@squell squell removed the msrv label Apr 17, 2025
bjorn3 added 7 commits April 23, 2025 10:41
To enable adding exceptions to the file closer in run_command
This is using seccomp syscall filtering of the execve and execveat
syscalls. Unlike the original sudo this does not depend on using
LD_PRELOAD. Instead SECCOMP_RET_USER_NOTIF is used combined with a
thread which allows the first exec (as done by sudo itself) and denies
all further execs. This makes it robust against both statically linked
executables and executables compiled for a different libc than sudo-rs
itself. Sudo-rs just like original sudo does not protect against
malicious programs with NOEXEC. It doesn't prevent mapping memory as
executable, nor does it protect against future syscalls that do an exec
like the planned io_uring exec opcode [^1]. And it also doesn't protect
against honest programs that intentionally or not allow the user to
write to /proc/self/mem for the same reasons as that it doesn't protect
against malicious programs.

[^1]: https://lwn.net/Articles/1002371/
@bjorn3
Copy link
Collaborator Author

bjorn3 commented Apr 23, 2025

Opened #1078 to track implementing NOEXEC on FreeBSD.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-exec Execution component (interfacing with OS) linux ubuntu
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add NOEXEC support to exec Investigate NOEXEC loading
2 participants