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