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

Use anonymous shared memory on FreeBSD #178

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

valpackett
Copy link

It works in Capsicum capability mode (process sandbox).

Copy link
Contributor

@dlrobertson dlrobertson left a comment

Choose a reason for hiding this comment

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

👍

fn create_shmem(name: CString, length: usize) -> c_int {
unsafe {
// NB: the FreeBSD man page for shm_unlink states that it requires
// write permissions, but testing shows that read-write is required.
let fd = libc::shm_open(name.as_ptr(),
libc::O_CREAT | libc::O_RDWR | libc::O_EXCL,
0o600);
Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able to decrease this in the linux specific shm_open. Last time I tested this, FreeBSD required read-write, but it was not required on linux.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I thought about that. It's not just for Linux though, it's for everything else, and I'm not sure where write-only would be ok. Linux has memfd anyway…

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, true

Copy link
Contributor

Choose a reason for hiding this comment

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

memfd usage is optional on Linux, though. (IIRC that was decided because memfd is a pretty recent addition, so it would fail on older Linux versions...)

As for other systems, it's entirely unclear. Actually, I'm not sure we can even rely on it Linux: while it seems more logical to require only write permissions, neither the Linux nor the POSIX man pages seem to mention anything about this at all... I guess it's safer to stick with the broader permissions -- it's not like it has any real downsides here, aside from being confusing.

Either way, I don't think it's appropriate to remove the comment entirely. Even if the code is no longer used on FreeBSD, it doesn't make the comment wrong -- and we need to keep some explanation for why the code is this way...

Copy link
Author

Choose a reason for hiding this comment

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

@antrik well I moved the comment to the #[cfg(target_os="freebsd")] section, I did not remove it entirely :)

Copy link
Contributor

Choose a reason for hiding this comment

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

@myfreeweb I am aware that you moved it -- but since you didn't modify the original code, it's still not valid to just drop the comment entirely... Feel free to change the wording though, if you feel the original comment would be confusing in view of the changed situation.

unsafe {
// NB: the FreeBSD man page for shm_unlink states that it requires
// write permissions, but testing shows that read-write is required.
let fd = libc::shm_open(1 as *mut i8, // SHM_ANON
Copy link
Contributor

@dlrobertson dlrobertson Nov 6, 2017

Choose a reason for hiding this comment

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

👍 Could we add SHM_ANON to libc

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

What's the status on this? Could you perhaps request a new release to get this functionality exposed?...

@@ -962,6 +960,20 @@ fn create_shmem(name: CString, length: usize) -> c_int {
}
}

#[cfg(target_os="freebsd")]
fn create_shmem(_name: CString, length: usize) -> c_int {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a bit dirty: since the name construction has side effects, I doubt the compiler is smart enough to realise it can be omitted altogether...

Though to be honest, I'm not at all sure whether it's really worthwhile to refactor the code in order to avoid this -- so I guess that's just me thinking out loud, rather than an actual request to change anything :-)

@valpackett
Copy link
Author

What do you think about pulling this code into a separate tiny crate? This exact functionality is needed in a lot of things (mostly Wayland-related). Would you merge a patch that replaces this code with a dependency?

@dlrobertson
Copy link
Contributor

I think that is reasonable. memfd_create is only available post linux 3.17 and has no glibc wrapper. It must be called via syscall, so as long as that it is only used when a feature is enabled, I think a separate crate would be reasonable.

@valpackett
Copy link
Author

Done! https://github.com/myfreeweb/shmemfdrs & updated this PR to use it

Copy link
Contributor

@dlrobertson dlrobertson left a comment

Choose a reason for hiding this comment

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

+1 for the new crate.

src/lib.rs Outdated
target_os="linux"))]
#[macro_use]
extern crate syscall;
#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
Copy link
Contributor

Choose a reason for hiding this comment

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

Related to myfreeweb/shmemfdrs#1. The old implementation had a default that was used if the target os was not linux (with memfd) or freebsd.

Copy link
Contributor

Choose a reason for hiding this comment

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

The issue is no longer valid, but this still does not allow e.g. openbsd to use the shmemfdrs crate

Copy link
Author

Choose a reason for hiding this comment

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

You mean the hardcoded any(target_os="linux", target_os="freebsd") in here? Yeah, I would also like to replace them with… all(unix, not(any(target_os="macos", target_os="ios"))) I guess?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I think you are right again here. I seem to have done the same thing with extern crate mio and this is the same as the cfg for mod unix, so there should probably be a separate issue to possibly modify the cfgs.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is a bit confusing, since the implementation of the unix back-end should work with any Unix-like OS, but the conditional selecting the unix back-end (in https://github.com/servo/ipc-channel/blob/master/src/platform/mod.rs ) only works on specific platforms :-(

The only real change here as far as I can tell is that the shmemfdrs dependency requires introducing (yet another) redundant copy of the unix conditional.

(A long-standing issue on my personal ToDo-list is to try to factor out the platform conditionals in a central place, so everything else would only have to test for a custom platform_unix conditional, or something along these lines...)

Copy link
Author

Choose a reason for hiding this comment

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

Yeah. Arguably, it's not another copy, it's syscall's copy :D

+1 that it's a separate issue

Copy link
Contributor

Choose a reason for hiding this comment

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

@dlrobertson oh, I see you already figured that out :-)

Copy link
Contributor

@antrik antrik Dec 9, 2017

Choose a reason for hiding this comment

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

@myfreeweb nah, syscall doesn't have an exact copy of the unix conditional, since that one is (and always was) Linux-specific, so it didn't have the "not generic enough" problem. But yeah, separate issue.

@antrik
Copy link
Contributor

antrik commented Dec 9, 2017

Looks good to me. I'm not sure though what Servo's policy is for introducing new external dependencies?

@myfreeweb out of curiosity: how and for what purpose does WR need to use this?

@dlrobertson that's a bit tangential: but did we ever discuss checking for memfd support at run-time?...

@valpackett
Copy link
Author

valpackett commented Dec 9, 2017

WR? WebRender, on its own? Does it use ipc-channel at all?

Servo needs SHM_ANON to run sandboxed on FreeBSD: servo/servo#11625 (comment)

@dlrobertson
Copy link
Contributor

@antrik I think we discussed it but I think I forgot to create an issue for it and therefore forgot to investigate further.

@antrik
Copy link
Contributor

antrik commented Dec 9, 2017

@myfreeweb whoops, I guess I misread "Wayland" as "Webrender"...

So I'm a bit confused now: are there other users for shmemfdrs outside of ipc-channel?

@valpackett
Copy link
Author

No existing users as the crate was created today :) But potential users like Smithay/wayland-window#14

@antrik
Copy link
Contributor

antrik commented Dec 9, 2017

@myfreeweb going by the discussion there, it seems like they actually need a way to select the specific mechanism depending on client requests, rather than an automatic abstraction? So it doesn't seem like this crate will really help there...

The reason I'm bringing this up is because I am somewhat reluctant -- and from what I gathered, other Servo developers are too -- to introduce a new crate for code that is not actually likely to be used outside of Servo. That would just increase maintenance burden.

@valpackett
Copy link
Author

The mechanism being file descriptors or not file descriptors — not different ways of creating file descriptors :)

@antrik
Copy link
Contributor

antrik commented Dec 9, 2017

@myfreeweb I was pretty sure it was actually about temporary file based descriptors vs. anonymous descriptors? But then again, I'm not really familiar with the Wayland protocol -- so I guess I might be misreading it...

@valpackett
Copy link
Author

I made similar changes work in weston, so I know something :) Of course no one cares how a file descriptor is made.

Shared memory file descriptors are used to pass software-rendered buffers from the client to the compositor. The primary "other way" is passing GPU (EGL) buffers. And a compositor theoretically could support EGL only.

@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #187) made this pull request unmergeable. Please resolve the merge conflicts.

(which adds support for FreeBSD SHM_ANON)
@bors-servo
Copy link
Contributor

☔ The latest upstream changes (presumably #216) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants