From f052cfefc8d6d27fa068c34190615db1819b8fef Mon Sep 17 00:00:00 2001 From: paulhsia Date: Tue, 22 Jan 2019 15:22:25 +0800 Subject: [PATCH] linux: Add ac97 device with CRAS backend Add an ac97 device that plays audio through CRAS audio server. BUG=chromium:781398 BUG=chromium:907520 TEST=Test building by $ cargo build TEST=Deploy crosvm to DUT and test audio functionality CQ-DEPEND=CL:1429311 CQ-DEPEND=CL:1429542 Change-Id: Ia273d8f1e82c20d1f1882f088886458339399aae Reviewed-on: https://chromium-review.googlesource.com/1426282 Commit-Ready: Chih-Yang Hsia Tested-by: kokoro Tested-by: Chih-Yang Hsia Reviewed-by: Chih-Yang Hsia --- Cargo.lock | 19 ++++++++++ Cargo.toml | 2 + seccomp/arm/cras_audio_device.policy | 49 +++++++++++++++++++++++++ seccomp/x86_64/cras_audio_device.policy | 47 ++++++++++++++++++++++++ src/linux.rs | 15 ++++++++ src/main.rs | 7 ++++ 6 files changed, 139 insertions(+) create mode 100644 seccomp/arm/cras_audio_device.policy create mode 100644 seccomp/x86_64/cras_audio_device.policy diff --git a/Cargo.lock b/Cargo.lock index ea2b856b49..741f4e80e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,6 +69,13 @@ name = "cfg-if" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cras-sys" +version = "0.1.0" +dependencies = [ + "data_model 0.1.0", +] + [[package]] name = "crosvm" version = "0.1.0" @@ -88,6 +95,7 @@ dependencies = [ "kvm 0.1.0", "kvm_sys 0.1.0", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libcras 0.1.0", "msg_socket 0.1.0", "net_util 0.1.0", "p9 0.1.0", @@ -231,6 +239,17 @@ name = "libc" version = "0.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libcras" +version = "0.1.0" +dependencies = [ + "audio_streams 0.1.0", + "cras-sys 0.1.0", + "data_model 0.1.0", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sys_util 0.1.0", +] + [[package]] name = "log" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index 084d2087d3..098d4b543c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ usb_util = { path = "usb_util", optional = true } kernel_cmdline = { path = "kernel_cmdline" } kernel_loader = { path = "kernel_loader" } libc = "=0.2.44" +libcras = "*" byteorder = "=1.1.0" net_util = { path = "net_util" } vhost = { path = "vhost" } @@ -71,6 +72,7 @@ sys_util = "*" assertions = { path = "assertions" } audio_streams = { path = "../../third_party/adhd/audio_streams" } # ignored by ebuild data_model = { path = "data_model" } +libcras = { path = "../../third_party/adhd/cras/client/libcras" } # ignored by ebuild poll_token_derive = { path = "sys_util/poll_token_derive" } sync = { path = "sync" } sys_util = { path = "sys_util" } diff --git a/seccomp/arm/cras_audio_device.policy b/seccomp/arm/cras_audio_device.policy new file mode 100644 index 0000000000..829381e08a --- /dev/null +++ b/seccomp/arm/cras_audio_device.policy @@ -0,0 +1,49 @@ +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +close: 1 +dup: 1 +dup2: 1 +exit: 1 +exit_group: 1 +futex: 1 +gettimeofday: 1 +madvise: 1 +# Disallow mmap with PROT_EXEC set. The syntax here doesn't allow bit +# negation, thus the manually negated mask constant. +mmap2: arg2 in 0xfffffffb +mprotect: arg2 in 0xfffffffb +munmap: 1 +read: 1 +recv: 1 +sched_getaffinity: 1 +set_robust_list: 1 +sigaltstack: 1 +# Disallow clone's other than new threads. +clone: arg0 & 0x00010000 +write: 1 +eventfd2: 1 +nanosleep: 1 +poll: 1 +ppoll: 1 +getpid: 1 +# Allow PR_SET_NAME only. +prctl: arg0 == 15 +prlimit64: 1 +restart_syscall: 1 +setrlimit: 1 +epoll_create1: 1 +epoll_ctl: 1 +epoll_wait: 1 +# Kill child thread when it fails +tgkill: 1 +# Real time priority +rt_sigprocmask: 1 +rt_sigaction: 1 +rt_sigreturn: 1 +# Sockets +recvmsg: 1 +sendmsg: 1 +socketpair: arg0 == AF_UNIX +clock_gettime: 1 diff --git a/seccomp/x86_64/cras_audio_device.policy b/seccomp/x86_64/cras_audio_device.policy new file mode 100644 index 0000000000..9257a1898a --- /dev/null +++ b/seccomp/x86_64/cras_audio_device.policy @@ -0,0 +1,47 @@ +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +close: 1 +dup: 1 +dup2: 1 +exit: 1 +exit_group: 1 +futex: 1 +# Disallow mmap with PROT_EXEC set. The syntax here doesn't allow bit +# negation, thus the manually negated mask constant. +mmap: arg2 in 0xfffffffb +mprotect: arg2 in 0xfffffffb +madvise: 1 +munmap: 1 +read: 1 +recvfrom: 1 +sched_getaffinity: 1 +set_robust_list: 1 +sigaltstack: 1 +# Disallow clone's other than new threads. +clone: arg0 & 0x00010000 +write: 1 +eventfd2: 1 +nanosleep: 1 +poll: 1 +ppoll: 1 +getpid: 1 +# Allow PR_SET_NAME only. +prctl: arg0 == 15 +prlimit64: 1 +restart_syscall: 1 +setrlimit: 1 +epoll_create1: 1 +epoll_ctl: 1 +epoll_wait: 1 +# Kill child thread when it fails +tgkill: 1 +# Real time priority +rt_sigprocmask: 1 +rt_sigaction: 1 +rt_sigreturn: 1 +# Sockets +recvmsg: 1 +sendmsg: 1 +socketpair: arg0 == AF_UNIX diff --git a/src/linux.rs b/src/linux.rs index 8c33d12e1f..a61392bf6f 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -26,6 +26,7 @@ use byteorder::{ByteOrder, LittleEndian}; use devices::{self, PciDevice, VirtioPciDevice}; use io_jail::{self, Minijail}; use kvm::*; +use libcras::CrasClient; use msg_socket::{MsgReceiver, MsgSender, MsgSocket, UnlinkMsgSocket}; use net_util::{Error as NetError, Tap}; use qcow::{self, ImageType, QcowFile}; @@ -633,6 +634,20 @@ fn create_virtio_devs( pci_devices.push((pci_dev, stub.jail)); } + if cfg.cras_audio { + let cras_audio_box = Box::new(devices::Ac97Dev::new( + (*mem).clone(), + Box::new(CrasClient::new()?), + )); + let cras_audio_jail = if cfg.multiprocess { + let policy_path: PathBuf = cfg.seccomp_policy_dir.join("cras_audio_device.policy"); + Some(create_base_minijail(empty_root_path, &policy_path)?) + } else { + None + }; + pci_devices.push((cras_audio_box, cras_audio_jail)); + } + if cfg.null_audio { let null_audio_box = Box::new(devices::Ac97Dev::new( (*mem).clone(), diff --git a/src/main.rs b/src/main.rs index 555c98d300..5847087b7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ extern crate kernel_loader; extern crate kvm; extern crate kvm_sys; extern crate libc; +extern crate libcras; extern crate net_util; extern crate qcow; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] @@ -93,6 +94,7 @@ pub struct Config { multiprocess: bool, seccomp_policy_dir: PathBuf, gpu: bool, + cras_audio: bool, null_audio: bool, } @@ -120,6 +122,7 @@ impl Default for Config { shared_dirs: Vec::new(), multiprocess: !cfg!(feature = "default-no-sandbox"), seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR), + cras_audio: false, null_audio: false, } } @@ -212,6 +215,9 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: })?, ) } + "cras-audio" => { + cfg.cras_audio = true; + } "null-audio" => { cfg.null_audio = true; } @@ -497,6 +503,7 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> { "IP address to assign to host tap interface."), Argument::value("netmask", "NETMASK", "Netmask for VM subnet."), Argument::value("mac", "MAC", "MAC address for VM."), + Argument::flag("cras-audio", "Add an audio device to the VM that plays samples through CRAS server"), Argument::flag("null-audio", "Add an audio device to the VM that plays samples to /dev/null"), Argument::value("wayland-sock", "PATH", "Path to the Wayland socket to use."), #[cfg(feature = "wl-dmabuf")]