1 // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved.
2 //
3 // StratoVirt is licensed under Mulan PSL v2.
4 // You can use this software according to the terms and conditions of the Mulan
5 // PSL v2.
6 // You may obtain a copy of Mulan PSL v2 at:
7 //         http://license.coscl.org.cn/MulanPSL2
8 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
9 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
10 // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 // See the Mulan PSL v2 for more details.
12 
13 use std::{fs, path::Path};
14 
15 use anyhow::{Context, Result};
16 
17 const APPARMOR_ENABLED_PATH: &str = "/sys/module/apparmor/parameters/enabled";
18 const APPARMOR_INTERFACE: &str = "/proc/self/attr/apparmor/exec";
19 const APPARMOR_LEGACY_INTERFACE: &str = "/proc/self/attr/exec";
20 
is_enabled() -> Result<bool>21 pub fn is_enabled() -> Result<bool> {
22     let enabled = fs::read_to_string(APPARMOR_ENABLED_PATH)
23         .with_context(|| format!("Failed to read {}", APPARMOR_ENABLED_PATH))?;
24     Ok(enabled.starts_with('Y'))
25 }
26 
apply_profile(profile: &str) -> Result<()>27 pub fn apply_profile(profile: &str) -> Result<()> {
28     if profile.is_empty() {
29         return Ok(());
30     }
31 
32     // Try the module specific subdirectory. This is recommended to configure LSMs
33     // since Linux kernel 5.1. AppArmor has such a directory since Linux kernel 5.8.
34     match activate_profile(Path::new(APPARMOR_INTERFACE), profile) {
35         Ok(_) => Ok(()),
36         Err(_) => activate_profile(Path::new(APPARMOR_LEGACY_INTERFACE), profile)
37             .with_context(|| "Failed to apply apparmor profile"),
38     }
39 }
40 
activate_profile(path: &Path, profile: &str) -> Result<()>41 fn activate_profile(path: &Path, profile: &str) -> Result<()> {
42     fs::write(path, format!("exec {}", profile))?;
43     Ok(())
44 }
45