1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use libc::c_int;
use libc::c_void;

use super::errno_result;
use super::Result;

#[allow(non_camel_case_types)]
type cap_t = *mut c_void;

#[link(name = "cap")]
extern "C" {
    fn cap_init() -> cap_t;
    fn cap_free(ptr: *mut c_void) -> c_int;
    fn cap_set_proc(cap: cap_t) -> c_int;
}

/// Drops all capabilities (permitted, inheritable, and effective) from the current process.
pub fn drop_capabilities() -> Result<()> {
    // SAFETY:
    // Safe because we do not actually manipulate any memory handled by libcap
    // and we check errors.
    unsafe {
        let caps = cap_init();
        if caps.is_null() {
            return errno_result();
        }

        // Freshly initialized capabilities do not have any bits set, so applying them
        // will drop all capabilities from the process.
        // Safe because we will check the result and otherwise do not touch the memory.
        let ret = cap_set_proc(caps);
        // We need to free capabilities regardless of success of the operation above.
        cap_free(caps);
        // Now check if we managed to apply (drop) capabilities.
        if ret < 0 {
            return errno_result();
        }
    }
    Ok(())
}