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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
/*
* Copyright (c) 1997,2020 Andrew G Morgan <morgan@kernel.org>
*
* This file contains internal definitions for the various functions in
* this small capability library.
*/
#ifndef LIBCAP_H
#define LIBCAP_H
#include <errno.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/capability.h>
#ifndef __u8
#define __u8 uint8_t
#endif /* __8 */
#ifndef __u32
#define __u32 uint32_t
#endif /* __u32 */
/* include the names for the caps and a definition of __CAP_BITS */
#include "cap_names.h"
#ifndef _LINUX_CAPABILITY_U32S_1
# define _LINUX_CAPABILITY_U32S_1 1
#endif /* ndef _LINUX_CAPABILITY_U32S_1 */
/*
* Do we match the local kernel?
*/
#if !defined(_LINUX_CAPABILITY_VERSION)
# error Kernel <linux/capability.h> does not support library
# error file "libcap.h" --> fix and recompile libcap
#elif !defined(_LINUX_CAPABILITY_VERSION_2)
# warning Kernel <linux/capability.h> does not support 64-bit capabilities
# warning and libcap is being built with no support for 64-bit capabilities
# ifndef _LINUX_CAPABILITY_VERSION_1
# define _LINUX_CAPABILITY_VERSION_1 0x19980330
# endif
# _LIBCAP_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
# _LIBCAP_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1
#elif defined(_LINUX_CAPABILITY_VERSION_3)
# if (_LINUX_CAPABILITY_VERSION_3 != 0x20080522)
# error Kernel <linux/capability.h> v3 does not match library
# error file "libcap.h" --> fix and recompile libcap
# else
# define _LIBCAP_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3
# define _LIBCAP_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3
# endif
#elif (_LINUX_CAPABILITY_VERSION_2 != 0x20071026)
# error Kernel <linux/capability.h> does not match library
# error file "libcap.h" --> fix and recompile libcap
#else
# define _LIBCAP_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2
# define _LIBCAP_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_2
#endif
#undef _LINUX_CAPABILITY_VERSION
#undef _LINUX_CAPABILITY_U32S
/*
* This is a pointer to a struct containing three consecutive
* capability sets in the order of the cap_flag_t type: the are
* effective,inheritable and permitted. This is the type that the
* user-space routines think of as 'internal' capabilities - this is
* the type that is passed to the kernel with the system calls related
* to processes.
*/
#if defined(VFS_CAP_REVISION_MASK) && !defined(VFS_CAP_U32)
# define VFS_CAP_U32_1 1
# define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
# define VFS_CAP_U32 VFS_CAP_U32_1
struct _cap_vfs_cap_data {
__le32 magic_etc;
struct {
__le32 permitted;
__le32 inheritable;
} data[VFS_CAP_U32_1];
};
# define vfs_cap_data _cap_vfs_cap_data
#endif
#ifndef CAP_TO_INDEX
# define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */
#endif /* ndef CAP_TO_INDEX */
#ifndef CAP_TO_MASK
# define CAP_TO_MASK(x) (1 << ((x) & 31))
#endif /* ndef CAP_TO_MASK */
#define NUMBER_OF_CAP_SETS 3 /* effective, inheritable, permitted */
#define __CAP_BLKS (_LIBCAP_CAPABILITY_U32S)
#define CAP_SET_SIZE (__CAP_BLKS * sizeof(__u32))
#define CAP_T_MAGIC 0xCA90D0
struct _cap_struct {
__u8 mutex;
struct __user_cap_header_struct head;
union {
struct __user_cap_data_struct set;
__u32 flat[NUMBER_OF_CAP_SETS];
} u[_LIBCAP_CAPABILITY_U32S];
uid_t rootid;
};
/*
* Elementary exclusive locking primatives for situations where
* linking with pthreads needs it, but such linking is not common.
*
* _cap_mu_blocked(x) attempts to lock x but if already locked, returns true
* _cap_mu_lock(x) attempts to lock and waits until the lock is granted
* _cap_mu_unlock(x) unconditionally unlocks the lock
* _cap_mu_unlock_return(x, y) unlock lock x and return value y
*/
#define _cap_mu_blocked(x) \
__atomic_test_and_set((void *)(x), __ATOMIC_SEQ_CST)
#define _cap_mu_lock(x) \
while (_cap_mu_blocked(x)) sched_yield()
#define _cap_mu_unlock(x) \
__atomic_clear((void *) (x), __ATOMIC_SEQ_CST)
#define _cap_mu_unlock_return(x, y) \
do { _cap_mu_unlock(x); return (y); } while (0)
/* the maximum bits supportable */
#define __CAP_MAXBITS (__CAP_BLKS * 32)
/* string magic for cap_free */
#define CAP_S_MAGIC 0xCA95D0
/* iab set magic for cap_free */
#define CAP_IAB_MAGIC 0xCA91AB
/* launcher magic for cap_free */
#define CAP_LAUNCH_MAGIC 0xCA91AC
#define magic_of(x) ((x) ? *(-2 + (const __u32 *) x) : 0)
#define good_cap_t(x) (CAP_T_MAGIC == magic_of(x))
#define good_cap_iab_t(x) (CAP_IAB_MAGIC == magic_of(x))
#define good_cap_launch_t(x) (CAP_LAUNCH_MAGIC == magic_of(x))
/*
* kernel API cap set abstraction
*/
#define raise_cap(x, set) u[(x) >> 5].flat[set] |= (1u << ((x)&31))
#define lower_cap(x, set) u[(x) >> 5].flat[set] &= ~(1u << ((x)&31))
#define isset_cap(y, x, set) ((y)->u[(x) >> 5].flat[set] & (1u << ((x)&31)))
/*
* These match CAP_DIFFERS() expectations
*/
#define LIBCAP_EFF (1 << CAP_EFFECTIVE)
#define LIBCAP_INH (1 << CAP_INHERITABLE)
#define LIBCAP_PER (1 << CAP_PERMITTED)
/*
* library debugging
*/
#ifdef DEBUG
#include <stdio.h>
# define _cap_debug(f, x...) do { \
fprintf(stderr, "%s(%s:%d): ", __FUNCTION__, __FILE__, __LINE__); \
fprintf(stderr, f, ## x); \
fprintf(stderr, "\n"); \
} while (0)
# define _cap_debugcap(s, c, set) do { \
unsigned _cap_index; \
fprintf(stderr, "%s(%s:%d): %s", __FUNCTION__, __FILE__, __LINE__, s); \
for (_cap_index=_LIBCAP_CAPABILITY_U32S; _cap_index-- > 0; ) { \
fprintf(stderr, "%08x", (c).u[_cap_index].flat[set]); \
} \
fprintf(stderr, "\n"); \
} while (0)
#else /* !DEBUG */
# define _cap_debug(f, x...)
# define _cap_debugcap(s, c, set)
#endif /* DEBUG */
extern char *_libcap_strdup(const char *text);
extern void _libcap_initialize(void);
extern int _libcap_overrode_syscalls;
/*
* Note: we hardcode the prototype for the psx_load_syscalls()
* function here so the compiler isn't worried. If we force the build
* to include the psx_syscall.h header, we are close to requiring the
* optional libpsx to be linked.
*/
extern void psx_load_syscalls(
long int (**syscall_fn)(long int, long int, long int, long int),
long int (**syscall6_fn)(long int, long int, long int, long int,
long int, long int, long int));
#define EXECABLE_INITIALIZE _libcap_initialize()
/*
* These are semi-public prototypes, they will only be defined in
* <sys/capability.h> if _POSIX_SOURCE is not #define'd, so we
* place them here too.
*/
extern int capget(cap_user_header_t header, cap_user_data_t data);
extern int capgetp(pid_t pid, cap_t cap_d);
extern int capsetp(pid_t pid, cap_t cap_d);
/* prctl based API for altering character of current process */
#define PR_GET_KEEPCAPS 7
#define PR_SET_KEEPCAPS 8
#define PR_CAPBSET_READ 23
#define PR_CAPBSET_DROP 24
#define PR_GET_SECUREBITS 27
#define PR_SET_SECUREBITS 28
/*
* The library compares sizeof() with integer return values. To avoid
* signed/unsigned comparisons, leading to unfortunate
* misinterpretations of -1, we provide a convenient cast-to-signed-integer
* version of sizeof().
*/
#define ssizeof(x) ((ssize_t) sizeof(x))
/*
* Put this here as a macro so we can unit test it.
*/
#define _binary_search(val, fn, low, high, fallback) do { \
cap_value_t min = low, max = high; \
while (min <= max) { \
cap_value_t mid = (min+max) / 2; \
if (fn(mid) < 0) { \
max = mid - 1; \
} else { \
min = mid + 1; \
} \
} \
val = min ? (min <= high ? min : fallback) : fallback; \
} while(0)
/*
* cap_iab_s holds a collection of inheritable capability bits. The i
* bits are inheritable (these are the same as those in cap_t), the a
* bits are ambient bits (which cannot be a superset of i&p), and nb
* are the bits that will be dropped from the bounding set when
* applied.
*/
struct cap_iab_s {
__u8 mutex;
__u32 i[_LIBCAP_CAPABILITY_U32S];
__u32 a[_LIBCAP_CAPABILITY_U32S];
__u32 nb[_LIBCAP_CAPABILITY_U32S];
};
#define LIBCAP_IAB_I_FLAG (1U << CAP_IAB_INH)
#define LIBCAP_IAB_A_FLAG (1U << CAP_IAB_AMB)
#define LIBCAP_IAB_IA_FLAG (LIBCAP_IAB_I_FLAG | LIBCAP_IAB_A_FLAG)
#define LIBCAP_IAB_NB_FLAG (1U << CAP_IAB_BOUND)
/*
* The following support launching another process without destroying
* the state of the current process. This is especially useful for
* multithreaded applications.
*/
struct cap_launch_s {
__u8 mutex;
/*
* Once forked but before active privilege is changed, this
* function (if non-NULL) is called.
*/
int (*custom_setup_fn)(void *detail);
/*
* user and groups to be used by the forked child.
*/
int change_uids;
uid_t uid;
int change_gids;
gid_t gid;
int ngroups;
const gid_t *groups;
/*
* mode holds the preferred capability mode. Any non-uncertain
* setting here will require an empty ambient set.
*/
int change_mode;
cap_mode_t mode;
/*
* i,a,[n]b caps. These bitmaps hold all of the capability sets that
* cap_launch will affect. nb holds values to be lowered in the bounding
* set.
*/
struct cap_iab_s *iab;
/* chroot holds a preferred chroot for the launched child. */
char *chroot;
/*
* execve style arguments
*/
const char *arg0;
const char *const *argv;
const char *const *envp;
};
#endif /* LIBCAP_H */
|