| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //! A rust library wrapping the libcap functionality. |
| |
| use anyhow::{bail, Result}; |
| use cap_bindgen::{ |
| cap_clear_flag, cap_drop_bound, cap_flag_t, cap_free, cap_get_proc, cap_set_proc, cap_value_t, |
| CAP_LAST_CAP, |
| }; |
| use nix::errno::Errno; |
| |
| /// Removes inheritable capabilities set for this process. |
| /// See: https://man7.org/linux/man-pages/man7/capabilities.7.html |
| pub fn drop_inheritable_caps() -> Result<()> { |
| // SAFETY: we do not manipulate memory handled by libcap. |
| unsafe { |
| let caps = cap_get_proc(); |
| scopeguard::defer! { |
| cap_free(caps as *mut std::os::raw::c_void); |
| } |
| if cap_clear_flag(caps, cap_flag_t::CAP_INHERITABLE) < 0 { |
| let e = Errno::last(); |
| bail!("cap_clear_flag failed: {:?}", e) |
| } |
| if cap_set_proc(caps) < 0 { |
| let e = Errno::last(); |
| bail!("cap_set_proc failed: {:?}", e) |
| } |
| } |
| Ok(()) |
| } |
| |
| /// Drop bounding set capabitilies for this process. |
| /// See: https://man7.org/linux/man-pages/man7/capabilities.7.html |
| pub fn drop_bounding_set() -> Result<()> { |
| let mut cap_id: cap_value_t = 0; |
| while cap_id <= CAP_LAST_CAP.try_into().unwrap() { |
| // SAFETY: we do not manipulate memory handled by libcap. |
| unsafe { |
| if cap_drop_bound(cap_id) == -1 { |
| let e = Errno::last(); |
| bail!("cap_drop_bound failed for {}: {:?}", cap_id, e); |
| } |
| } |
| cap_id += 1; |
| } |
| Ok(()) |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| // Basic test to verify that calling drop_inheritable_caps doesn't fail |
| #[test] |
| fn test_drop_inheritable_caps() { |
| let result = drop_inheritable_caps(); |
| assert!(result.is_ok(), "failed with: {:?}", result) |
| } |
| } |