Home | History | Annotate | Download | only in init
      1 // Copyright (C) 2016 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "capabilities.h"
     16 
     17 #include <sys/capability.h>
     18 #include <sys/prctl.h>
     19 
     20 #include <map>
     21 #include <memory>
     22 
     23 #include <android-base/logging.h>
     24 #include <android-base/macros.h>
     25 
     26 #define CAP_MAP_ENTRY(cap) { #cap, CAP_##cap }
     27 
     28 static const std::map<std::string, int> cap_map = {
     29     CAP_MAP_ENTRY(CHOWN),
     30     CAP_MAP_ENTRY(DAC_OVERRIDE),
     31     CAP_MAP_ENTRY(DAC_READ_SEARCH),
     32     CAP_MAP_ENTRY(FOWNER),
     33     CAP_MAP_ENTRY(FSETID),
     34     CAP_MAP_ENTRY(KILL),
     35     CAP_MAP_ENTRY(SETGID),
     36     CAP_MAP_ENTRY(SETUID),
     37     CAP_MAP_ENTRY(SETPCAP),
     38     CAP_MAP_ENTRY(LINUX_IMMUTABLE),
     39     CAP_MAP_ENTRY(NET_BIND_SERVICE),
     40     CAP_MAP_ENTRY(NET_BROADCAST),
     41     CAP_MAP_ENTRY(NET_ADMIN),
     42     CAP_MAP_ENTRY(NET_RAW),
     43     CAP_MAP_ENTRY(IPC_LOCK),
     44     CAP_MAP_ENTRY(IPC_OWNER),
     45     CAP_MAP_ENTRY(SYS_MODULE),
     46     CAP_MAP_ENTRY(SYS_RAWIO),
     47     CAP_MAP_ENTRY(SYS_CHROOT),
     48     CAP_MAP_ENTRY(SYS_PTRACE),
     49     CAP_MAP_ENTRY(SYS_PACCT),
     50     CAP_MAP_ENTRY(SYS_ADMIN),
     51     CAP_MAP_ENTRY(SYS_BOOT),
     52     CAP_MAP_ENTRY(SYS_NICE),
     53     CAP_MAP_ENTRY(SYS_RESOURCE),
     54     CAP_MAP_ENTRY(SYS_TIME),
     55     CAP_MAP_ENTRY(SYS_TTY_CONFIG),
     56     CAP_MAP_ENTRY(MKNOD),
     57     CAP_MAP_ENTRY(LEASE),
     58     CAP_MAP_ENTRY(AUDIT_WRITE),
     59     CAP_MAP_ENTRY(AUDIT_CONTROL),
     60     CAP_MAP_ENTRY(SETFCAP),
     61     CAP_MAP_ENTRY(MAC_OVERRIDE),
     62     CAP_MAP_ENTRY(MAC_ADMIN),
     63     CAP_MAP_ENTRY(SYSLOG),
     64     CAP_MAP_ENTRY(WAKE_ALARM),
     65     CAP_MAP_ENTRY(BLOCK_SUSPEND),
     66     CAP_MAP_ENTRY(AUDIT_READ),
     67 };
     68 
     69 static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ");
     70 
     71 static bool ComputeCapAmbientSupported() {
     72     return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >= 0;
     73 }
     74 
     75 static unsigned int ComputeLastValidCap() {
     76     // Android does not support kernels < 3.8. 'CAP_WAKE_ALARM' has been present since 3.0, see
     77     // http://lxr.free-electrons.com/source/include/linux/capability.h?v=3.0#L360.
     78     unsigned int last_valid_cap = CAP_WAKE_ALARM;
     79     for (; prctl(PR_CAPBSET_READ, last_valid_cap, 0, 0, 0) >= 0; ++last_valid_cap);
     80 
     81     // |last_valid_cap| will be the first failing value.
     82     return last_valid_cap - 1;
     83 }
     84 
     85 static bool DropBoundingSet(const CapSet& to_keep) {
     86     unsigned int last_valid_cap = GetLastValidCap();
     87     // When dropping the bounding set, attempt to drop capabilities reported at
     88     // run-time, not at compile-time.
     89     // If the run-time kernel is older than the compile-time headers, this
     90     // avoids dropping an invalid capability. If the run-time kernel is newer
     91     // than the headers, this guarantees all capabilities (even those unknown at
     92     // compile time) will be dropped.
     93     for (size_t cap = 0; cap <= last_valid_cap; ++cap) {
     94         if (cap < to_keep.size() && to_keep.test(cap)) {
     95             // No need to drop this capability.
     96             continue;
     97         }
     98         if (cap_drop_bound(cap) == -1) {
     99             PLOG(ERROR) << "cap_drop_bound(" << cap << ") failed";
    100             return false;
    101         }
    102     }
    103     return true;
    104 }
    105 
    106 static bool SetProcCaps(const CapSet& to_keep, bool add_setpcap) {
    107     cap_t caps = cap_init();
    108     auto deleter = [](cap_t* p) { cap_free(*p); };
    109     std::unique_ptr<cap_t, decltype(deleter)> ptr_caps(&caps, deleter);
    110 
    111     cap_clear(caps);
    112     cap_value_t value[1];
    113     for (size_t cap = 0; cap < to_keep.size(); ++cap) {
    114         if (to_keep.test(cap)) {
    115             value[0] = cap;
    116             if (cap_set_flag(caps, CAP_INHERITABLE, arraysize(value), value, CAP_SET) != 0 ||
    117                 cap_set_flag(caps, CAP_PERMITTED, arraysize(value), value, CAP_SET) != 0) {
    118                 PLOG(ERROR) << "cap_set_flag(INHERITABLE|PERMITTED, " << cap << ") failed";
    119                 return false;
    120             }
    121         }
    122     }
    123 
    124     if (add_setpcap) {
    125         value[0] = CAP_SETPCAP;
    126         if (cap_set_flag(caps, CAP_PERMITTED, arraysize(value), value, CAP_SET) != 0 ||
    127             cap_set_flag(caps, CAP_EFFECTIVE, arraysize(value), value, CAP_SET) != 0) {
    128             PLOG(ERROR) << "cap_set_flag(PERMITTED|EFFECTIVE, " << CAP_SETPCAP << ") failed";
    129             return false;
    130         }
    131     }
    132 
    133     if (cap_set_proc(caps) != 0) {
    134         PLOG(ERROR) << "cap_set_proc(" << to_keep.to_ulong() << ") failed";
    135         return false;
    136     }
    137     return true;
    138 }
    139 
    140 static bool SetAmbientCaps(const CapSet& to_raise) {
    141     for (size_t cap = 0; cap < to_raise.size(); ++cap) {
    142         if (to_raise.test(cap)) {
    143             if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) {
    144                 PLOG(ERROR) << "prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, " << cap << ") failed";
    145                 return false;
    146             }
    147         }
    148     }
    149     return true;
    150 }
    151 
    152 int LookupCap(const std::string& cap_name) {
    153     auto e = cap_map.find(cap_name);
    154     if (e != cap_map.end()) {
    155         return e->second;
    156     } else {
    157         return -1;
    158     }
    159 }
    160 
    161 bool CapAmbientSupported() {
    162     static bool cap_ambient_supported = ComputeCapAmbientSupported();
    163     return cap_ambient_supported;
    164 }
    165 
    166 unsigned int GetLastValidCap() {
    167     static unsigned int last_valid_cap = ComputeLastValidCap();
    168     return last_valid_cap;
    169 }
    170 
    171 bool SetCapsForExec(const CapSet& to_keep) {
    172     // Need to keep SETPCAP to drop bounding set below.
    173     bool add_setpcap = true;
    174     if (!SetProcCaps(to_keep, add_setpcap)) {
    175         LOG(ERROR) << "failed to apply initial capset";
    176         return false;
    177     }
    178 
    179     if (!DropBoundingSet(to_keep)) {
    180         return false;
    181     }
    182 
    183     // If SETPCAP wasn't specifically requested, drop it now.
    184     add_setpcap = false;
    185     if (!SetProcCaps(to_keep, add_setpcap)) {
    186         LOG(ERROR) << "failed to apply final capset";
    187         return false;
    188     }
    189 
    190     // Add the capabilities to the ambient set so that they are preserved across
    191     // execve(2).
    192     // See http://man7.org/linux/man-pages/man7/capabilities.7.html.
    193     return SetAmbientCaps(to_keep);
    194 }
    195