mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-10 20:19:07 +00:00
sys_util: shm: make using names with shared memory more convenient
This change adds a string based constructor of `SharedMemory` as well as adding a method for retrieving that name from the underlying file. This change also includes a new anonymous constructor. TEST=cargo test -p sys_util BUG=None Change-Id: Ibd7a28851c8a0f41e595ee35b35f0d06fef1e1d9 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1797187 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Zach Reizner <zachr@chromium.org> Tested-by: Zach Reizner <zachr@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
0b86007d3e
commit
532533dd39
1 changed files with 65 additions and 16 deletions
|
@ -2,14 +2,15 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fs::{read_link, File};
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
|
||||
use libc::{
|
||||
self, c_char, c_int, c_long, c_uint, close, fcntl, ftruncate64, off64_t, syscall, F_ADD_SEALS,
|
||||
F_GET_SEALS, F_SEAL_GROW, F_SEAL_SEAL, F_SEAL_SHRINK, F_SEAL_WRITE, MFD_ALLOW_SEALING,
|
||||
self, c_char, c_int, c_long, c_uint, close, fcntl, ftruncate64, off64_t, syscall, EINVAL,
|
||||
F_ADD_SEALS, F_GET_SEALS, F_SEAL_GROW, F_SEAL_SEAL, F_SEAL_SHRINK, F_SEAL_WRITE,
|
||||
MFD_ALLOW_SEALING,
|
||||
};
|
||||
use syscall_defines::linux::LinuxSyscall::SYS_memfd_create;
|
||||
|
||||
|
@ -97,6 +98,22 @@ impl MemfdSeals {
|
|||
}
|
||||
|
||||
impl SharedMemory {
|
||||
/// Convenience function for `SharedMemory::new` that is always named and accepts a wide variety
|
||||
/// of string-like types.
|
||||
///
|
||||
/// Note that the given name may not have NUL characters anywhere in it, or this will return an
|
||||
/// error.
|
||||
pub fn named<T: Into<Vec<u8>>>(name: T) -> Result<SharedMemory> {
|
||||
Self::new(Some(
|
||||
&CString::new(name).map_err(|_| errno::Error::new(EINVAL))?,
|
||||
))
|
||||
}
|
||||
|
||||
/// Convenience function for `SharedMemory::new` that has an arbitrary and unspecified name.
|
||||
pub fn anon() -> Result<SharedMemory> {
|
||||
Self::new(None)
|
||||
}
|
||||
|
||||
/// Creates a new shared memory file descriptor with zero size.
|
||||
///
|
||||
/// If a name is given, it will appear in `/proc/self/fd/<shm fd>` for the purposes of
|
||||
|
@ -176,6 +193,24 @@ impl SharedMemory {
|
|||
self.size = size;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reads the name from the underlying file as a `String`.
|
||||
///
|
||||
/// If the underlying file was not created with `SharedMemory::new` or with `memfd_create`, the
|
||||
/// results are undefined. Because this returns a `String`, the name's bytes are interpreted as
|
||||
/// utf-8.
|
||||
pub fn read_name(&self) -> Result<String> {
|
||||
let fd_path = format!("/proc/self/fd/{}", self.as_raw_fd());
|
||||
let link_name = read_link(fd_path)?;
|
||||
link_name
|
||||
.to_str()
|
||||
.map(|s| {
|
||||
s.trim_start_matches("/memfd:")
|
||||
.trim_end_matches(" (deleted)")
|
||||
.to_owned()
|
||||
})
|
||||
.ok_or(errno::Error::new(EINVAL))
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for SharedMemory {
|
||||
|
@ -262,18 +297,35 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::fs::read_link;
|
||||
|
||||
use data_model::VolatileMemory;
|
||||
|
||||
use crate::MemoryMapping;
|
||||
|
||||
#[test]
|
||||
fn named() {
|
||||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
const TEST_NAME: &str = "Name McCool Person";
|
||||
let shm = SharedMemory::named(TEST_NAME).expect("failed to create shared memory");
|
||||
assert_eq!(shm.read_name(), Ok(TEST_NAME.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anon() {
|
||||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
SharedMemory::anon().expect("failed to create shared memory");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new() {
|
||||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
let shm = SharedMemory::new(None).expect("failed to create shared memory");
|
||||
let shm = SharedMemory::anon().expect("failed to create shared memory");
|
||||
assert_eq!(shm.size(), 0);
|
||||
}
|
||||
|
||||
|
@ -282,7 +334,7 @@ mod tests {
|
|||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
let mut shm = SharedMemory::new(None).expect("failed to create shared memory");
|
||||
let mut shm = SharedMemory::anon().expect("failed to create shared memory");
|
||||
shm.set_size(1024)
|
||||
.expect("failed to set shared memory size");
|
||||
assert_eq!(shm.size(), 1024);
|
||||
|
@ -293,7 +345,7 @@ mod tests {
|
|||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
let mut shm = SharedMemory::new(None).expect("failed to create shared memory");
|
||||
let mut shm = SharedMemory::anon().expect("failed to create shared memory");
|
||||
shm.set_size(0x7fff_ffff_ffff_ffff)
|
||||
.expect("failed to set shared memory size");
|
||||
assert_eq!(shm.size(), 0x7fff_ffff_ffff_ffff);
|
||||
|
@ -304,7 +356,7 @@ mod tests {
|
|||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
let mut shm = SharedMemory::new(None).expect("failed to create shared memory");
|
||||
let mut shm = SharedMemory::anon().expect("failed to create shared memory");
|
||||
shm.set_size(0x8000_0000_0000_0000).unwrap_err();
|
||||
assert_eq!(shm.size(), 0);
|
||||
}
|
||||
|
@ -317,10 +369,7 @@ mod tests {
|
|||
let name = "very unique name";
|
||||
let cname = CString::new(name).unwrap();
|
||||
let shm = SharedMemory::new(Some(&cname)).expect("failed to create shared memory");
|
||||
let fd_path = format!("/proc/self/fd/{}", shm.as_raw_fd());
|
||||
let link_name =
|
||||
read_link(fd_path).expect("failed to read link of shared memory /proc/self/fd entry");
|
||||
assert!(link_name.to_str().unwrap().contains(name));
|
||||
assert_eq!(shm.read_name(), Ok(name.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -328,7 +377,7 @@ mod tests {
|
|||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
let mut shm = SharedMemory::new(None).expect("failed to create shared memory");
|
||||
let mut shm = SharedMemory::anon().expect("failed to create shared memory");
|
||||
let mut seals = shm.get_seals().expect("failed to get seals");
|
||||
assert_eq!(seals.bitmask(), 0);
|
||||
seals.set_seal_seal();
|
||||
|
@ -344,7 +393,7 @@ mod tests {
|
|||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
let mut shm = SharedMemory::new(None).expect("failed to create shared memory");
|
||||
let mut shm = SharedMemory::anon().expect("failed to create shared memory");
|
||||
shm.set_size(4096)
|
||||
.expect("failed to set shared memory size");
|
||||
|
||||
|
@ -373,7 +422,7 @@ mod tests {
|
|||
if !kernel_has_memfd() {
|
||||
return;
|
||||
}
|
||||
let mut shm = SharedMemory::new(None).expect("failed to create shared memory");
|
||||
let mut shm = SharedMemory::anon().expect("failed to create shared memory");
|
||||
shm.set_size(8092)
|
||||
.expect("failed to set shared memory size");
|
||||
|
||||
|
|
Loading…
Reference in a new issue