From b0eef29be78ea4fca45d92bc20a4107fc3967c32 Mon Sep 17 00:00:00 2001
From: Wei Gao <gaowei66@huawei.com>
Date: Fri, 18 Dec 2020 00:18:44 -0500
Subject: [PATCH] seccomp: replace prctl(2) by seccomp(2) to use seccomp.

1. Replace prctl(2) by seccomp(2) syscall.
2. Add flag SECCOMP_FILTER_FLAG_TSYNC to sync all thread seccomp filter.
3. Remove seccomp args im vm_start and CPU::start.

Signed-off-by: Wei Gao <gaowei66@huawei.com>
---
 device_model/src/cpu/mod.rs      | 21 ++-------------------
 device_model/src/micro_vm/mod.rs |  7 +++----
 docs/config_guidebook.md         |  2 +-
 src/main.rs                      |  5 +----
 util/src/seccomp.rs              | 15 ++++++++++-----
 5 files changed, 17 insertions(+), 33 deletions(-)

diff --git a/device_model/src/cpu/mod.rs b/device_model/src/cpu/mod.rs
index c754f38..203fea1 100644
--- a/device_model/src/cpu/mod.rs
+++ b/device_model/src/cpu/mod.rs
@@ -159,13 +159,7 @@ pub trait CPUInterface {
     /// * `cpu` - The cpu instance shared in thread.
     /// * `thread_barrier` - The cpu thread barrier.
     /// * `paused` - After started, paused vcpu or not.
-    /// * `use seccomp` - Use seccomp in vcpu thread.
-    fn start(
-        cpu: Arc<Self>,
-        thread_barrier: Arc<Barrier>,
-        paused: bool,
-        use_seccomp: bool,
-    ) -> Result<()>
+    fn start(cpu: Arc<Self>, thread_barrier: Arc<Barrier>, paused: bool) -> Result<()>
     where
         Self: std::marker::Sized;
 
@@ -336,12 +330,7 @@ impl CPUInterface for CPU {
         Ok(())
     }
 
-    fn start(
-        cpu: Arc<CPU>,
-        thread_barrier: Arc<Barrier>,
-        paused: bool,
-        use_seccomp: bool,
-    ) -> Result<()> {
+    fn start(cpu: Arc<CPU>, thread_barrier: Arc<Barrier>, paused: bool) -> Result<()> {
         let (cpu_state, _) = &*cpu.state;
         if *cpu_state.lock().unwrap() == CpuLifecycleState::Running {
             return Err(ErrorKind::StartVcpu("Cpu is already running".to_string()).into());
@@ -372,12 +361,6 @@ impl CPUInterface for CPU {
                 thread_barrier.wait();
 
                 info!("vcpu{} start running", cpu.id);
-                if use_seccomp {
-                    if let Err(e) = crate::micro_vm::micro_syscall::register_seccomp() {
-                        error!("Failed to register seccomp in cpu{} thread:{}", cpu.id, e);
-                    }
-                }
-
                 loop {
                     if !cpu.ready_for_running() {
                         break;
diff --git a/device_model/src/micro_vm/mod.rs b/device_model/src/micro_vm/mod.rs
index 7bf582e..5df63aa 100644
--- a/device_model/src/micro_vm/mod.rs
+++ b/device_model/src/micro_vm/mod.rs
@@ -463,14 +463,13 @@ impl LightMachine {
     /// # Arguments
     ///
     /// * `paused` - After started, paused all vcpu or not.
-    /// * `use_seccomp` - If use seccomp sandbox or not.
-    pub fn vm_start(&self, paused: bool, use_seccomp: bool) -> Result<()> {
+    pub fn vm_start(&self, paused: bool) -> Result<()> {
         let cpus_thread_barrier = Arc::new(Barrier::new((self.cpu_topo.max_cpus + 1) as usize));
 
         for cpu_index in 0..self.cpu_topo.max_cpus {
             let cpu_thread_barrier = cpus_thread_barrier.clone();
             let cpu = self.cpus.lock().unwrap()[cpu_index as usize].clone();
-            CPU::start(cpu, cpu_thread_barrier, paused, use_seccomp)?;
+            CPU::start(cpu, cpu_thread_barrier, paused)?;
         }
 
         let mut vmstate = self.vm_state.deref().0.lock().unwrap();
@@ -640,7 +639,7 @@ impl MachineLifecycle for LightMachine {
 
         match (old, new) {
             (Created, Running) => {
-                if let Err(e) = self.vm_start(false, false) {
+                if let Err(e) = self.vm_start(false) {
                     error!("Vm lifecycle error:{}", e);
                 };
             }
diff --git a/docs/config_guidebook.md b/docs/config_guidebook.md
index a309018..ea31fc4 100644
--- a/docs/config_guidebook.md
+++ b/docs/config_guidebook.md
@@ -493,7 +493,7 @@ And you can also restore StratoVirt's **pid number** to a file by:
 
 ### 4.2 Seccomp
 
-StratoVirt use [prctl(2)](https://man7.org/linux/man-pages/man2/prctl.2.html) to limit the syscalls
+StratoVirt use [seccomp(2)](https://man7.org/linux/man-pages/man2/seccomp.2.html) to limit the syscalls
 in StratoVirt process by default. StratoVirt use only 33 syscalls in aarch64 (34 syscalls in x86_64) after running. 
 It will make a slight influence on performance to StratoVirt. If you want to disable seccomp, you can
 run StratoVirt with `-disable-seccomp`.
diff --git a/src/main.rs b/src/main.rs
index c0000bd..dd2b260 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -134,10 +134,7 @@ fn real_main(cmd_args: &arg_parser::ArgMatches) -> Result<()> {
     .chain_err(|| "Failed to add api event to MainLoop")?;
 
     vm.realize()?;
-    vm.vm_start(
-        cmd_args.is_present("freeze_cpu"),
-        !cmd_args.is_present("disable-seccomp"),
-    )?;
+    vm.vm_start(cmd_args.is_present("freeze_cpu"))?;
 
     if !cmd_args.is_present("disable-seccomp") {
         register_seccomp()?;
diff --git a/util/src/seccomp.rs b/util/src/seccomp.rs
index 8919c50..7a782c6 100644
--- a/util/src/seccomp.rs
+++ b/util/src/seccomp.rs
@@ -116,6 +116,10 @@ const SECCOMP_RET_TRACE: u32 = 0x7ff0_0000;
 const SECCOMP_RET_ALLOW: u32 = 0x7fff_0000;
 /// See: https://elixir.bootlin.com/linux/v4.19.123/source/include/uapi/linux/seccomp.h#L45
 const SECCOMP_RET_MASK: u32 = 0x0000_ffff;
+/// See: https://elixir.bootlin.com/linux/v4.19.123/source/include/uapi/linux/seccomp.h#L16
+const SECCOMP_MODE_FILTER: u32 = 1;
+/// See: https://elixir.bootlin.com/linux/v4.19.123/source/include/uapi/linux/seccomp.h#L21
+const SECCOMP_FILETER_FLAG_TSYNC: u32 = 1;
 
 /// System call convention as an AUDIT_ARCH_* value
 #[cfg(target_arch = "x86_64")]
@@ -409,16 +413,17 @@ impl SyscallFilter {
         };
         let bpf_prog_ptr = &prog as *const SockFProg;
 
-        // Use prctl(2) to make bpf rules take effect.
+        // Use seccomp(2) to make bpf rules take effect.
         let ret = unsafe {
-            libc::prctl(
-                libc::PR_SET_SECCOMP,
-                libc::SECCOMP_MODE_FILTER,
+            libc::syscall(
+                libc::SYS_seccomp,
+                SECCOMP_MODE_FILTER,
+                SECCOMP_FILETER_FLAG_TSYNC,
                 bpf_prog_ptr,
             )
         };
         if ret != 0 {
-            bail!("Seccomp: prctl(2) set seccomp filter mode failed.");
+            bail!("Seccomp: seccomp(2) set seccomp filter mode failed.");
         }
 
         Ok(())
-- 
2.27.0

