diff options
Diffstat (limited to 'libcap')
-rw-r--r-- | libcap/.gitignore | 6 | ||||
-rw-r--r-- | libcap/Makefile | 79 | ||||
-rw-r--r-- | libcap/_makenames.c | 61 | ||||
-rw-r--r-- | libcap/cap_alloc.c | 139 | ||||
-rw-r--r-- | libcap/cap_extint.c | 123 | ||||
-rw-r--r-- | libcap/cap_file.c | 321 | ||||
-rw-r--r-- | libcap/cap_flag.c | 150 | ||||
-rw-r--r-- | libcap/cap_proc.c | 126 | ||||
-rw-r--r-- | libcap/cap_text.c | 429 | ||||
-rw-r--r-- | libcap/include/linux/capability.h | 576 | ||||
-rw-r--r-- | libcap/include/linux/prctl.h | 105 | ||||
-rw-r--r-- | libcap/include/linux/securebits.h | 54 | ||||
-rw-r--r-- | libcap/include/sys/capability.h | 129 | ||||
-rw-r--r-- | libcap/include/sys/securebits.h | 22 | ||||
-rw-r--r-- | libcap/libcap.h | 200 |
15 files changed, 2520 insertions, 0 deletions
diff --git a/libcap/.gitignore b/libcap/.gitignore new file mode 100644 index 0000000..34cc5d6 --- /dev/null +++ b/libcap/.gitignore @@ -0,0 +1,6 @@ +cap_names.h +cap_names.list.h +_caps_output.gperf +libcap.a +libcap.so* +_makenames diff --git a/libcap/Makefile b/libcap/Makefile new file mode 100644 index 0000000..4762c60 --- /dev/null +++ b/libcap/Makefile @@ -0,0 +1,79 @@ +# +# defines +# +topdir=$(shell pwd)/.. +include ../Make.Rules +# +# Library version +# +LIBNAME=$(LIBTITLE).so +STALIBNAME=$(LIBTITLE).a +# + +FILES=cap_alloc cap_proc cap_extint cap_flag cap_text + +# make including file support something you can override (no libattr +# no support). +ifeq ($(LIBATTR),yes) +FILES += cap_file +LDFLAGS += -lattr +endif + +INCLS=libcap.h cap_names.h $(INCS) +OBJS=$(addsuffix .o, $(FILES)) +MAJLIBNAME=$(LIBNAME).$(VERSION) +MINLIBNAME=$(MAJLIBNAME).$(MINOR) +GPERF_OUTPUT = _caps_output.gperf + +all: $(MINLIBNAME) $(STALIBNAME) + +ifeq ($(shell gperf --version > /dev/null 2>&1 && echo yes),yes) +USE_GPERF_OUTPUT = $(GPERF_OUTPUT) +INCLUDE_GPERF_OUTPUT = -include $(GPERF_OUTPUT) +endif + +_makenames: _makenames.c cap_names.list.h + $(BUILD_CC) $(BUILD_CFLAGS) $< -o $@ + +cap_names.h: _makenames + ./_makenames > cap_names.h + +$(GPERF_OUTPUT): cap_names.list.h + perl -e 'print "struct __cap_token_s { const char *name; int index; };\n%{\nconst struct __cap_token_s *__cap_lookup_name(const char *, unsigned int);\n%}\n%%\n"; while ($$l = <>) { $$l =~ s/[\{\"]//g; $$l =~ s/\}.*// ; print $$l; }' < $< | gperf --ignore-case --language=ANSI-C --readonly --null-strings --global-table --hash-function-name=__cap_hash_name --lookup-function-name="__cap_lookup_name" -c -t -m20 $(INDENT) > $@ + +cap_names.list.h: Makefile $(KERNEL_HEADERS)/linux/capability.h + @echo "=> making $@ from $(KERNEL_HEADERS)/linux/capability.h" + perl -e 'while ($$l=<>) { if ($$l =~ /^\#define[ \t](CAP[_A-Z]+)[ \t]+([0-9]+)\s+$$/) { $$tok=$$1; $$val=$$2; $$tok =~ tr/A-Z/a-z/; print "{\"$$tok\",$$val},\n"; } }' $(KERNEL_HEADERS)/linux/capability.h | fgrep -v 0x > $@ + +$(STALIBNAME): $(OBJS) + $(AR) rcs $@ $^ + $(RANLIB) $@ + +$(MINLIBNAME): $(OBJS) + $(LD) $(CFLAGS) $(LDFLAGS) -Wl,-soname,$(MAJLIBNAME) -o $@ $^ + ln -sf $(MINLIBNAME) $(MAJLIBNAME) + ln -sf $(MAJLIBNAME) $(LIBNAME) + +%.o: %.c $(INCLS) + $(CC) $(CFLAGS) $(IPATH) -c $< -o $@ + +cap_text.o: cap_text.c $(USE_GPERF_OUTPUT) $(INCLS) + $(CC) $(CFLAGS) $(IPATH) $(INCLUDE_GPERF_OUTPUT) -c $< -o $@ + +install: all + mkdir -p -m 0755 $(INCDIR)/sys + install -m 0644 include/sys/capability.h $(INCDIR)/sys + mkdir -p -m 0755 $(LIBDIR) + install -m 0644 $(STALIBNAME) $(LIBDIR)/$(STALIBNAME) + install -m 0644 $(MINLIBNAME) $(LIBDIR)/$(MINLIBNAME) + ln -sf $(MINLIBNAME) $(LIBDIR)/$(MAJLIBNAME) + ln -sf $(MAJLIBNAME) $(LIBDIR)/$(LIBNAME) +ifeq ($(FAKEROOT),) + -/sbin/ldconfig +endif + +clean: + $(LOCALCLEAN) + rm -f $(OBJS) $(LIBNAME)* $(STALIBNAME) + rm -f cap_names.h cap_names.list.h _makenames $(GPERF_OUTPUT) + cd include/sys && $(LOCALCLEAN) diff --git a/libcap/_makenames.c b/libcap/_makenames.c new file mode 100644 index 0000000..8cc819b --- /dev/null +++ b/libcap/_makenames.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1997-8 Andrew G. Morgan <morgan@kernel.org> + * + * This is a file to make the capability <-> string mappings for + * libcap. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/capability.h> + +/* + * #include 'sed' generated array + */ + +struct { + const char *name; + int index; +} const list[] = { +#include "cap_names.list.h" + {NULL, -1} +}; + +/* this should be more than big enough (factor of three at least) */ +const char *pointers[8*sizeof(struct __user_cap_data_struct)]; + +int main(void) +{ + int i, maxcaps=0; + + for ( i=0; list[i].index >= 0 && list[i].name; ++i ) { + if (maxcaps <= list[i].index) { + maxcaps = list[i].index + 1; + } + pointers[list[i].index] = list[i].name; + } + + printf("/*\n" + " * DO NOT EDIT: this file is generated automatically from\n" + " *\n" + " * <linux/capability.h>\n" + " */\n" + "#define __CAP_BITS %d\n" + "\n" + "#ifdef LIBCAP_PLEASE_INCLUDE_ARRAY\n" + " char const *_cap_names[__CAP_BITS] = {\n", maxcaps); + + for (i=0; i<maxcaps; ++i) { + if (pointers[i]) + printf(" /* %d */\t\"%s\",\n", i, pointers[i]); + else + printf(" /* %d */\tNULL,\t\t/* - presently unused */\n", i); + } + + printf(" };\n" + "#endif /* LIBCAP_PLEASE_INCLUDE_ARRAY */\n" + "\n" + "/* END OF FILE */\n"); + + exit(0); +} diff --git a/libcap/cap_alloc.c b/libcap/cap_alloc.c new file mode 100644 index 0000000..5fa5e93 --- /dev/null +++ b/libcap/cap_alloc.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1997-8 Andrew G Morgan <morgan@kernel.org> + * + * This file deals with allocation and deallocation of internal + * capability sets as specified by POSIX.1e (formerlly, POSIX 6). + */ + +#include "libcap.h" + +/* + * Obtain a blank set of capabilities + */ + +cap_t cap_init(void) +{ + __u32 *raw_data; + cap_t result; + + raw_data = malloc( sizeof(__u32) + sizeof(*result) ); + + if (raw_data == NULL) { + _cap_debug("out of memory"); + errno = ENOMEM; + return NULL; + } + + *raw_data = CAP_T_MAGIC; + result = (cap_t) (raw_data + 1); + memset(result, 0, sizeof(*result)); + + result->head.version = _LIBCAP_CAPABILITY_VERSION; + capget(&result->head, NULL); /* load the kernel-capability version */ + + switch (result->head.version) { +#ifdef _LINUX_CAPABILITY_VERSION_1 + case _LINUX_CAPABILITY_VERSION_1: + break; +#endif +#ifdef _LINUX_CAPABILITY_VERSION_2 + case _LINUX_CAPABILITY_VERSION_2: + break; +#endif +#ifdef _LINUX_CAPABILITY_VERSION_3 + case _LINUX_CAPABILITY_VERSION_3: + break; +#endif + default: /* No idea what to do */ + cap_free(result); + result = NULL; + break; + } + + return result; +} + +/* + * This is an internal library function to duplicate a string and + * tag the result as something cap_free can handle. + */ + +char *_libcap_strdup(const char *old) +{ + __u32 *raw_data; + + if (old == NULL) { + errno = EINVAL; + return NULL; + } + + raw_data = malloc( sizeof(__u32) + strlen(old) + 1 ); + if (raw_data == NULL) { + errno = ENOMEM; + return NULL; + } + + *(raw_data++) = CAP_S_MAGIC; + strcpy((char *) raw_data, old); + + return ((char *) raw_data); +} + +/* + * This function duplicates an internal capability set with + * malloc()'d memory. It is the responsibility of the user to call + * cap_free() to liberate it. + */ + +cap_t cap_dup(cap_t cap_d) +{ + cap_t result; + + if (!good_cap_t(cap_d)) { + _cap_debug("bad argument"); + errno = EINVAL; + return NULL; + } + + result = cap_init(); + if (result == NULL) { + _cap_debug("out of memory"); + return NULL; + } + + memcpy(result, cap_d, sizeof(*cap_d)); + + return result; +} + + +/* + * Scrub and then liberate an internal capability set. + */ + +int cap_free(void *data_p) +{ + if ( !data_p ) + return 0; + + if ( good_cap_t(data_p) ) { + data_p = -1 + (__u32 *) data_p; + memset(data_p, 0, sizeof(__u32) + sizeof(struct _cap_struct)); + free(data_p); + data_p = NULL; + return 0; + } + + if ( good_cap_string(data_p) ) { + int length = strlen(data_p) + sizeof(__u32); + data_p = -1 + (__u32 *) data_p; + memset(data_p, 0, length); + free(data_p); + data_p = NULL; + return 0; + } + + _cap_debug("don't recognize what we're supposed to liberate"); + errno = EINVAL; + return -1; +} diff --git a/libcap/cap_extint.c b/libcap/cap_extint.c new file mode 100644 index 0000000..5a0cc8e --- /dev/null +++ b/libcap/cap_extint.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1997-8 Andrew G Morgan <morgan@kernel.org> + * + * This file deals with exchanging internal and external + * representations of capability sets. + */ + +#include "libcap.h" + +/* + * External representation for capabilities. (exported as a fixed + * length) + */ +#define CAP_EXT_MAGIC "\220\302\001\121" +#define CAP_EXT_MAGIC_SIZE 4 +const static __u8 external_magic[CAP_EXT_MAGIC_SIZE+1] = CAP_EXT_MAGIC; + +struct cap_ext_struct { + __u8 magic[CAP_EXT_MAGIC_SIZE]; + __u8 length_of_capset; + /* + * note, we arrange these so the caps are stacked with byte-size + * resolution + */ + __u8 bytes[CAP_SET_SIZE][NUMBER_OF_CAP_SETS]; +}; + +/* + * return size of external capability set + */ + +ssize_t cap_size(cap_t caps) +{ + return sizeof(struct cap_ext_struct); +} + +/* + * Copy the internal (cap_d) capability set into an external + * representation. The external representation is portable to other + * Linux architectures. + */ + +ssize_t cap_copy_ext(void *cap_ext, cap_t cap_d, ssize_t length) +{ + struct cap_ext_struct *result = (struct cap_ext_struct *) cap_ext; + int i; + + /* valid arguments? */ + if (!good_cap_t(cap_d) || length < sizeof(struct cap_ext_struct) + || cap_ext == NULL) { + errno = EINVAL; + return -1; + } + + /* fill external capability set */ + memcpy(&result->magic, external_magic, CAP_EXT_MAGIC_SIZE); + result->length_of_capset = CAP_SET_SIZE; + + for (i=0; i<NUMBER_OF_CAP_SETS; ++i) { + int j; + for (j=0; j<CAP_SET_SIZE; ) { + __u32 val; + + val = cap_d->u[j/sizeof(__u32)].flat[i]; + + result->bytes[j++][i] = val & 0xFF; + result->bytes[j++][i] = (val >>= 8) & 0xFF; + result->bytes[j++][i] = (val >>= 8) & 0xFF; + result->bytes[j++][i] = (val >> 8) & 0xFF; + } + } + + /* All done: return length of external representation */ + return (sizeof(struct cap_ext_struct)); +} + +/* + * Import an external representation to produce an internal rep. + * the internal rep should be liberated with cap_free(). + */ + +cap_t cap_copy_int(const void *cap_ext) +{ + const struct cap_ext_struct *export = + (const struct cap_ext_struct *) cap_ext; + cap_t cap_d; + int set, blen; + + /* Does the external representation make sense? */ + if ((export == NULL) + || memcmp(export->magic, external_magic, CAP_EXT_MAGIC_SIZE)) { + errno = EINVAL; + return NULL; + } + + /* Obtain a new internal capability set */ + if (!(cap_d = cap_init())) + return NULL; + + blen = export->length_of_capset; + for (set=0; set<NUMBER_OF_CAP_SETS; ++set) { + int blk; + int bno = 0; + for (blk=0; blk<(CAP_SET_SIZE/sizeof(__u32)); ++blk) { + __u32 val = 0; + + if (bno != blen) + val = export->bytes[bno++][set]; + if (bno != blen) + val |= export->bytes[bno++][set] << 8; + if (bno != blen) + val |= export->bytes[bno++][set] << 16; + if (bno != blen) + val |= export->bytes[bno++][set] << 24; + + cap_d->u[blk].flat[set] = val; + } + } + + /* all done */ + return cap_d; +} + diff --git a/libcap/cap_file.c b/libcap/cap_file.c new file mode 100644 index 0000000..634e601 --- /dev/null +++ b/libcap/cap_file.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 1997,2007 Andrew G Morgan <morgan@kernel.org> + * + * This file deals with setting capabilities on files. + */ + +#include <sys/types.h> +#include <sys/xattr.h> +#include <byteswap.h> +#include <sys/stat.h> +#include <unistd.h> + +#define XATTR_SECURITY_PREFIX "security." + +#include "libcap.h" + +#ifdef VFS_CAP_U32 + +#if VFS_CAP_U32 != __CAP_BLKS +# error VFS representation of capabilities is not the same size as kernel +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +#define FIXUP_32BITS(x) bswap_32(x) +#else +#define FIXUP_32BITS(x) (x) +#endif + +static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result, + int bytes) +{ + __u32 magic_etc; + unsigned tocopy, i; + + magic_etc = FIXUP_32BITS(rawvfscap->magic_etc); + switch (magic_etc & VFS_CAP_REVISION_MASK) { +#ifdef VFS_CAP_REVISION_1 + case VFS_CAP_REVISION_1: + tocopy = VFS_CAP_U32_1; + bytes -= XATTR_CAPS_SZ_1; + break; +#endif + +#ifdef VFS_CAP_REVISION_2 + case VFS_CAP_REVISION_2: + tocopy = VFS_CAP_U32_2; + bytes -= XATTR_CAPS_SZ_2; + break; +#endif + + default: + cap_free(result); + result = NULL; + return result; + } + + /* + * Verify that we loaded exactly the right number of bytes + */ + if (bytes != 0) { + cap_free(result); + result = NULL; + return result; + } + + for (i=0; i < tocopy; i++) { + result->u[i].flat[CAP_INHERITABLE] + = FIXUP_32BITS(rawvfscap->data[i].inheritable); + result->u[i].flat[CAP_PERMITTED] + = FIXUP_32BITS(rawvfscap->data[i].permitted); + if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) { + result->u[i].flat[CAP_EFFECTIVE] + = result->u[i].flat[CAP_INHERITABLE] + | result->u[i].flat[CAP_PERMITTED]; + } + } + while (i < __CAP_BLKS) { + result->u[i].flat[CAP_INHERITABLE] + = result->u[i].flat[CAP_PERMITTED] + = result->u[i].flat[CAP_EFFECTIVE] = 0; + i++; + } + + return result; +} + +static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d, + int *bytes_p) +{ + __u32 eff_not_zero, magic; + unsigned tocopy, i; + + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + switch (cap_d->head.version) { +#ifdef _LINUX_CAPABILITY_VERSION_1 + case _LINUX_CAPABILITY_VERSION_1: + magic = VFS_CAP_REVISION_1; + tocopy = VFS_CAP_U32_1; + *bytes_p = XATTR_CAPS_SZ_1; + break; +#endif + +#ifdef _LINUX_CAPABILITY_VERSION_2 + case _LINUX_CAPABILITY_VERSION_2: + magic = VFS_CAP_REVISION_2; + tocopy = VFS_CAP_U32_2; + *bytes_p = XATTR_CAPS_SZ_2; + break; +#endif + +#ifdef _LINUX_CAPABILITY_VERSION_3 + case _LINUX_CAPABILITY_VERSION_3: + magic = VFS_CAP_REVISION_2; + tocopy = VFS_CAP_U32_2; + *bytes_p = XATTR_CAPS_SZ_2; + break; +#endif + + default: + errno = EINVAL; + return -1; + } + + _cap_debug("setting named file capabilities"); + + for (eff_not_zero = 0, i = 0; i < tocopy; i++) { + eff_not_zero |= cap_d->u[i].flat[CAP_EFFECTIVE]; + } + while (i < __CAP_BLKS) { + if ((cap_d->u[i].flat[CAP_EFFECTIVE] + || cap_d->u[i].flat[CAP_INHERITABLE] + || cap_d->u[i].flat[CAP_PERMITTED])) { + /* + * System does not support these capabilities + */ + errno = EINVAL; + return -1; + } + i++; + } + + for (i=0; i < tocopy; i++) { + rawvfscap->data[i].permitted + = FIXUP_32BITS(cap_d->u[i].flat[CAP_PERMITTED]); + rawvfscap->data[i].inheritable + = FIXUP_32BITS(cap_d->u[i].flat[CAP_INHERITABLE]); + + if (eff_not_zero + && ((~(cap_d->u[i].flat[CAP_EFFECTIVE])) + & (cap_d->u[i].flat[CAP_PERMITTED] + | cap_d->u[i].flat[CAP_INHERITABLE]))) { + errno = EINVAL; + return -1; + } + } + + if (eff_not_zero == 0) { + rawvfscap->magic_etc = FIXUP_32BITS(magic); + } else { + rawvfscap->magic_etc = FIXUP_32BITS(magic|VFS_CAP_FLAGS_EFFECTIVE); + } + + return 0; /* success */ +} + +/* + * Get the capabilities of an open file, as specified by its file + * descriptor. + */ + +cap_t cap_get_fd(int fildes) +{ + cap_t result; + + /* allocate a new capability set */ + result = cap_init(); + if (result) { + struct vfs_cap_data rawvfscap; + int sizeofcaps; + + _cap_debug("getting fildes capabilities"); + + /* fill the capability sets via a system call */ + sizeofcaps = fgetxattr(fildes, XATTR_NAME_CAPS, + &rawvfscap, sizeof(rawvfscap)); + if (sizeofcaps < sizeof(rawvfscap.magic_etc)) { + cap_free(result); + result = NULL; + } else { + result = _fcaps_load(&rawvfscap, result, sizeofcaps); + } + } + + return result; +} + +/* + * Get the capabilities from a named file. + */ + +cap_t cap_get_file(const char *filename) +{ + cap_t result; + + /* allocate a new capability set */ + result = cap_init(); + if (result) { + struct vfs_cap_data rawvfscap; + int sizeofcaps; + + _cap_debug("getting filename capabilities"); + + /* fill the capability sets via a system call */ + sizeofcaps = getxattr(filename, XATTR_NAME_CAPS, + &rawvfscap, sizeof(rawvfscap)); + if (sizeofcaps < sizeof(rawvfscap.magic_etc)) { + cap_free(result); + result = NULL; + } else { + result = _fcaps_load(&rawvfscap, result, sizeofcaps); + } + } + + return result; +} + +/* + * Set the capabilities of an open file, as specified by its file + * descriptor. + */ + +int cap_set_fd(int fildes, cap_t cap_d) +{ + struct vfs_cap_data rawvfscap; + int sizeofcaps; + struct stat buf; + + if (fstat(fildes, &buf) != 0) { + _cap_debug("unable to stat file descriptor %d", fildes); + return -1; + } + if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) { + _cap_debug("file descriptor %d for non-regular file", fildes); + errno = EINVAL; + return -1; + } + + if (cap_d == NULL) { + _cap_debug("deleting fildes capabilities"); + return fremovexattr(fildes, XATTR_NAME_CAPS); + } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) { + return -1; + } + + _cap_debug("setting fildes capabilities"); + + return fsetxattr(fildes, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0); +} + +/* + * Set the capabilities of a named file. + */ + +int cap_set_file(const char *filename, cap_t cap_d) +{ + struct vfs_cap_data rawvfscap; + int sizeofcaps; + struct stat buf; + + if (lstat(filename, &buf) != 0) { + _cap_debug("unable to stat file [%s]", filename); + return -1; + } + if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) { + _cap_debug("file [%s] is not a regular file", filename); + errno = EINVAL; + return -1; + } + + if (cap_d == NULL) { + _cap_debug("removing filename capabilities"); + return removexattr(filename, XATTR_NAME_CAPS); + } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) { + return -1; + } + + _cap_debug("setting filename capabilities"); + return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0); +} + +#else /* ie. ndef VFS_CAP_U32 */ + +cap_t cap_get_fd(int fildes) +{ + errno = EINVAL; + return NULL; +} + +cap_t cap_get_file(const char *filename) +{ + errno = EINVAL; + return NULL; +} + +int cap_set_fd(int fildes, cap_t cap_d) +{ + errno = EINVAL; + return -1; +} + +int cap_set_file(const char *filename, cap_t cap_d) +{ + errno = EINVAL; + return -1; +} + +#endif /* def VFS_CAP_U32 */ diff --git a/libcap/cap_flag.c b/libcap/cap_flag.c new file mode 100644 index 0000000..52ec3b3 --- /dev/null +++ b/libcap/cap_flag.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1997-8,2008 Andrew G. Morgan <morgan@kernel.org> + * + * This file deals with flipping of capabilities on internal + * capability sets as specified by POSIX.1e (formerlly, POSIX 6). + */ + +#include "libcap.h" + +/* + * Return the state of a specified capability flag. The state is + * returned as the contents of *raised. The capability is from one of + * the sets stored in cap_d as specified by set and value + */ + +int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set, + cap_flag_value_t *raised) +{ + /* + * Do we have a set and a place to store its value? + * Is it a known capability? + */ + + if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_BITS + && set >= 0 && set < NUMBER_OF_CAP_SETS) { + *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR; + return 0; + } else { + _cap_debug("invalid arguments"); + errno = EINVAL; + return -1; + } +} + +/* + * raise/lower a selection of capabilities + */ + +int cap_set_flag(cap_t cap_d, cap_flag_t set, + int no_values, const cap_value_t *array_values, + cap_flag_value_t raise) +{ + /* + * Do we have a set and a place to store its value? + * Is it a known capability? + */ + + if (good_cap_t(cap_d) && no_values > 0 && no_values <= __CAP_BITS + && (set >= 0) && (set < NUMBER_OF_CAP_SETS) + && (raise == CAP_SET || raise == CAP_CLEAR) ) { + int i; + for (i=0; i<no_values; ++i) { + if (array_values[i] < 0 || array_values[i] >= __CAP_BITS) { + _cap_debug("weird capability (%d) - skipped", array_values[i]); + } else { + int value = array_values[i]; + + if (raise == CAP_SET) { + cap_d->raise_cap(value,set); + } else { + cap_d->lower_cap(value,set); + } + } + } + return 0; + + } else { + + _cap_debug("invalid arguments"); + errno = EINVAL; + return -1; + + } +} + +/* + * Reset the capability to be empty (nothing raised) + */ + +int cap_clear(cap_t cap_d) +{ + if (good_cap_t(cap_d)) { + + memset(&(cap_d->u), 0, sizeof(cap_d->u)); + return 0; + + } else { + + _cap_debug("invalid pointer"); + errno = EINVAL; + return -1; + + } +} + +/* + * Reset the all of the capability bits for one of the flag sets + */ + +int cap_clear_flag(cap_t cap_d, cap_flag_t flag) +{ + switch (flag) { + case CAP_EFFECTIVE: + case CAP_PERMITTED: + case CAP_INHERITABLE: + if (good_cap_t(cap_d)) { + unsigned i; + + for (i=0; i<_LIBCAP_CAPABILITY_U32S; i++) { + cap_d->u[i].flat[flag] = 0; + } + return 0; + } + /* + * fall through + */ + + default: + _cap_debug("invalid pointer"); + errno = EINVAL; + return -1; + } +} + +/* + * Compare two capability sets + */ + +int cap_compare(cap_t a, cap_t b) +{ + unsigned i; + int result; + + if (!(good_cap_t(a) && good_cap_t(b))) { + _cap_debug("invalid arguments"); + errno = EINVAL; + return -1; + } + + for (i=0, result=0; i<_LIBCAP_CAPABILITY_U32S; i++) { + result |= + ((a->u[i].flat[CAP_EFFECTIVE] != b->u[i].flat[CAP_EFFECTIVE]) + ? LIBCAP_EFF : 0) + | ((a->u[i].flat[CAP_INHERITABLE] != b->u[i].flat[CAP_INHERITABLE]) + ? LIBCAP_INH : 0) + | ((a->u[i].flat[CAP_PERMITTED] != b->u[i].flat[CAP_PERMITTED]) + ? LIBCAP_PER : 0); + } + return result; +} diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c new file mode 100644 index 0000000..8ecb57a --- /dev/null +++ b/libcap/cap_proc.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1997-8,2007,2011 Andrew G Morgan <morgan@kernel.org> + * + * This file deals with getting and setting capabilities on processes. + */ + +#include <sys/prctl.h> + +#include "libcap.h" + +cap_t cap_get_proc(void) +{ + cap_t result; + + /* allocate a new capability set */ + result = cap_init(); + if (result) { + _cap_debug("getting current process' capabilities"); + + /* fill the capability sets via a system call */ + if (capget(&result->head, &result->u[0].set)) { + cap_free(result); + result = NULL; + } + } + + return result; +} + +int cap_set_proc(cap_t cap_d) +{ + int retval; + + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting process capabilities"); + retval = capset(&cap_d->head, &cap_d->u[0].set); + + return retval; +} + +/* the following two functions are not required by POSIX */ + +/* read the caps on a specific process */ + +int capgetp(pid_t pid, cap_t cap_d) +{ + int error; + + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("getting process capabilities for proc %d", pid); + + cap_d->head.pid = pid; + error = capget(&cap_d->head, &cap_d->u[0].set); + cap_d->head.pid = 0; + + return error; +} + +/* allocate space for and return capabilities of target process */ + +cap_t cap_get_pid(pid_t pid) +{ + cap_t result; + + result = cap_init(); + if (result) { + if (capgetp(pid, result) != 0) { + int my_errno; + + my_errno = errno; + cap_free(result); + errno = my_errno; + result = NULL; + } + } + + return result; +} + +/* set the caps on a specific process/pg etc.. */ + +int capsetp(pid_t pid, cap_t cap_d) +{ + int error; + + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting process capabilities for proc %d", pid); + cap_d->head.pid = pid; + error = capset(&cap_d->head, &cap_d->u[0].set); + cap_d->head.version = _LIBCAP_CAPABILITY_VERSION; + cap_d->head.pid = 0; + + return error; +} + +/* get a capability from the bounding set */ + +int cap_get_bound(cap_value_t cap) +{ + int result; + + result = prctl(PR_CAPBSET_READ, cap); + return result; +} + +/* drop a capability from the bounding set */ + +int cap_drop_bound(cap_value_t cap) +{ + int result; + + result = prctl(PR_CAPBSET_DROP, cap); + return result; +} diff --git a/libcap/cap_text.c b/libcap/cap_text.c new file mode 100644 index 0000000..42fb685 --- /dev/null +++ b/libcap/cap_text.c @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1997-8,2007-8 Andrew G Morgan <morgan@kernel.org> + * Copyright (c) 1997 Andrew Main <zefram@dcs.warwick.ac.uk> + * + * This file deals with exchanging internal and textual + * representations of capability sets. + */ + +#define _GNU_SOURCE +#include <stdio.h> + +#define LIBCAP_PLEASE_INCLUDE_ARRAY +#include "libcap.h" + +#include <ctype.h> +#include <limits.h> + +/* Maximum output text length (16 per cap) */ +#define CAP_TEXT_SIZE (16*__CAP_MAXBITS) + +/* + * Parse a textual representation of capabilities, returning an internal + * representation. + */ + +#define raise_cap_mask(flat, c) (flat)[CAP_TO_INDEX(c)] |= CAP_TO_MASK(c) + +static void setbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks) +{ + int n; + for (n = blks; n--; ) { + a->u[n].flat[set] |= b[n]; + } +} + +static void clrbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks) +{ + int n; + for (n = blks; n--; ) + a->u[n].flat[set] &= ~b[n]; +} + +static char const *namcmp(char const *str, char const *nam) +{ + while (*nam && tolower((unsigned char)*str) == *nam) { + str++; + nam++; + } + if (*nam || isalnum((unsigned char)*str) || *str == '_') + return NULL; + return str; +} + +static void forceall(__u32 *flat, __u32 value, unsigned blks) +{ + unsigned n; + + for (n = blks; n--; flat[n] = value); + + return; +} + +static int lookupname(char const **strp) +{ + union { + char const *constp; + char *p; + } str; + + str.constp = *strp; + if (isdigit(*str.constp)) { + unsigned long n = strtoul(str.constp, &str.p, 0); + if (n >= __CAP_MAXBITS) + return -1; + *strp = str.constp; + return n; + } else { + int c; + unsigned len; + + for (len=0; (c = str.constp[len]); ++len) { + if (!(isalpha(c) || (c == '_'))) { + break; + } + } + +#ifdef GPERF_DOWNCASE + const struct __cap_token_s *token_info; + + token_info = __cap_lookup_name(str.constp, len); + if (token_info != NULL) { + *strp = str.constp + len; + return token_info->index; + } +#else /* ie., ndef GPERF_DOWNCASE */ + char const *s; + unsigned n; + + for (n = __CAP_BITS; n--; ) + if (_cap_names[n] && (s = namcmp(str.constp, _cap_names[n]))) { + *strp = s; + return n; + } +#endif /* def GPERF_DOWNCASE */ + + return -1; /* No definition available */ + } +} + +cap_t cap_from_text(const char *str) +{ + cap_t res; + int n; + unsigned cap_blks; + + if (str == NULL) { + _cap_debug("bad argument"); + errno = EINVAL; + return NULL; + } + + if (!(res = cap_init())) + return NULL; + + switch (res->head.version) { + case _LINUX_CAPABILITY_VERSION_1: + cap_blks = _LINUX_CAPABILITY_U32S_1; + break; + case _LINUX_CAPABILITY_VERSION_2: + cap_blks = _LINUX_CAPABILITY_U32S_2; + break; + case _LINUX_CAPABILITY_VERSION_3: + cap_blks = _LINUX_CAPABILITY_U32S_3; + break; + default: + errno = EINVAL; + return NULL; + } + + _cap_debug("%s", str); + + for (;;) { + __u32 list[__CAP_BLKS]; + char op; + int flags = 0, listed=0; + + forceall(list, 0, __CAP_BLKS); + + /* skip leading spaces */ + while (isspace((unsigned char)*str)) + str++; + if (!*str) { + _cap_debugcap("e = ", *res, CAP_EFFECTIVE); + _cap_debugcap("i = ", *res, CAP_INHERITABLE); + _cap_debugcap("p = ", *res, CAP_PERMITTED); + + return res; + } + + /* identify caps specified by this clause */ + if (isalnum((unsigned char)*str) || *str == '_') { + for (;;) { + if (namcmp(str, "all")) { + str += 3; + forceall(list, ~0, cap_blks); + } else { + n = lookupname(&str); + if (n == -1) + goto bad; + raise_cap_mask(list, n); + } + if (*str != ',') + break; + if (!isalnum((unsigned char)*++str) && *str != '_') + goto bad; + } + listed = 1; + } else if (*str == '+' || *str == '-') { + goto bad; /* require a list of capabilities */ + } else { + forceall(list, ~0, cap_blks); + } + + /* identify first operation on list of capabilities */ + op = *str++; + if (op == '=' && (*str == '+' || *str == '-')) { + if (!listed) + goto bad; + op = (*str++ == '+' ? 'P':'M'); /* skip '=' and take next op */ + } else if (op != '+' && op != '-' && op != '=') + goto bad; + + /* cycle through list of actions */ + do { + _cap_debug("next char = `%c'", *str); + if (*str && !isspace(*str)) { + switch (*str++) { /* Effective, Inheritable, Permitted */ + case 'e': + flags |= LIBCAP_EFF; + break; + case 'i': + flags |= LIBCAP_INH; + break; + case 'p': + flags |= LIBCAP_PER; + break; + default: + goto bad; + } + } else if (op != '=') { + _cap_debug("only '=' can be followed by space"); + goto bad; + } + + _cap_debug("how to read?"); + switch (op) { /* how do we interpret the caps? */ + case '=': + case 'P': /* =+ */ + case 'M': /* =- */ + clrbits(res, list, CAP_EFFECTIVE, cap_blks); + clrbits(res, list, CAP_PERMITTED, cap_blks); + clrbits(res, list, CAP_INHERITABLE, cap_blks); + if (op == 'M') + goto minus; + /* fall through */ + case '+': + if (flags & LIBCAP_EFF) + setbits(res, list, CAP_EFFECTIVE, cap_blks); + if (flags & LIBCAP_PER) + setbits(res, list, CAP_PERMITTED, cap_blks); + if (flags & LIBCAP_INH) + setbits(res, list, CAP_INHERITABLE, cap_blks); + break; + case '-': + minus: + if (flags & LIBCAP_EFF) + clrbits(res, list, CAP_EFFECTIVE, cap_blks); + if (flags & LIBCAP_PER) + clrbits(res, list, CAP_PERMITTED, cap_blks); + if (flags & LIBCAP_INH) + clrbits(res, list, CAP_INHERITABLE, cap_blks); + break; + } + + /* new directive? */ + if (*str == '+' || *str == '-') { + if (!listed) { + _cap_debug("for + & - must list capabilities"); + goto bad; + } + flags = 0; /* reset the flags */ + op = *str++; + if (!isalpha(*str)) + goto bad; + } + } while (*str && !isspace(*str)); + _cap_debug("next clause"); + } + +bad: + cap_free(res); + res = NULL; + errno = EINVAL; + return res; +} + +/* + * lookup a capability name and return its numerical value + */ +int cap_from_name(const char *name, cap_value_t *value_p) +{ + int n; + + if (((n = lookupname(&name)) >= 0) && (value_p != NULL)) { + *value_p = (unsigned) n; + } + return -(n < 0); +} + +/* + * Convert a single capability index number into a string representation + */ +char *cap_to_name(cap_value_t cap) +{ + if ((cap < 0) || (cap >= __CAP_BITS)) { +#if UINT_MAX != 4294967295U +# error Recompile with correctly sized numeric array +#endif + char *tmp, *result; + + asprintf(&tmp, "%u", cap); + result = _libcap_strdup(tmp); + free(tmp); + + return result; + } else { + return _libcap_strdup(_cap_names[cap]); + } +} + +/* + * Convert an internal representation to a textual one. The textual + * representation is stored in static memory. It will be overwritten + * on the next occasion that this function is called. + */ + +static int getstateflags(cap_t caps, int capno) +{ + int f = 0; + + if (isset_cap(caps, capno, CAP_EFFECTIVE)) { + f |= LIBCAP_EFF; + } + if (isset_cap(caps, capno, CAP_PERMITTED)) { + f |= LIBCAP_PER; + } + if (isset_cap(caps, capno, CAP_INHERITABLE)) { + f |= LIBCAP_INH; + } + + return f; +} + +#define CAP_TEXT_BUFFER_ZONE 100 + +char *cap_to_text(cap_t caps, ssize_t *length_p) +{ + char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE]; + char *p; + int histo[8]; + int m, t; + unsigned n; + unsigned cap_maxbits, cap_blks; + + /* Check arguments */ + if (!good_cap_t(caps)) { + errno = EINVAL; + return NULL; + } + + switch (caps->head.version) { + case _LINUX_CAPABILITY_VERSION_1: + cap_blks = _LINUX_CAPABILITY_U32S_1; + break; + case _LINUX_CAPABILITY_VERSION_2: + cap_blks = _LINUX_CAPABILITY_U32S_2; + break; + case _LINUX_CAPABILITY_VERSION_3: + cap_blks = _LINUX_CAPABILITY_U32S_3; + break; + default: + errno = EINVAL; + return NULL; + } + + cap_maxbits = 32 * cap_blks; + + _cap_debugcap("e = ", *caps, CAP_EFFECTIVE); + _cap_debugcap("i = ", *caps, CAP_INHERITABLE); + _cap_debugcap("p = ", *caps, CAP_PERMITTED); + + memset(histo, 0, sizeof(histo)); + + /* default prevailing state to the upper - unnamed bits */ + for (n = cap_maxbits-1; n > __CAP_BITS; n--) + histo[getstateflags(caps, n)]++; + + /* find which combination of capability sets shares the most bits + we bias to preferring non-set (m=0) with the >= 0 test. Failing + to do this causes strange things to happen with older systems + that don't know about bits 32+. */ + for (m=t=7; t--; ) + if (histo[t] >= histo[m]) + m = t; + + /* capture remaining bits - selecting m from only the unnamed bits, + we maximize the likelihood that we won't see numeric capability + values in the text output. */ + while (n--) + histo[getstateflags(caps, n)]++; + + /* blank is not a valid capability set */ + p = sprintf(buf, "=%s%s%s", + (m & LIBCAP_EFF) ? "e" : "", + (m & LIBCAP_INH) ? "i" : "", + (m & LIBCAP_PER) ? "p" : "" ) + buf; + + for (t = 8; t--; ) + if (t != m && histo[t]) { + *p++ = ' '; + for (n = 0; n < cap_maxbits; n++) + if (getstateflags(caps, n) == t) { + char *this_cap_name; + + this_cap_name = cap_to_name(n); + if ((strlen(this_cap_name) + (p - buf)) > CAP_TEXT_SIZE) { + cap_free(this_cap_name); + errno = ERANGE; + return NULL; + } + p += sprintf(p, "%s,", this_cap_name); + cap_free(this_cap_name); + } + p--; + n = t & ~m; + if (n) + p += sprintf(p, "+%s%s%s", + (n & LIBCAP_EFF) ? "e" : "", + (n & LIBCAP_INH) ? "i" : "", + (n & LIBCAP_PER) ? "p" : ""); + n = ~t & m; + if (n) + p += sprintf(p, "-%s%s%s", + (n & LIBCAP_EFF) ? "e" : "", + (n & LIBCAP_INH) ? "i" : "", + (n & LIBCAP_PER) ? "p" : ""); + if (p - buf > CAP_TEXT_SIZE) { + errno = ERANGE; + return NULL; + } + } + + _cap_debug("%s", buf); + if (length_p) { + *length_p = p - buf; + } + + return (_libcap_strdup(buf)); +} diff --git a/libcap/include/linux/capability.h b/libcap/include/linux/capability.h new file mode 100644 index 0000000..4924f2a --- /dev/null +++ b/libcap/include/linux/capability.h @@ -0,0 +1,576 @@ +/* + * This is <linux/capability.h> + * + * Andrew G. Morgan <morgan@kernel.org> + * Alexander Kjeldaas <astor@guardian.no> + * with help from Aleph1, Roland Buresund and Andrew Main. + * + * See here for the libcap library ("POSIX draft" compliance): + * + * ftp://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/ + */ + +#ifndef _LINUX_CAPABILITY_H +#define _LINUX_CAPABILITY_H + +#include <linux/types.h> + +struct task_struct; + +/* User-level do most of the mapping between kernel and user + capabilities based on the version tag given by the kernel. The + kernel might be somewhat backwards compatible, but don't bet on + it. */ + +/* Note, cap_t, is defined by POSIX (draft) to be an "opaque" pointer to + a set of three capability sets. The transposition of 3*the + following structure to such a composite is better handled in a user + library since the draft standard requires the use of malloc/free + etc.. */ + +#define _LINUX_CAPABILITY_VERSION_1 0x19980330 +#define _LINUX_CAPABILITY_U32S_1 1 + +#define _LINUX_CAPABILITY_VERSION_2 0x20071026 /* deprecated - use v3 */ +#define _LINUX_CAPABILITY_U32S_2 2 + +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 +#define _LINUX_CAPABILITY_U32S_3 2 + +typedef struct __user_cap_header_struct { + __u32 version; + int pid; +} __user *cap_user_header_t; + +typedef struct __user_cap_data_struct { + __u32 effective; + __u32 permitted; + __u32 inheritable; +} __user *cap_user_data_t; + + +#define XATTR_CAPS_SUFFIX "capability" +#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX + +#define VFS_CAP_REVISION_MASK 0xFF000000 +#define VFS_CAP_REVISION_SHIFT 24 +#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK +#define VFS_CAP_FLAGS_EFFECTIVE 0x000001 + +#define VFS_CAP_REVISION_1 0x01000000 +#define VFS_CAP_U32_1 1 +#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1)) + +#define VFS_CAP_REVISION_2 0x02000000 +#define VFS_CAP_U32_2 2 +#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2)) + +#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2 +#define VFS_CAP_U32 VFS_CAP_U32_2 +#define VFS_CAP_REVISION VFS_CAP_REVISION_2 + +struct vfs_cap_data { + __le32 magic_etc; /* Little endian */ + struct { + __le32 permitted; /* Little endian */ + __le32 inheritable; /* Little endian */ + } data[VFS_CAP_U32]; +}; + +#ifndef __KERNEL__ + +/* + * Backwardly compatible definition for source code - trapped in a + * 32-bit world. If you find you need this, please consider using + * libcap to untrap yourself... + */ +#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1 +#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1 + +#else + +#define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 +#define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3 + +extern int file_caps_enabled; + +typedef struct kernel_cap_struct { + __u32 cap[_KERNEL_CAPABILITY_U32S]; +} kernel_cap_t; + +/* exact same as vfs_cap_data but in cpu endian and always filled completely */ +struct cpu_vfs_cap_data { + __u32 magic_etc; + kernel_cap_t permitted; + kernel_cap_t inheritable; +}; + +#define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct)) +#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t)) + +#endif + + +/** + ** POSIX-draft defined capabilities. + **/ + +/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this + overrides the restriction of changing file ownership and group + ownership. */ + +#define CAP_CHOWN 0 + +/* Override all DAC access, including ACL execute access if + [_POSIX_ACL] is defined. Excluding DAC access covered by + CAP_LINUX_IMMUTABLE. */ + +#define CAP_DAC_OVERRIDE 1 + +/* Overrides all DAC restrictions regarding read and search on files + and directories, including ACL restrictions if [_POSIX_ACL] is + defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */ + +#define CAP_DAC_READ_SEARCH 2 + +/* Overrides all restrictions about allowed operations on files, where + file owner ID must be equal to the user ID, except where CAP_FSETID + is applicable. It doesn't override MAC and DAC restrictions. */ + +#define CAP_FOWNER 3 + +/* Overrides the following restrictions that the effective user ID + shall match the file owner ID when setting the S_ISUID and S_ISGID + bits on that file; that the effective group ID (or one of the + supplementary group IDs) shall match the file owner ID when setting + the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are + cleared on successful return from chown(2) (not implemented). */ + +#define CAP_FSETID 4 + +/* Overrides the restriction that the real or effective user ID of a + process sending a signal must match the real or effective user ID + of the process receiving the signal. */ + +#define CAP_KILL 5 + +/* Allows setgid(2) manipulation */ +/* Allows setgroups(2) */ +/* Allows forged gids on socket credentials passing. */ + +#define CAP_SETGID 6 + +/* Allows set*uid(2) manipulation (including fsuid). */ +/* Allows forged pids on socket credentials passing. */ + +#define CAP_SETUID 7 + + +/** + ** Linux-specific capabilities + **/ + +/* Without VFS support for capabilities: + * Transfer any capability in your permitted set to any pid, + * remove any capability in your permitted set from any pid + * With VFS support for capabilities (neither of above, but) + * Add any capability from current's capability bounding set + * to the current process' inheritable set + * Allow taking bits out of capability bounding set + * Allow modification of the securebits for a process + */ + +#define CAP_SETPCAP 8 + +/* Allow modification of S_IMMUTABLE and S_APPEND file attributes */ + +#define CAP_LINUX_IMMUTABLE 9 + +/* Allows binding to TCP/UDP sockets below 1024 */ +/* Allows binding to ATM VCIs below 32 */ + +#define CAP_NET_BIND_SERVICE 10 + +/* Allow broadcasting, listen to multicast */ + +#define CAP_NET_BROADCAST 11 + +/* Allow interface configuration */ +/* Allow administration of IP firewall, masquerading and accounting */ +/* Allow setting debug option on sockets */ +/* Allow modification of routing tables */ +/* Allow setting arbitrary process / process group ownership on + sockets */ +/* Allow binding to any address for transparent proxying */ +/* Allow setting TOS (type of service) */ +/* Allow setting promiscuous mode */ +/* Allow clearing driver statistics */ +/* Allow multicasting */ +/* Allow read/write of device-specific registers */ +/* Allow activation of ATM control sockets */ + +#define CAP_NET_ADMIN 12 + +/* Allow use of RAW sockets */ +/* Allow use of PACKET sockets */ + +#define CAP_NET_RAW 13 + +/* Allow locking of shared memory segments */ +/* Allow mlock and mlockall (which doesn't really have anything to do + with IPC) */ + +#define CAP_IPC_LOCK 14 + +/* Override IPC ownership checks */ + +#define CAP_IPC_OWNER 15 + +/* Insert and remove kernel modules - modify kernel without limit */ +#define CAP_SYS_MODULE 16 + +/* Allow ioperm/iopl access */ +/* Allow sending USB messages to any device via /proc/bus/usb */ + +#define CAP_SYS_RAWIO 17 + +/* Allow use of chroot() */ + +#define CAP_SYS_CHROOT 18 + +/* Allow ptrace() of any process */ + +#define CAP_SYS_PTRACE 19 + +/* Allow configuration of process accounting */ + +#define CAP_SYS_PACCT 20 + +/* Allow configuration of the secure attention key */ +/* Allow administration of the random device */ +/* Allow examination and configuration of disk quotas */ +/* Allow configuring the kernel's syslog (printk behaviour) */ +/* Allow setting the domainname */ +/* Allow setting the hostname */ +/* Allow calling bdflush() */ +/* Allow mount() and umount(), setting up new smb connection */ +/* Allow some autofs root ioctls */ +/* Allow nfsservctl */ +/* Allow VM86_REQUEST_IRQ */ +/* Allow to read/write pci config on alpha */ +/* Allow irix_prctl on mips (setstacksize) */ +/* Allow flushing all cache on m68k (sys_cacheflush) */ +/* Allow removing semaphores */ +/* Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores + and shared memory */ +/* Allow locking/unlocking of shared memory segment */ +/* Allow turning swap on/off */ +/* Allow forged pids on socket credentials passing */ +/* Allow setting readahead and flushing buffers on block devices */ +/* Allow setting geometry in floppy driver */ +/* Allow turning DMA on/off in xd driver */ +/* Allow administration of md devices (mostly the above, but some + extra ioctls) */ +/* Allow tuning the ide driver */ +/* Allow access to the nvram device */ +/* Allow administration of apm_bios, serial and bttv (TV) device */ +/* Allow manufacturer commands in isdn CAPI support driver */ +/* Allow reading non-standardized portions of pci configuration space */ +/* Allow DDI debug ioctl on sbpcd driver */ +/* Allow setting up serial ports */ +/* Allow sending raw qic-117 commands */ +/* Allow enabling/disabling tagged queuing on SCSI controllers and sending + arbitrary SCSI commands */ +/* Allow setting encryption key on loopback filesystem */ +/* Allow setting zone reclaim policy */ + +#define CAP_SYS_ADMIN 21 + +/* Allow use of reboot() */ + +#define CAP_SYS_BOOT 22 + +/* Allow raising priority and setting priority on other (different + UID) processes */ +/* Allow use of FIFO and round-robin (realtime) scheduling on own + processes and setting the scheduling algorithm used by another + process. */ +/* Allow setting cpu affinity on other processes */ + +#define CAP_SYS_NICE 23 + +/* Override resource limits. Set resource limits. */ +/* Override quota limits. */ +/* Override reserved space on ext2 filesystem */ +/* Modify data journaling mode on ext3 filesystem (uses journaling + resources) */ +/* NOTE: ext2 honors fsuid when checking for resource overrides, so + you can override using fsuid too */ +/* Override size restrictions on IPC message queues */ +/* Allow more than 64hz interrupts from the real-time clock */ +/* Override max number of consoles on console allocation */ +/* Override max number of keymaps */ + +#define CAP_SYS_RESOURCE 24 + +/* Allow manipulation of system clock */ +/* Allow irix_stime on mips */ +/* Allow setting the real-time clock */ + +#define CAP_SYS_TIME 25 + +/* Allow configuration of tty devices */ +/* Allow vhangup() of tty */ + +#define CAP_SYS_TTY_CONFIG 26 + +/* Allow the privileged aspects of mknod() */ + +#define CAP_MKNOD 27 + +/* Allow taking of leases on files */ + +#define CAP_LEASE 28 + +#define CAP_AUDIT_WRITE 29 + +#define CAP_AUDIT_CONTROL 30 + +#define CAP_SETFCAP 31 + +/* Override MAC access. + The base kernel enforces no MAC policy. + An LSM may enforce a MAC policy, and if it does and it chooses + to implement capability based overrides of that policy, this is + the capability it should use to do so. */ + +#define CAP_MAC_OVERRIDE 32 + +/* Allow MAC configuration or state changes. + The base kernel requires no MAC configuration. + An LSM may enforce a MAC policy, and if it does and it chooses + to implement capability based checks on modifications to that + policy or the data required to maintain it, this is the + capability it should use to do so. */ + +#define CAP_MAC_ADMIN 33 + + +/* Privileged syslog operations currently require CAP_SYSLOG. + CAP_SYS_ADMIN is not acceptable anymore. */ +#define CAP_SYSLOG 34 + +#define CAP_LAST_CAP CAP_SYSLOG + +#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) + +/* + * Bit location of each capability (used by user-space library and kernel) + */ + +#define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */ +#define CAP_TO_MASK(x) (1 << ((x) & 31)) /* mask for indexed __u32 */ + +#ifdef __KERNEL__ + +/* + * Internal kernel functions only + */ + +#define CAP_FOR_EACH_U32(__capi) \ + for (__capi = 0; __capi < _KERNEL_CAPABILITY_U32S; ++__capi) + +/* + * CAP_FS_MASK and CAP_NFSD_MASKS: + * + * The fs mask is all the privileges that fsuid==0 historically meant. + * At one time in the past, that included CAP_MKNOD and CAP_LINUX_IMMUTABLE. + * + * It has never meant setting security.* and trusted.* xattrs. + * + * We could also define fsmask as follows: + * 1. CAP_FS_MASK is the privilege to bypass all fs-related DAC permissions + * 2. The security.* and trusted.* xattrs are fs-related MAC permissions + */ + +# define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \ + | CAP_TO_MASK(CAP_MKNOD) \ + | CAP_TO_MASK(CAP_DAC_OVERRIDE) \ + | CAP_TO_MASK(CAP_DAC_READ_SEARCH) \ + | CAP_TO_MASK(CAP_FOWNER) \ + | CAP_TO_MASK(CAP_FSETID)) + +# define CAP_FS_MASK_B1 (CAP_TO_MASK(CAP_MAC_OVERRIDE)) + +#if _KERNEL_CAPABILITY_U32S != 2 +# error Fix up hand-coded capability macro initializers +#else /* HAND-CODED capability initializers */ + +# define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) +# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) +# define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}) +# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ + | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ + CAP_FS_MASK_B1 } }) +# define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ + | CAP_TO_MASK(CAP_SYS_RESOURCE), \ + CAP_FS_MASK_B1 } }) + +#endif /* _KERNEL_CAPABILITY_U32S != 2 */ + +#define CAP_INIT_INH_SET CAP_EMPTY_SET + +# define cap_clear(c) do { (c) = __cap_empty_set; } while (0) +# define cap_set_full(c) do { (c) = __cap_full_set; } while (0) +# define cap_set_init_eff(c) do { (c) = __cap_init_eff_set; } while (0) + +#define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) +#define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) +#define cap_raised(c, flag) ((c).cap[CAP_TO_INDEX(flag)] & CAP_TO_MASK(flag)) + +#define CAP_BOP_ALL(c, a, b, OP) \ +do { \ + unsigned __capi; \ + CAP_FOR_EACH_U32(__capi) { \ + c.cap[__capi] = a.cap[__capi] OP b.cap[__capi]; \ + } \ +} while (0) + +#define CAP_UOP_ALL(c, a, OP) \ +do { \ + unsigned __capi; \ + CAP_FOR_EACH_U32(__capi) { \ + c.cap[__capi] = OP a.cap[__capi]; \ + } \ +} while (0) + +static inline kernel_cap_t cap_combine(const kernel_cap_t a, + const kernel_cap_t b) +{ + kernel_cap_t dest; + CAP_BOP_ALL(dest, a, b, |); + return dest; +} + +static inline kernel_cap_t cap_intersect(const kernel_cap_t a, + const kernel_cap_t b) +{ + kernel_cap_t dest; + CAP_BOP_ALL(dest, a, b, &); + return dest; +} + +static inline kernel_cap_t cap_drop(const kernel_cap_t a, + const kernel_cap_t drop) +{ + kernel_cap_t dest; + CAP_BOP_ALL(dest, a, drop, &~); + return dest; +} + +static inline kernel_cap_t cap_invert(const kernel_cap_t c) +{ + kernel_cap_t dest; + CAP_UOP_ALL(dest, c, ~); + return dest; +} + +static inline int cap_isclear(const kernel_cap_t a) +{ + unsigned __capi; + CAP_FOR_EACH_U32(__capi) { + if (a.cap[__capi] != 0) + return 0; + } + return 1; +} + +/* + * Check if "a" is a subset of "set". + * return 1 if ALL of the capabilities in "a" are also in "set" + * cap_issubset(0101, 1111) will return 1 + * return 0 if ANY of the capabilities in "a" are not in "set" + * cap_issubset(1111, 0101) will return 0 + */ +static inline int cap_issubset(const kernel_cap_t a, const kernel_cap_t set) +{ + kernel_cap_t dest; + dest = cap_drop(a, set); + return cap_isclear(dest); +} + +/* Used to decide between falling back on the old suser() or fsuser(). */ + +static inline int cap_is_fs_cap(int cap) +{ + const kernel_cap_t __cap_fs_set = CAP_FS_SET; + return !!(CAP_TO_MASK(cap) & __cap_fs_set.cap[CAP_TO_INDEX(cap)]); +} + +static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a) +{ + const kernel_cap_t __cap_fs_set = CAP_FS_SET; + return cap_drop(a, __cap_fs_set); +} + +static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a, + const kernel_cap_t permitted) +{ + const kernel_cap_t __cap_fs_set = CAP_FS_SET; + return cap_combine(a, + cap_intersect(permitted, __cap_fs_set)); +} + +static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a) +{ + const kernel_cap_t __cap_fs_set = CAP_NFSD_SET; + return cap_drop(a, __cap_fs_set); +} + +static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a, + const kernel_cap_t permitted) +{ + const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET; + return cap_combine(a, + cap_intersect(permitted, __cap_nfsd_set)); +} + +extern const kernel_cap_t __cap_empty_set; +extern const kernel_cap_t __cap_full_set; +extern const kernel_cap_t __cap_init_eff_set; + +/** + * has_capability - Determine if a task has a superior capability available + * @t: The task in question + * @cap: The capability to be tested for + * + * Return true if the specified task has the given superior capability + * currently in effect, false if not. + * + * Note that this does not set PF_SUPERPRIV on the task. + */ +#define has_capability(t, cap) (security_real_capable((t), (cap)) == 0) + +/** + * has_capability_noaudit - Determine if a task has a superior capability available (unaudited) + * @t: The task in question + * @cap: The capability to be tested for + * + * Return true if the specified task has the given superior capability + * currently in effect, false if not, but don't write an audit message for the + * check. + * + * Note that this does not set PF_SUPERPRIV on the task. + */ +#define has_capability_noaudit(t, cap) \ + (security_real_capable_noaudit((t), (cap)) == 0) + +extern int capable(int cap); + +/* audit system wants to get cap info from files as well */ +struct dentry; +extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps); + +#endif /* __KERNEL__ */ + +#endif /* !_LINUX_CAPABILITY_H */ diff --git a/libcap/include/linux/prctl.h b/libcap/include/linux/prctl.h new file mode 100644 index 0000000..a3baeb2 --- /dev/null +++ b/libcap/include/linux/prctl.h @@ -0,0 +1,105 @@ +#ifndef _LINUX_PRCTL_H +#define _LINUX_PRCTL_H + +/* Values to pass as first argument to prctl() */ + +#define PR_SET_PDEATHSIG 1 /* Second arg is a signal */ +#define PR_GET_PDEATHSIG 2 /* Second arg is a ptr to return the signal */ + +/* Get/set current->mm->dumpable */ +#define PR_GET_DUMPABLE 3 +#define PR_SET_DUMPABLE 4 + +/* Get/set unaligned access control bits (if meaningful) */ +#define PR_GET_UNALIGN 5 +#define PR_SET_UNALIGN 6 +# define PR_UNALIGN_NOPRINT 1 /* silently fix up unaligned user accesses */ +# define PR_UNALIGN_SIGBUS 2 /* generate SIGBUS on unaligned user access */ + +/* Get/set whether or not to drop capabilities on setuid() away from + * uid 0 (as per security/commoncap.c) */ +#define PR_GET_KEEPCAPS 7 +#define PR_SET_KEEPCAPS 8 + +/* Get/set floating-point emulation control bits (if meaningful) */ +#define PR_GET_FPEMU 9 +#define PR_SET_FPEMU 10 +# define PR_FPEMU_NOPRINT 1 /* silently emulate fp operations accesses */ +# define PR_FPEMU_SIGFPE 2 /* don't emulate fp operations, send SIGFPE instead */ + +/* Get/set floating-point exception mode (if meaningful) */ +#define PR_GET_FPEXC 11 +#define PR_SET_FPEXC 12 +# define PR_FP_EXC_SW_ENABLE 0x80 /* Use FPEXC for FP exception enables */ +# define PR_FP_EXC_DIV 0x010000 /* floating point divide by zero */ +# define PR_FP_EXC_OVF 0x020000 /* floating point overflow */ +# define PR_FP_EXC_UND 0x040000 /* floating point underflow */ +# define PR_FP_EXC_RES 0x080000 /* floating point inexact result */ +# define PR_FP_EXC_INV 0x100000 /* floating point invalid operation */ +# define PR_FP_EXC_DISABLED 0 /* FP exceptions disabled */ +# define PR_FP_EXC_NONRECOV 1 /* async non-recoverable exc. mode */ +# define PR_FP_EXC_ASYNC 2 /* async recoverable exception mode */ +# define PR_FP_EXC_PRECISE 3 /* precise exception mode */ + +/* Get/set whether we use statistical process timing or accurate timestamp + * based process timing */ +#define PR_GET_TIMING 13 +#define PR_SET_TIMING 14 +# define PR_TIMING_STATISTICAL 0 /* Normal, traditional, + statistical process timing */ +# define PR_TIMING_TIMESTAMP 1 /* Accurate timestamp based + process timing */ + +#define PR_SET_NAME 15 /* Set process name */ +#define PR_GET_NAME 16 /* Get process name */ + +/* Get/set process endian */ +#define PR_GET_ENDIAN 19 +#define PR_SET_ENDIAN 20 +# define PR_ENDIAN_BIG 0 +# define PR_ENDIAN_LITTLE 1 /* True little endian mode */ +# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */ + +/* Get/set process seccomp mode */ +#define PR_GET_SECCOMP 21 +#define PR_SET_SECCOMP 22 + +/* Get/set the capability bounding set (as per security/commoncap.c) */ +#define PR_CAPBSET_READ 23 +#define PR_CAPBSET_DROP 24 + +/* Get/set the process' ability to use the timestamp counter instruction */ +#define PR_GET_TSC 25 +#define PR_SET_TSC 26 +# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */ +# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */ + +/* Get/set securebits (as per security/commoncap.c) */ +#define PR_GET_SECUREBITS 27 +#define PR_SET_SECUREBITS 28 + +/* + * Get/set the timerslack as used by poll/select/nanosleep + * A value of 0 means "use default" + */ +#define PR_SET_TIMERSLACK 29 +#define PR_GET_TIMERSLACK 30 + +#define PR_TASK_PERF_EVENTS_DISABLE 31 +#define PR_TASK_PERF_EVENTS_ENABLE 32 + +/* + * Set early/late kill mode for hwpoison memory corruption. + * This influences when the process gets killed on a memory corruption. + */ +#define PR_MCE_KILL 33 +# define PR_MCE_KILL_CLEAR 0 +# define PR_MCE_KILL_SET 1 + +# define PR_MCE_KILL_LATE 0 +# define PR_MCE_KILL_EARLY 1 +# define PR_MCE_KILL_DEFAULT 2 + +#define PR_MCE_KILL_GET 34 + +#endif /* _LINUX_PRCTL_H */ diff --git a/libcap/include/linux/securebits.h b/libcap/include/linux/securebits.h new file mode 100644 index 0000000..3340617 --- /dev/null +++ b/libcap/include/linux/securebits.h @@ -0,0 +1,54 @@ +#ifndef _LINUX_SECUREBITS_H +#define _LINUX_SECUREBITS_H 1 + +/* Each securesetting is implemented using two bits. One bit specifies + whether the setting is on or off. The other bit specify whether the + setting is locked or not. A setting which is locked cannot be + changed from user-level. */ +#define issecure_mask(X) (1 << (X)) +#ifdef __KERNEL__ +#define issecure(X) (issecure_mask(X) & current_cred_xxx(securebits)) +#endif + +#define SECUREBITS_DEFAULT 0x00000000 + +/* When set UID 0 has no special privileges. When unset, we support + inheritance of root-permissions and suid-root executable under + compatibility mode. We raise the effective and inheritable bitmasks + *of the executable file* if the effective uid of the new process is + 0. If the real uid is 0, we raise the effective (legacy) bit of the + executable file. */ +#define SECURE_NOROOT 0 +#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */ + +#define SECBIT_NOROOT (issecure_mask(SECURE_NOROOT)) +#define SECBIT_NOROOT_LOCKED (issecure_mask(SECURE_NOROOT_LOCKED)) + +/* When set, setuid to/from uid 0 does not trigger capability-"fixup". + When unset, to provide compatiblility with old programs relying on + set*uid to gain/lose privilege, transitions to/from uid 0 cause + capabilities to be gained/lost. */ +#define SECURE_NO_SETUID_FIXUP 2 +#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */ + +#define SECBIT_NO_SETUID_FIXUP (issecure_mask(SECURE_NO_SETUID_FIXUP)) +#define SECBIT_NO_SETUID_FIXUP_LOCKED \ + (issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED)) + +/* When set, a process can retain its capabilities even after + transitioning to a non-root user (the set-uid fixup suppressed by + bit 2). Bit-4 is cleared when a process calls exec(); setting both + bit 4 and 5 will create a barrier through exec that no exec()'d + child can use this feature again. */ +#define SECURE_KEEP_CAPS 4 +#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */ + +#define SECBIT_KEEP_CAPS (issecure_mask(SECURE_KEEP_CAPS)) +#define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED)) + +#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \ + issecure_mask(SECURE_NO_SETUID_FIXUP) | \ + issecure_mask(SECURE_KEEP_CAPS)) +#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1) + +#endif /* !_LINUX_SECUREBITS_H */ diff --git a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h new file mode 100644 index 0000000..4b54acc --- /dev/null +++ b/libcap/include/sys/capability.h @@ -0,0 +1,129 @@ +/* + * <sys/capability.h> + * + * Copyright (C) 1997 Aleph One + * Copyright (C) 1997-8,2008 Andrew G. Morgan <morgan@kernel.org> + * + * defunct POSIX.1e Standard: 25.2 Capabilities <sys/capability.h> + */ + +#ifndef _SYS_CAPABILITY_H +#define _SYS_CAPABILITY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This file complements the kernel file by providing prototype + * information for the user library. + */ + +#include <sys/types.h> +#include <stdint.h> +#include <linux/types.h> + +/* + * Required to limit what gets defined in the kernel header file. + */ +#ifndef __user +#define __user +#endif +#include <linux/capability.h> + +/* + * POSIX capability types + */ + +/* + * Opaque capability handle (defined internally by libcap) + * internal capability representation + */ +typedef struct _cap_struct *cap_t; + +/* "external" capability representation is a (void *) */ + +/* + * This is the type used to identify capabilities + */ + +typedef int cap_value_t; + +/* + * Set identifiers + */ +typedef enum { + CAP_EFFECTIVE=0, /* Specifies the effective flag */ + CAP_PERMITTED=1, /* Specifies the permitted flag */ + CAP_INHERITABLE=2 /* Specifies the inheritable flag */ +} cap_flag_t; + +/* + * These are the states available to each capability + */ +typedef enum { + CAP_CLEAR=0, /* The flag is cleared/disabled */ + CAP_SET=1 /* The flag is set/enabled */ +} cap_flag_value_t; + +/* + * User-space capability manipulation routines + */ + +/* libcap/cap_alloc.c */ +extern cap_t cap_dup(cap_t); +extern int cap_free(void *); +extern cap_t cap_init(void); + +/* libcap/cap_flag.c */ +extern int cap_get_flag(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *); +extern int cap_set_flag(cap_t, cap_flag_t, int, const cap_value_t *, + cap_flag_value_t); +extern int cap_clear(cap_t); +extern int cap_clear_flag(cap_t, cap_flag_t); + +/* libcap/cap_file.c */ +extern cap_t cap_get_fd(int); +extern cap_t cap_get_file(const char *); +extern int cap_set_fd(int, cap_t); +extern int cap_set_file(const char *, cap_t); + +/* libcap/cap_proc.c */ +extern cap_t cap_get_proc(void); +extern cap_t cap_get_pid(pid_t); +extern int cap_set_proc(cap_t); + +extern int cap_get_bound(cap_value_t); +extern int cap_drop_bound(cap_value_t); + +#define CAP_IS_SUPPORTED(cap) (cap_get_bound(cap) >= 0) + +/* libcap/cap_extint.c */ +extern ssize_t cap_size(cap_t); +extern ssize_t cap_copy_ext(void *, cap_t, ssize_t); +extern cap_t cap_copy_int(const void *); + +/* libcap/cap_text.c */ +extern cap_t cap_from_text(const char *); +extern char * cap_to_text(cap_t, ssize_t *); +extern int cap_from_name(const char *, cap_value_t *); +extern char * cap_to_name(cap_value_t); + +#define CAP_DIFFERS(result, flag) (((result) & (1 << (flag))) != 0) +extern int cap_compare(cap_t, cap_t); + +/* system calls - look to libc for function to system call mapping */ +extern int capset(cap_user_header_t header, cap_user_data_t data); +extern int capget(cap_user_header_t header, const cap_user_data_t data); + +/* deprecated - use cap_get_pid() */ +extern int capgetp(pid_t pid, cap_t cap_d); + +/* not valid with filesystem capability support - use cap_set_proc() */ +extern int capsetp(pid_t pid, cap_t cap_d); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CAPABILITY_H */ diff --git a/libcap/include/sys/securebits.h b/libcap/include/sys/securebits.h new file mode 100644 index 0000000..14cf3c5 --- /dev/null +++ b/libcap/include/sys/securebits.h @@ -0,0 +1,22 @@ +/* + * <sys/securebits.h> + * Copyright (C) 2010 Serge Hallyn <serue@us.ibm.com> + */ + +#ifndef _SYS_SECUREBITS_H +#define _SYS_SECUREBITS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __user +#define __user +#endif +#include <linux/securebits.h> + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SECUREBITS_H */ diff --git a/libcap/libcap.h b/libcap/libcap.h new file mode 100644 index 0000000..1e66f98 --- /dev/null +++ b/libcap/libcap.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 1997 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/capability.h> + +#ifndef __u8 +#define __u8 unsigned char +#endif /* __8 */ + +#ifndef __u32 +#define __u32 unsigned int +#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 */ + +/* + * 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 { + struct __user_cap_header_struct head; + union { + struct __user_cap_data_struct set; + __u32 flat[NUMBER_OF_CAP_SETS]; + } u[_LIBCAP_CAPABILITY_U32S]; +}; + +/* the maximum bits supportable */ +#define __CAP_MAXBITS (__CAP_BLKS * 32) + +/* string magic for cap_free */ +#define CAP_S_MAGIC 0xCA95D0 + +/* + * kernel API cap set abstraction + */ + +#define raise_cap(x,set) u[(x)>>5].flat[set] |= (1<<((x)&31)) +#define lower_cap(x,set) u[(x)>>5].flat[set] &= ~(1<<((x)&31)) +#define isset_cap(y,x,set) ((y)->u[(x)>>5].flat[set] & (1<<((x)&31))) + +/* + * Private definitions for internal use by the library. + */ + +#define __libcap_check_magic(c,magic) ((c) && *(-1+(__u32 *)(c)) == (magic)) +#define good_cap_t(c) __libcap_check_magic(c, CAP_T_MAGIC) +#define good_cap_string(c) __libcap_check_magic(c, CAP_S_MAGIC) + +/* + * 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); + +/* + * 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 capset(cap_user_header_t header, cap_user_data_t data); +extern int capget(cap_user_header_t header, const 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 + +#endif /* LIBCAP_H */ |