1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! A rust library wrapping the libcap functionality.
18 
19 use anyhow::{bail, Result};
20 use cap_bindgen::{
21     cap_clear_flag, cap_drop_bound, cap_flag_t, cap_free, cap_get_proc, cap_set_proc, cap_value_t,
22     CAP_LAST_CAP,
23 };
24 use nix::errno::Errno;
25 
26 /// Removes inheritable capabilities set for this process.
27 /// See: https://man7.org/linux/man-pages/man7/capabilities.7.html
drop_inheritable_caps() -> Result<()>28 pub fn drop_inheritable_caps() -> Result<()> {
29     // SAFETY: we do not manipulate memory handled by libcap.
30     unsafe {
31         let caps = cap_get_proc();
32         scopeguard::defer! {
33             cap_free(caps as *mut std::os::raw::c_void);
34         }
35         if cap_clear_flag(caps, cap_flag_t::CAP_INHERITABLE) < 0 {
36             let e = Errno::last();
37             bail!("cap_clear_flag failed: {:?}", e)
38         }
39         if cap_set_proc(caps) < 0 {
40             let e = Errno::last();
41             bail!("cap_set_proc failed: {:?}", e)
42         }
43     }
44     Ok(())
45 }
46 
47 /// Drop bounding set capabitilies for this process.
48 /// See: https://man7.org/linux/man-pages/man7/capabilities.7.html
drop_bounding_set() -> Result<()>49 pub fn drop_bounding_set() -> Result<()> {
50     let mut cap_id: cap_value_t = 0;
51     while cap_id <= CAP_LAST_CAP.try_into().unwrap() {
52         // SAFETY: we do not manipulate memory handled by libcap.
53         unsafe {
54             if cap_drop_bound(cap_id) == -1 {
55                 let e = Errno::last();
56                 bail!("cap_drop_bound failed for {}: {:?}", cap_id, e);
57             }
58         }
59         cap_id += 1;
60     }
61     Ok(())
62 }
63 
64 #[cfg(test)]
65 mod tests {
66     use super::*;
67 
68     // Basic test to verify that calling drop_inheritable_caps doesn't fail
69     #[test]
test_drop_inheritable_caps()70     fn test_drop_inheritable_caps() {
71         let result = drop_inheritable_caps();
72         assert!(result.is_ok(), "failed with: {:?}", result)
73     }
74 }
75