Source code
Revision control
Copy as Markdown
Other Tools
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
#ifndef mozilla_LinuxCapabilities_h
#define mozilla_LinuxCapabilities_h
#include <linux/capability.h>
#include <stdint.h>
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/PodOperations.h"
// This class is a relatively simple interface to manipulating the
// capabilities of a Linux process/thread; see the capabilities(7) man
// page for background information.
// Unfortunately, Android's kernel headers omit some definitions
// needed for the low-level capability interface. They're part of the
// stable syscall ABI, so it's safe to include them here.
#ifndef _LINUX_CAPABILITY_VERSION_3
# define _LINUX_CAPABILITY_VERSION_3 0x20080522
# define _LINUX_CAPABILITY_U32S_3 2
#endif
#ifndef CAP_TO_INDEX
# define CAP_TO_INDEX(x) ((x) >> 5)
# define CAP_TO_MASK(x) (1 << ((x) & 31))
#endif
namespace mozilla {
class LinuxCapabilities final {
public:
// A class to represent a bit within the capability sets as an lvalue.
class BitRef {
__u32& mWord;
__u32 mMask;
friend class LinuxCapabilities;
BitRef(__u32& aWord, uint32_t aMask) : mWord(aWord), mMask(aMask) {}
BitRef(const BitRef& aBit) = default;
public:
MOZ_IMPLICIT operator bool() const { return mWord & mMask; }
BitRef& operator=(bool aSetTo) {
if (aSetTo) {
mWord |= mMask;
} else {
mWord &= mMask;
}
return *this;
}
};
// The default value is the empty set.
LinuxCapabilities() { PodArrayZero(mBits); }
// Get the current thread's capability sets and assign them to this
// object. Returns whether it succeeded and sets errno on failure.
// Shouldn't fail unless the kernel is very old.
bool GetCurrent();
// Try to set the current thread's capability sets to those
// specified in this object. Returns whether it succeeded and sets
// errno on failure.
bool SetCurrentRaw() const;
// The capability model requires that the permitted set always be a
// superset of the effective and inheritable sets. This method
// expands the permitted set as needed and then sets the current
// thread's capabilities, as described above.
bool SetCurrent() {
Normalize();
return SetCurrentRaw();
}
void Normalize() {
for (size_t i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) {
mBits[i].permitted |= mBits[i].effective | mBits[i].inheritable;
}
}
bool AnyEffective() const {
for (size_t i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) {
if (mBits[i].effective != 0) {
return true;
}
}
return false;
}
// These three methods expose individual bits in the three
// capability sets as objects that can be used as bool lvalues.
// The argument is the capability number, as defined in
// the <linux/capability.h> header.
BitRef Effective(unsigned aCap) {
return GenericBitRef(&__user_cap_data_struct::effective, aCap);
}
BitRef Permitted(unsigned aCap) {
return GenericBitRef(&__user_cap_data_struct::permitted, aCap);
}
BitRef Inheritable(unsigned aCap) {
return GenericBitRef(&__user_cap_data_struct::inheritable, aCap);
}
private:
__user_cap_data_struct mBits[_LINUX_CAPABILITY_U32S_3];
BitRef GenericBitRef(__u32 __user_cap_data_struct::*aField, unsigned aCap) {
// Please don't pass untrusted data as the capability number.
MOZ_ASSERT(CAP_TO_INDEX(aCap) < _LINUX_CAPABILITY_U32S_3);
return BitRef(mBits[CAP_TO_INDEX(aCap)].*aField, CAP_TO_MASK(aCap));
}
};
} // namespace mozilla
#endif // mozilla_LinuxCapabilities_h