blob: 26d9d7738569fbdf919cf8888341c917d5380534 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/starnix/tests/syscalls/cpp/capabilities_helper.h"
#include <string.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/capability.h>
#include <linux/prctl.h>
#include "src/starnix/tests/syscalls/cpp/test_helper.h"
namespace test_helper {
// Drops all capabilities from the effective, permitted, and inheritable sets.
void DropAllCapabilities() {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3] = {{0, 0, 0}};
SAFE_SYSCALL(syscall(SYS_capset, &header, &caps));
}
// Checks if a capability is in the effective set.
bool HasCapability(int cap) { return HasCapabilityEffective(cap); }
// Unsets a capability from the effective set.
void UnsetCapability(int cap) { UnsetCapabilityEffective(cap); }
// Checks whether a capability is in the thread's effective set.
bool HasCapabilityEffective(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
return caps[CAP_TO_INDEX(cap)].effective & CAP_TO_MASK(cap);
}
// Checks whether a capability is in the thread's permitted set.
bool HasCapabilityPermitted(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
return caps[CAP_TO_INDEX(cap)].permitted & CAP_TO_MASK(cap);
}
// Checks whether a capability is in the thread's inheritable set.
bool HasCapabilityInheritable(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
return caps[CAP_TO_INDEX(cap)].inheritable & CAP_TO_MASK(cap);
}
bool HasCapabilityAmbient(int cap) {
return SAFE_SYSCALL(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, cap, 0, 0)) == 1;
}
bool HasCapabilityBounding(int cap) { return SAFE_SYSCALL(prctl(PR_CAPBSET_READ, cap)) == 1; }
// Removes a capability from the thread's effective set.
void UnsetCapabilityEffective(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
caps[CAP_TO_INDEX(cap)].effective &= ~CAP_TO_MASK(cap);
SAFE_SYSCALL(syscall(SYS_capset, &header, &caps));
}
// Removes a capability from the thread's permitted set.
void UnsetCapabilityPermitted(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
caps[CAP_TO_INDEX(cap)].permitted &= ~CAP_TO_MASK(cap);
SAFE_SYSCALL(syscall(SYS_capset, &header, &caps));
}
// Removes a capability from the thread's inheritable set.
void UnsetCapabilityInheritable(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
caps[CAP_TO_INDEX(cap)].inheritable &= ~CAP_TO_MASK(cap);
SAFE_SYSCALL(syscall(SYS_capset, &header, &caps));
}
// Removes a capability from the thread's ambient set.
void UnsetCapabilityAmbient(int cap) {
SAFE_SYSCALL(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, cap, 0, 0));
}
// Removes a capability from the thread's bounding set.
void UnsetCapabilityBounding(int cap) { SAFE_SYSCALL(prctl(PR_CAPBSET_DROP, cap)); }
// Sets a capability in the thread's effective set.
void SetCapabilityEffective(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
caps[CAP_TO_INDEX(cap)].effective |= CAP_TO_MASK(cap);
SAFE_SYSCALL(syscall(SYS_capset, &header, &caps));
}
// Sets a capability in the thread's permitted set.
void SetCapabilityPermitted(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
caps[CAP_TO_INDEX(cap)].permitted |= CAP_TO_MASK(cap);
SAFE_SYSCALL(syscall(SYS_capset, &header, &caps));
}
// Sets a capability in the thread's inheritable set.
void SetCapabilityInheritable(int cap) {
__user_cap_header_struct header;
memset(&header, 0, sizeof(header));
header.version = _LINUX_CAPABILITY_VERSION_3;
__user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
SAFE_SYSCALL(syscall(SYS_capget, &header, &caps));
caps[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap);
SAFE_SYSCALL(syscall(SYS_capset, &header, &caps));
}
// Sets a capability in the thread's ambient set.
void SetCapabilityAmbient(int cap) {
SAFE_SYSCALL(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0L, 0L));
}
void DropAllAmbientCapabilities() {
SAFE_SYSCALL(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0L, 0L, 0L));
}
} // namespace test_helper