LinuxCapabilities.h (3869B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_LinuxCapabilities_h 8 #define mozilla_LinuxCapabilities_h 9 10 #include <linux/capability.h> 11 #include <stdint.h> 12 13 #include "mozilla/Assertions.h" 14 #include "mozilla/Attributes.h" 15 #include "mozilla/PodOperations.h" 16 17 // This class is a relatively simple interface to manipulating the 18 // capabilities of a Linux process/thread; see the capabilities(7) man 19 // page for background information. 20 21 // Unfortunately, Android's kernel headers omit some definitions 22 // needed for the low-level capability interface. They're part of the 23 // stable syscall ABI, so it's safe to include them here. 24 #ifndef _LINUX_CAPABILITY_VERSION_3 25 # define _LINUX_CAPABILITY_VERSION_3 0x20080522 26 # define _LINUX_CAPABILITY_U32S_3 2 27 #endif 28 #ifndef CAP_TO_INDEX 29 # define CAP_TO_INDEX(x) ((x) >> 5) 30 # define CAP_TO_MASK(x) (1 << ((x) & 31)) 31 #endif 32 33 namespace mozilla { 34 35 class LinuxCapabilities final { 36 public: 37 // A class to represent a bit within the capability sets as an lvalue. 38 class BitRef { 39 __u32& mWord; 40 __u32 mMask; 41 friend class LinuxCapabilities; 42 BitRef(__u32& aWord, uint32_t aMask) : mWord(aWord), mMask(aMask) {} 43 BitRef(const BitRef& aBit) = default; 44 45 public: 46 MOZ_IMPLICIT operator bool() const { return mWord & mMask; } 47 BitRef& operator=(bool aSetTo) { 48 if (aSetTo) { 49 mWord |= mMask; 50 } else { 51 mWord &= mMask; 52 } 53 return *this; 54 } 55 }; 56 57 // The default value is the empty set. 58 LinuxCapabilities() { PodArrayZero(mBits); } 59 60 // Get the current thread's capability sets and assign them to this 61 // object. Returns whether it succeeded and sets errno on failure. 62 // Shouldn't fail unless the kernel is very old. 63 bool GetCurrent(); 64 65 // Try to set the current thread's capability sets to those 66 // specified in this object. Returns whether it succeeded and sets 67 // errno on failure. 68 bool SetCurrentRaw() const; 69 70 // The capability model requires that the permitted set always be a 71 // superset of the effective and inheritable sets. This method 72 // expands the permitted set as needed and then sets the current 73 // thread's capabilities, as described above. 74 bool SetCurrent() { 75 Normalize(); 76 return SetCurrentRaw(); 77 } 78 79 void Normalize() { 80 for (size_t i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) { 81 mBits[i].permitted |= mBits[i].effective | mBits[i].inheritable; 82 } 83 } 84 85 bool AnyEffective() const { 86 for (size_t i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) { 87 if (mBits[i].effective != 0) { 88 return true; 89 } 90 } 91 return false; 92 } 93 94 // These three methods expose individual bits in the three 95 // capability sets as objects that can be used as bool lvalues. 96 // The argument is the capability number, as defined in 97 // the <linux/capability.h> header. 98 BitRef Effective(unsigned aCap) { 99 return GenericBitRef(&__user_cap_data_struct::effective, aCap); 100 } 101 102 BitRef Permitted(unsigned aCap) { 103 return GenericBitRef(&__user_cap_data_struct::permitted, aCap); 104 } 105 106 BitRef Inheritable(unsigned aCap) { 107 return GenericBitRef(&__user_cap_data_struct::inheritable, aCap); 108 } 109 110 private: 111 __user_cap_data_struct mBits[_LINUX_CAPABILITY_U32S_3]; 112 113 BitRef GenericBitRef(__u32 __user_cap_data_struct::* aField, unsigned aCap) { 114 // Please don't pass untrusted data as the capability number. 115 MOZ_ASSERT(CAP_TO_INDEX(aCap) < _LINUX_CAPABILITY_U32S_3); 116 return BitRef(mBits[CAP_TO_INDEX(aCap)].*aField, CAP_TO_MASK(aCap)); 117 } 118 }; 119 120 } // namespace mozilla 121 122 #endif // mozilla_LinuxCapabilities_h