diff options
author | Andrew Morgan <morgan@kernel.org> | 2007-07-10 20:50:21 -0700 |
---|---|---|
committer | Andrew Morgan <morgan@kernel.org> | 2007-07-10 20:50:21 -0700 |
commit | 2c9c0532daccfd300f0eb1401b15348ed19d0ce7 (patch) | |
tree | 0e850e1a45be8cb8452a5157bd4b6538eafdbebe /libcap | |
download | libcap-2c9c0532daccfd300f0eb1401b15348ed19d0ce7.tar.gz |
This is the source for libcap-1.0.tar.gz
http://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/libcap-1.0.tar.gz
Diffstat (limited to 'libcap')
-rw-r--r-- | libcap/Makefile | 77 | ||||
-rw-r--r-- | libcap/RCS/Makefile,v | 256 | ||||
-rw-r--r-- | libcap/RCS/_makenames.c,v | 218 | ||||
-rw-r--r-- | libcap/RCS/cap_alloc.c,v | 168 | ||||
-rw-r--r-- | libcap/RCS/cap_extint.c,v | 260 | ||||
-rw-r--r-- | libcap/RCS/cap_file.c,v | 278 | ||||
-rw-r--r-- | libcap/RCS/cap_flag.c,v | 241 | ||||
-rw-r--r-- | libcap/RCS/cap_proc.c,v | 241 | ||||
-rw-r--r-- | libcap/RCS/cap_sys.c,v | 176 | ||||
-rw-r--r-- | libcap/RCS/cap_text.c,v | 996 | ||||
-rw-r--r-- | libcap/RCS/libcap.h,v | 287 | ||||
-rw-r--r-- | libcap/_makenames.c | 79 | ||||
-rw-r--r-- | libcap/cap_alloc.c | 90 | ||||
-rw-r--r-- | libcap/cap_extint.c | 142 | ||||
-rw-r--r-- | libcap/cap_file.c | 117 | ||||
-rw-r--r-- | libcap/cap_flag.c | 122 | ||||
-rw-r--r-- | libcap/cap_proc.c | 100 | ||||
-rw-r--r-- | libcap/cap_sys.c | 36 | ||||
-rw-r--r-- | libcap/cap_text.c | 323 | ||||
-rw-r--r-- | libcap/include/sys/RCS/capability.h,v | 197 | ||||
-rw-r--r-- | libcap/include/sys/capability.h | 104 | ||||
-rw-r--r-- | libcap/libcap.h | 125 |
22 files changed, 4633 insertions, 0 deletions
diff --git a/libcap/Makefile b/libcap/Makefile new file mode 100644 index 0000000..19287da --- /dev/null +++ b/libcap/Makefile @@ -0,0 +1,77 @@ +## +## $Log: Makefile,v $ +## Revision 1.5 1998/05/24 22:54:09 morgan +## updated for 2.1.104 +## +## Revision 1.4 1997/05/14 05:17:13 morgan +## autoconf rearrangement from Zefram +## +## Revision 1.3 1997/05/04 05:34:59 morgan +## cleaner +## +## Revision 1.2 1997/04/28 00:57:11 morgan +## fixes and zefram's patches +## +## Revision 1.1 1997/04/21 04:33:29 morgan +## Initial revision +## +## +## + +# +# defines +# +topdir=$(shell pwd)/.. +include ../Make.Rules +# +# Library version +# +LIBNAME=libcap.so +# + +FILES=cap_alloc cap_proc cap_extint cap_flag cap_text cap_sys + +# for later when there is filesystem support for cap's: +#FILES += cap_file + +INCLS=libcap.h cap_names.h $(INCS) +OBJS=$(addsuffix .o, $(FILES)) +MAJLIBNAME=$(LIBNAME).$(VERSION) +MINLIBNAME=$(MAJLIBNAME).$(MINOR) + +all: $(MINLIBNAME) + +_makenames: _makenames.c cap_names.sed + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ + +cap_names.h: _makenames + ./_makenames > cap_names.h + +cap_names.sed: Makefile /usr/include/linux/capability.h + @echo "=> making cap_names.c from <linux/capability.h>" + @sed -ne '/^#define[ \t]CAP[_A-Z]\+[ \t]\+[0-9]\+/{s/^#define \([^ \t]*\)[ \t]*\([^ \t]*\)/ \{ \2, \"\1\" \},/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;p;}' < /usr/include/linux/capability.h | fgrep -v 0x > cap_names.sed +# @sed -ne '/^#define[ \t]CAP[_A-Z]\+[ \t]\+[0-9]\+/{s/^#define CAP_\([^ \t]*\)[ \t]*\([^ \t]*\)/ \{ \2, \"\1\" \},/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;p;}' < /usr/include/linux/capability.h | fgrep -v 0x > cap_names.sed + +$(MINLIBNAME): $(OBJS) + $(LD) -soname $(MAJLIBNAME) -x -shared -o $@ $(OBJS) + ln -sf $(MINLIBNAME) $(MAJLIBNAME) + ln -sf $(MAJLIBNAME) $(LIBNAME) + +%.o: %.c $(INCLS) + $(CC) $(CFLAGS) -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 $(MINLIBNAME) $(LIBDIR)/$(MINLIBNAME) + ln -sf $(MINLIBNAME) $(LIBDIR)/$(MAJLIBNAME) + ln -sf $(MAJLIBNAME) $(LIBDIR)/$(LIBNAME) + -/sbin/ldconfig + +clean: + $(LOCALCLEAN) + rm -f $(OBJS) $(LIBNAME)* + rm -f cap_names.h cap_names.sed _makenames + cd include/sys && $(LOCALCLEAN) + diff --git a/libcap/RCS/Makefile,v b/libcap/RCS/Makefile,v new file mode 100644 index 0000000..098675e --- /dev/null +++ b/libcap/RCS/Makefile,v @@ -0,0 +1,256 @@ +head 1.5; +access; +symbols; +locks; strict; +comment @# @; + + +1.5 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.4; + +1.4 +date 97.05.14.05.17.13; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 97.05.04.05.34.59; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.33.29; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.5 +log +@updated for 2.1.104 +@ +text +@## +## $Log: Makefile,v $ +## Revision 1.4 1997/05/14 05:17:13 morgan +## autoconf rearrangement from Zefram +## +## Revision 1.3 1997/05/04 05:34:59 morgan +## cleaner +## +## Revision 1.2 1997/04/28 00:57:11 morgan +## fixes and zefram's patches +## +## Revision 1.1 1997/04/21 04:33:29 morgan +## Initial revision +## +## +## + +# +# defines +# +topdir=$(shell pwd)/.. +include ../Make.Rules +# +# Library version +# +LIBNAME=libcap.so +# + +FILES=cap_alloc cap_proc cap_extint cap_flag cap_text cap_sys + +# for later when there is filesystem support for cap's: +#FILES += cap_file + +INCLS=libcap.h cap_names.h $(INCS) +OBJS=$(addsuffix .o, $(FILES)) +MAJLIBNAME=$(LIBNAME).$(VERSION) +MINLIBNAME=$(MAJLIBNAME).$(MINOR) + +all: $(MINLIBNAME) + +_makenames: _makenames.c cap_names.sed + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@@ + +cap_names.h: _makenames + ./_makenames > cap_names.h + +cap_names.sed: Makefile /usr/include/linux/capability.h + @@echo "=> making cap_names.c from <linux/capability.h>" + @@sed -ne '/^#define[ \t]CAP[_A-Z]\+[ \t]\+[0-9]\+/{s/^#define \([^ \t]*\)[ \t]*\([^ \t]*\)/ \{ \2, \"\1\" \},/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;p;}' < /usr/include/linux/capability.h | fgrep -v 0x > cap_names.sed +# @@sed -ne '/^#define[ \t]CAP[_A-Z]\+[ \t]\+[0-9]\+/{s/^#define CAP_\([^ \t]*\)[ \t]*\([^ \t]*\)/ \{ \2, \"\1\" \},/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;p;}' < /usr/include/linux/capability.h | fgrep -v 0x > cap_names.sed + +$(MINLIBNAME): $(OBJS) + $(LD) -soname $(MAJLIBNAME) -x -shared -o $@@ $(OBJS) + ln -sf $(MINLIBNAME) $(MAJLIBNAME) + ln -sf $(MAJLIBNAME) $(LIBNAME) + +%.o: %.c $(INCLS) + $(CC) $(CFLAGS) -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 $(MINLIBNAME) $(LIBDIR)/$(MINLIBNAME) + ln -sf $(MINLIBNAME) $(LIBDIR)/$(MAJLIBNAME) + ln -sf $(MAJLIBNAME) $(LIBDIR)/$(LIBNAME) + -/sbin/ldconfig + +clean: + $(LOCALCLEAN) + rm -f $(OBJS) $(LIBNAME)* + rm -f cap_names.h cap_names.sed _makenames + cd include/sys && $(LOCALCLEAN) + +@ + + +1.4 +log +@autoconf rearrangement from Zefram +@ +text +@d3 3 +d29 4 +a32 2 +FILES=cap_alloc cap_file cap_proc cap_extint cap_flag cap_text cap_sys \ + cap_names +d34 1 +a34 1 +INCLS=libcap.h $(INCS) +d44 2 +a45 2 +cap_names.c: _makenames + ./_makenames > cap_names.c +d49 2 +a50 1 + @@sed -ne '/^#define CAP_/{s/^#define \([^ ]*\)[ ]*\([^ ]*\)/ \{ \2, \"\1\" \},/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;p;}' < /usr/include/linux/capability.h > cap_names.sed +d72 1 +a72 1 + rm -f cap_names.c cap_names.sed _makenames +@ + + +1.3 +log +@cleaner +@ +text +@d3 3 +d18 1 +a18 1 +topdir=.. +d29 1 +a29 1 +INCS=libcap.h include/sys/capability.h +d34 1 +a34 1 +all: $(LIBNAME) +d37 1 +a37 1 + $(CC) $(CFLAGS) $< -o $@@ +d46 1 +a46 1 +$(LIBNAME): $(OBJS) +d48 2 +d51 1 +a51 1 +%.o: %.c $(INCS) +d55 5 +a59 6 + mkdir -p $(INCDIR)/sys + install -g root -o root -m 0644 include/sys/capability.h $(INCDIR)/sys + mkdir -p $(LIBDIR) + install -g root -o root -m 0444 $(LIBNAME) $(LIBDIR)/$(MINLIBNAME) + rm -f $(LIBDIR)/$(LIBNAME) + /sbin/ldconfig -nN $(LIBDIR) +d61 1 +d65 2 +a66 1 + rm -f $(OBJS) $(LIBNAME) cap_names.c cap_names.sed _makenames +@ + + +1.2 +log +@fixes and zefram's patches +@ +text +@d3 3 +d33 9 +a41 12 +cap_names.c: _makenames /usr/include/linux/capability.h + @@echo -e "\n=> making cap_names.c from <linux/capability.h>\n" + @@( \ + echo '/** cap_names.c **'; \ + echo ' ** automatically generated -- DO NOT EDIT! **/'; \ + echo; \ + echo '#include "libcap.h"'; \ + echo; \ + echo 'char const *_cap_names[__CAP_BITS] = {'; \ + sed -ne '/^#define CAP_/{s/^#define \([^ ]*\)[ ]*\([^ ]*\)/ \2\/\1/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;p;}' < /usr/include/linux/capability.h | ./_makenames; \ + echo '};'; \ + ) > $@@ +d55 2 +a56 2 + /sbin/ldconfig + cd $(LIBDIR) && ln -sf $(MAJLIBNAME) $(LIBNAME) +d60 1 +a60 1 + rm -f $(OBJS) $(LIBNAME) cap_names.c _makenames +@ + + +1.1 +log +@Initial revision +@ +text +@d3 3 +d10 1 +a10 1 +# flags +d12 2 +a13 5 +IPATH=-I./include +WARNINGS = -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ + -Wpointer-arith -Wcast-qual -Wcast-align \ + -Wtraditional -Wstrict-prototypes -Wmissing-prototypes \ + -Wnested-externs -Winline -Wshadow -pedantic +a17 2 +VERSION=0 +MINOR=01 +d20 3 +a22 1 +FILES=cap_alloc cap_file cap_proc cap_extint cap_flag cap_text cap_sys +d28 1 +a28 1 +export CFLAGS =-Dlinux $(WARNINGS) $(DEBUG) $(COPTFLAG) $(IPATH) +d30 12 +a41 1 +all: $(LIBNAME) +d50 5 +a54 4 + mkdir -p $(FAKEROOT)/usr/include/sys + install -g root -o root -m 0644 include/sys/capability.h $(FAKEROOT)/usr/include/sys + mkdir -p $(FAKEROOT)/lib + install -g root -o root -m 0444 $(LIBNAME) $(FAKEROOT)/lib/$(MINLIBNAME) +d56 1 +d59 3 +a61 2 + rm -f *~ core $(OBJS) $(LIBNAME) + cd include/sys && rm -f *~ core +@ diff --git a/libcap/RCS/_makenames.c,v b/libcap/RCS/_makenames.c,v new file mode 100644 index 0000000..236d4be --- /dev/null +++ b/libcap/RCS/_makenames.c,v @@ -0,0 +1,218 @@ +head 1.4; +access; +symbols; +locks; strict; +comment @ * @; + + +1.4 +date 98.06.07.15.50.12; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.05.04.05.35.46; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next ; + + +desc +@Ansi partner to zefram's one line sed command +@ + + +1.4 +log +@updated to accommodate kernel's real header file :*) +@ +text +@/* + * $Id: _makenames.c,v 1.3 1998/05/24 22:54:09 morgan Exp morgan $ + * + * Copyright (c) 1997-8 Andrew G. Morgan <morgan@@linux.kernel.org> + * + * This is a file to make the capability <-> string mappings for + * libcap. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <linux/capability.h> + +/* + * #include 'sed' generated array + */ + +struct { + int index; + const char *name; +} const list[] = { +#include "cap_names.sed" + {-1, NULL} +}; + +/* 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; + } + 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); +} + +/* + * $Log: _makenames.c,v $ + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/05/04 05:35:46 morgan + * cleaned up to #include sed output. also generates whole cap_names.c file + * + * Revision 1.1 1997/04/28 00:57:11 morgan + * Initial revision + * + */ +@ + + +1.3 +log +@updated for 2.1.104 +@ +text +@d2 1 +a2 1 + * $Id: _makenames.c,v 1.2 1997/05/04 05:35:46 morgan Exp morgan $ +d27 1 +a27 1 +const char *pointers[8*sizeof(struct _user_cap_data_struct)]; +d67 3 +@ + + +1.2 +log +@cleaned up to #include sed output. also generates whole cap_names.c file +@ +text +@d2 1 +a2 1 + * $Id: _makenames.c,v 1.1 1997/04/28 00:57:11 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G. Morgan <morgan@@parc.power.net> +d26 2 +a27 1 +const char *pointers[__CAP_BITS]; +d31 1 +a31 1 + int i; +d34 3 +d45 1 +d47 2 +a48 3 + "#include \"libcap.h\"\n" + "\n" + "char const *_cap_names[__CAP_BITS] = {\n"); +d50 1 +a50 1 + for (i=0; i<__CAP_BITS; ++i) { +d52 1 +a52 1 + printf(" /* %d */\t\"%s\",\n", i, pointers[i]); +d54 1 +a54 1 + printf(" /* %d */\tNULL,\t\t/* - presently unused */\n", i); +d57 2 +a58 1 + printf("};\n" +d67 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +a10 2 +#define __USE_BSD +#include <string.h> +d15 1 +a15 2 + * Read the standard input for a list of index/string pairs + * store them in an array and then output an array setting file +d18 7 +a24 1 +#define MAXBUFF 100 +d26 1 +a26 1 +char *pointers[__CAP_BITS]; +d28 1 +a28 1 +void main(void) +a29 1 + char buffer[MAXBUFF]; +d32 3 +a34 5 + while (fgets(buffer, MAXBUFF, stdin)) { + char *tmp = buffer; + + tmp = strtok(tmp, "/"); + i = atoi(tmp); +d36 9 +a44 6 + tmp = strtok(NULL, "/"); + if (tmp[strlen(tmp)-1] == '\n') + tmp[strlen(tmp)-1] = '\0'; + + pointers[i] = strdup(tmp); + } +d52 6 +d61 4 +a64 1 + * $Log$ +@ diff --git a/libcap/RCS/cap_alloc.c,v b/libcap/RCS/cap_alloc.c,v new file mode 100644 index 0000000..4167830 --- /dev/null +++ b/libcap/RCS/cap_alloc.c,v @@ -0,0 +1,168 @@ +head 1.3; +access; +symbols; +locks; strict; +comment @ * @; + + +1.3 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.3 +log +@updated for 2.1.104 +@ +text +@/* + * $Id: cap_alloc.c,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with allocation and deallocation of internal + * capability sets as specified by POSIX.1e (formerlly, POSIX 6). + */ + +#include "libcap.h" + +/* + * This function duplicates an internal capability set (x3) 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_t) malloc( sizeof(*cap_d) ); + if (result == NULL) { + _cap_debug("out of memory"); + errno = ENOMEM; + return NULL; + } + + memcpy(result, cap_d, sizeof(*cap_d)); + + return result; +} + + +/* + * Scrub and then liberate an internal capability set. + */ + +int cap_free(cap_t *cap_d_p) +{ + if ( cap_d_p && good_cap_t(*cap_d_p) ) { + memset(*cap_d_p, 0, sizeof(**cap_d_p)); + free(*cap_d_p); + *cap_d_p = NULL; + + return 0; + } else { + _cap_debug("no capability to liberate"); + errno = EINVAL; + return -1; + } +} + +/* + * Obtain a blank set of capabilities + */ + +cap_t cap_init(void) +{ + cap_t result = (cap_t) calloc( 1, sizeof(*result) ); + + if (result) { + result->magic = CAP_T_MAGIC; + result->head.version = _LINUX_CAPABILITY_VERSION; + } else { + errno = ENOMEM; + } + return result; +} + +/* + * $Log: cap_alloc.c,v $ + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.2 +log +@fixes and zefram's patches +@ +text +@d2 1 +a2 1 + * $Id: cap_alloc.c,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G Morgan <morgan@@parc.power.net> +d68 1 +a68 1 + cap_t result = (cap_t) malloc( sizeof(*result) ); +d72 1 +a72 1 + memset(&result->set, 0, 3*sizeof(__cap_s)); +d81 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +a14 9 + * Return the byte length of the capability set + */ + +ssize_t cap_size(cap_t cap_d) +{ + return sizeof(*cap_d); +} + +/* +d51 1 +d72 1 +d80 4 +a83 1 + * $Log$ +@ diff --git a/libcap/RCS/cap_extint.c,v b/libcap/RCS/cap_extint.c,v new file mode 100644 index 0000000..3f07499 --- /dev/null +++ b/libcap/RCS/cap_extint.c,v @@ -0,0 +1,260 @@ +head 1.3; +access; +symbols; +locks; strict; +comment @ * @; + + +1.3 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.3 +log +@updated for 2.1.104 +@ +text +@/* + * $Id: cap_extint.c,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with exchanging internal and external + * representations of capability sets. + */ + +#include "libcap.h" + +/* + * External representation for capabilities. (exported as a fixed + * length (void *)) + */ +#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; + __u32 *from = (__u32 *) &(cap_d->set); + 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 = *from++; + + 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(). + */ + +/* + * XXX - need to take a little more care when importing small + * capability sets. + */ + +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; + __u32 * to = (__u32 *) &cap_d->set; + + /* 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/4); ++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; + + *to++ = val; + } + } + + /* all done */ + return cap_d; +} + +/* + * $Log: cap_extint.c,v $ + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.2 +log +@fixes and zefram's patches +@ +text +@d2 1 +a2 1 + * $Id: cap_extint.c,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G Morgan <morgan@@parc.power.net> +d20 1 +a20 1 +static __u8 external_magic[CAP_EXT_MAGIC_SIZE+1] = CAP_EXT_MAGIC; +d25 3 +a27 1 + __u8 bytes[sizeof(struct __cap_s)][3]; +d48 1 +d59 2 +a60 2 + memcpy(&result->magic,external_magic,CAP_EXT_MAGIC_SIZE); + result->length_of_capset = sizeof(struct __cap_s); +d62 1 +a62 1 + for (i=CAP_EFFECTIVE; i<=CAP_PERMITTED; ++i) { +d64 7 +a70 9 + for (j=0; j<__CAP_BLKS; ++j) { + __u32 val; + int k = j << 2; + + val = cap_d->set[i]._blk[j]; + result->bytes[k++][i] = val & 0xFF; + result->bytes[k++][i] = (val >>= 8) & 0xFF; + result->bytes[k++][i] = (val >>= 8) & 0xFF; + result->bytes[k][i] = (val >> 8) & 0xFF; +d94 1 +d108 1 +a108 1 + for (set=CAP_EFFECTIVE; set<=CAP_PERMITTED; ++set) { +d111 1 +a111 1 + for (blk=0; blk<__CAP_BLKS; ++blk) { +d123 1 +a123 1 + cap_d->set[set]._blk[blk] = val; +d133 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +d18 3 +d23 1 +d29 9 +d56 1 +d92 1 +d95 2 +a96 1 + if (export == NULL || export->length_of_capset > sizeof(struct __cap_s)) { +d102 20 +a121 13 + if ((cap_d = cap_init())) { + int i; + for (i=CAP_EFFECTIVE; i<=CAP_PERMITTED; ++i) { + int j; + for (j=0; j<__CAP_BLKS; ++j) { + __u32 val; + int k = (j+1) << 2; + + val = export->bytes[--k][i] << 8; + val |= export->bytes[--k][i]; val <<= 8; + val |= export->bytes[--k][i]; val <<= 8; + cap_d->set[i]._blk[j] = val | export->bytes[--k][i]; + } +d130 4 +a133 1 + * $Log$ +@ diff --git a/libcap/RCS/cap_file.c,v b/libcap/RCS/cap_file.c,v new file mode 100644 index 0000000..3a06923 --- /dev/null +++ b/libcap/RCS/cap_file.c,v @@ -0,0 +1,278 @@ +head 1.5; +access; +symbols; +locks; strict; +comment @ * @; + + +1.5 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.4; + +1.4 +date 97.05.14.05.17.13; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 97.05.04.05.35.46; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.5 +log +@updated for 2.1.104 +@ +text +@/* + * $Id: cap_file.c,v 1.4 1997/05/14 05:17:13 morgan Exp morgan $ + * + * Copyright (c) 1997 Andrew G Morgan <morgan@@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with setting capabilities on files. + */ + +#include "libcap.h" + +/* + * 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) { + _cap_debug("getting fildes capabilities"); + + /* fill the capability sets via a system call */ + if (_fgetfilecap(fildes, sizeof(struct __cap_s), + &result->set[CAP_INHERITABLE], + &result->set[CAP_PERMITTED], + &result->set[CAP_EFFECTIVE] )) { + cap_free(&result); + } + } + + return result; +} + +/* + * Set the capabilities on a named file. + */ + +cap_t cap_get_file(const char *filename) +{ + cap_t result; + + /* allocate a new capability set */ + result = cap_init(); + if (result) { + _cap_debug("getting named file capabilities"); + + /* fill the capability sets via a system call */ + if (_getfilecap(filename, sizeof(struct __cap_s), + &result->set[CAP_INHERITABLE], + &result->set[CAP_PERMITTED], + &result->set[CAP_EFFECTIVE] )) + cap_free(&result); + } + + 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) +{ + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting fildes capabilities"); + return _fsetfilecap(fildes, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +} + +/* + * Set the capabilities of a named file. + */ + +int cap_set_file(const char *filename, cap_t cap_d) +{ + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting filename capabilities"); + return _setfilecap(filename, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +} + +/* + * $Log: cap_file.c,v $ + * Revision 1.4 1997/05/14 05:17:13 morgan + * bug-fix from zefram (errno no set on success) + * + * Revision 1.3 1997/05/04 05:35:46 morgan + * fixed errno setting. syscalls do this part + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.4 +log +@bug-fix from zefram (errno no set on success) +@ +text +@d2 1 +a2 1 + * $Id: cap_file.c,v 1.3 1997/05/04 05:35:46 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G Morgan <morgan@@parc.power.net> +d102 3 +@ + + +1.3 +log +@fixed errno setting. syscalls do this part +@ +text +@d2 1 +a2 1 + * $Id: cap_file.c,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ +d70 1 +a70 10 + if (good_cap_t(cap_d)) { + _cap_debug("setting fildes capabilities"); + + if (_fsetfilecap(fildes, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] )) { + _cap_debug("failed: %s", strerror(errno)); + } + } else { +d72 1 +d75 5 +a79 1 + return (errno ? -1:0); +d88 1 +a88 10 + if (good_cap_t(cap_d)) { + _cap_debug("setting named file capabilities"); + + if (_setfilecap(filename, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] )) { + _cap_debug("failed: %s", strerror(errno)); + } + } else { +d90 1 +d93 5 +a97 1 + return (errno ? -1:0); +d102 3 +@ + + +1.2 +log +@fixes and zefram's patches +@ +text +@d2 1 +a2 1 + * $Id: cap_file.c,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +d28 1 +a28 1 + errno = -_fgetfilecap(fildes, sizeof(struct __cap_s), +d31 1 +a31 3 + &result->set[CAP_EFFECTIVE] ); + + if (errno) +d33 1 +d53 1 +a53 1 + errno = -_getfilecap(filename, sizeof(struct __cap_s), +d56 1 +a56 3 + &result->set[CAP_EFFECTIVE] ); + + if (errno) +d73 6 +a78 4 + errno = -_fsetfilecap(fildes, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +d95 6 +a100 4 + errno = -_setfilecap(filename, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +d110 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +d26 1 +d32 3 +d52 1 +d58 3 +d75 1 +d95 1 +d108 4 +a111 1 + * $Log$ +@ diff --git a/libcap/RCS/cap_flag.c,v b/libcap/RCS/cap_flag.c,v new file mode 100644 index 0000000..45a7258 --- /dev/null +++ b/libcap/RCS/cap_flag.c,v @@ -0,0 +1,241 @@ +head 1.4; +access; +symbols; +locks; strict; +comment @ * @; + + +1.4 +date 98.09.20.23.07.59; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.4 +log +@fixed lower bound check on 'set'. +@ +text +@/* + * $Id: cap_flag.c,v 1.3 1998/05/24 22:54:09 morgan Exp morgan $ + * + * Copyright (c) 1997-8 Andrew G. Morgan <morgan@@linux.kernel.org> + * + * See end of file for Log. + * + * 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) { + __cap_s *cap_p = (__cap_s *) (set*CAP_SET_SIZE + + (__u8 *) &cap_d->set); + + *raised = isset_cap(cap_p,value) ? 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, 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]; + __cap_s *cap_p = (__cap_s *) (set*CAP_SET_SIZE + + (__u8 *) &cap_d->set); + + if (raise == CAP_SET) { + cap_p->raise_cap(value); + } else { + cap_p->lower_cap(value); + } + } + } + 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->set), 0, sizeof(cap_d->set)); + return 0; + + } else { + + _cap_debug("invalid pointer"); + errno = EINVAL; + return -1; + + } +} + +/* + * $Log: cap_flag.c,v $ + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.3 +log +@updated for 2.1.104 +@ +text +@d2 1 +a2 1 + * $Id: cap_flag.c,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ +d29 1 +a29 1 + && set > 0 && set < NUMBER_OF_CAP_SETS) { +d59 1 +a59 1 + && (set > 0) && (set < NUMBER_OF_CAP_SETS) +d110 3 +@ + + +1.2 +log +@fixes and zefram's patches +@ +text +@d2 1 +a2 1 + * $Id: cap_flag.c,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G. Morgan <morgan@@parc.power.net> +d20 2 +a21 2 +int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set + , cap_flag_value_t *raised) +d28 4 +a31 1 + if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_BITS) { +d33 1 +a33 1 + *raised = (cap_d->set[set]._cap_raised(value)) ? CAP_SET:CAP_CLEAR; +d49 3 +a51 3 +int cap_set_flag(cap_t cap_d, cap_flag_t set + , int no_values, cap_value_t *array_values + , cap_flag_value_t raise) +d59 1 +a61 1 + +d65 10 +a74 4 + } else if (raise == CAP_SET) { + cap_d->set[set]._cap_raise(array_values[i]); + } else if (raise == CAP_CLEAR) { + cap_d->set[set]._cap_lower(array_values[i]); +d96 1 +a96 1 + memset(&(cap_d->set), 0, 3*sizeof(__cap_s)); +d110 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +d28 1 +a28 1 + if (raised && good_cap_t(cap_d)) { +d55 1 +a55 1 + if (good_cap_t(cap_d) && no_values > 0 && no_values < __NR_CAP +d60 1 +a60 1 + if (array_values[i] < 0 || array_values[i] >= __NR_CAP) { +d100 4 +a103 1 + * $Log$ +@ diff --git a/libcap/RCS/cap_proc.c,v b/libcap/RCS/cap_proc.c,v new file mode 100644 index 0000000..21a8c40 --- /dev/null +++ b/libcap/RCS/cap_proc.c,v @@ -0,0 +1,241 @@ +head 1.5; +access; +symbols; +locks; strict; +comment @ * @; + + +1.5 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.4; + +1.4 +date 97.05.14.05.17.13; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 97.05.04.05.35.46; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.5 +log +@updated for 2.1.104 +@ +text +@/* + * $Id: cap_proc.c,v 1.4 1997/05/14 05:17:13 morgan Exp morgan $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with setting capabilities on processes. + */ + +#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->set)) { + cap_free(&result); + } + } + + return result; +} + +int cap_set_proc(cap_t cap_d) +{ + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting process capabilities"); + return capset(&cap_d->head, &cap_d->set); +} + +/* 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->set); + cap_d->head.pid = 0; + + return error; +} + +/* 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->set); + cap_d->head.pid = 0; + + return error; +} + +/* + * $Log: cap_proc.c,v $ + * Revision 1.4 1997/05/14 05:17:13 morgan + * bug-fix from zefram (errno no set on success) + * + * Revision 1.3 1997/05/04 05:35:46 morgan + * fixed errno setting. syscalls do this part + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.4 +log +@bug-fix from zefram (errno no set on success) +@ +text +@d2 1 +a2 1 + * $Id: cap_proc.c,v 1.3 1997/05/04 05:35:46 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G Morgan <morgan@@parc.power.net> +d23 1 +a23 4 + if (_getproccap(sizeof(struct __cap_s), + &result->set[CAP_INHERITABLE], + &result->set[CAP_PERMITTED], + &result->set[CAP_EFFECTIVE] )) +d25 1 +d39 42 +a80 4 + return _setproccap(sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +d85 3 +@ + + +1.3 +log +@fixed errno setting. syscalls do this part +@ +text +@d2 1 +a2 1 + * $Id: cap_proc.c,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ +d35 1 +a35 11 + if (good_cap_t(cap_d)) { + _cap_debug("setting current process' capabilities"); + + /* fill the capability sets via a system call */ + if (_setproccap(sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] )) { + _cap_debug("failed: %s", strerror(errno)); + } + } else +d37 2 +d40 5 +a44 1 + return (errno ? -1:0); +d49 3 +@ + + +1.2 +log +@fixes and zefram's patches +@ +text +@d2 1 +a2 1 + * $Id: cap_proc.c,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +d23 4 +a26 6 + errno = -_getproccap(sizeof(struct __cap_s), + &result->set[CAP_INHERITABLE], + &result->set[CAP_PERMITTED], + &result->set[CAP_EFFECTIVE] ); + + if (errno) +d39 6 +a44 4 + errno = -_setproccap(sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +d53 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +d21 1 +d27 3 +d39 1 +d52 4 +a55 1 + * $Log$ +@ diff --git a/libcap/RCS/cap_sys.c,v b/libcap/RCS/cap_sys.c,v new file mode 100644 index 0000000..bdd6098 --- /dev/null +++ b/libcap/RCS/cap_sys.c,v @@ -0,0 +1,176 @@ +head 1.4; +access; +symbols; +locks; strict; +comment @ * @; + + +1.4 +date 98.06.08.00.14.01; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.4 +log +@change to accommodate alpha (glibc?) +@ +text +@/* + * $Id: cap_sys.c,v 1.3 1998/05/24 22:54:09 morgan Exp morgan $ + * + * Copyright (c) 1997-8 Andrew G. Morgan <morgan@@linux.kernel.org> + * + * This file contains the system calls for getting and setting + * capabilities + */ + +#include "libcap.h" +#define __LIBRARY__ +#include <linux/unistd.h> + +_syscall2(int, capget, + cap_user_header_t, header, + cap_user_data_t, data) + +_syscall2(int, capset, + cap_user_header_t, header, + const cap_user_data_t, data) + +/* + * $Log: cap_sys.c,v $ + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.3 +log +@updated for 2.1.104 +@ +text +@d2 1 +a2 1 + * $Id: cap_sys.c,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ +d11 1 +d24 3 +@ + + +1.2 +log +@fixes and zefram's patches +@ +text +@d2 1 +a2 1 + * $Id: cap_sys.c,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G. Morgan <morgan@@parc.power.net> +d13 7 +a19 41 +_syscall4(int, _setproccap, + size_t, usize, + __cap_s const *, iset, + __cap_s const *, pset, + __cap_s const *, eset) + +_syscall4(int, _getproccap, + size_t, usize, + __cap_s *, iset, + __cap_s *, pset, + __cap_s *, eset) + +/* Secondly, we have the file capabilities */ + +_syscall5(int, _setfilecap, + char const *, filename, + size_t, usize, + __cap_s const *, iset, + __cap_s const *, pset, + __cap_s const *, eset) + +_syscall5(int, _getfilecap, + char const *, filename, + size_t, usize, + __cap_s *, iset, + __cap_s *, pset, + __cap_s *, eset) + +_syscall5(int, _fsetfilecap, + int, fd, + size_t, usize, + __cap_s const *, iset, + __cap_s const *, pset, + __cap_s const *, eset) + +_syscall5(int, _fgetfilecap, + int, fd, + size_t, usize, + __cap_s *, iset, + __cap_s *, pset, + __cap_s *, eset) +d23 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +d11 1 +d21 3 +a23 3 + __cap_s const *, iset, + __cap_s const *, pset, + __cap_s const *, eset) +d25 1 +a25 1 +/* Secondly, we have the file capabilitiy setting */ +d37 3 +a39 3 + __cap_s const *, iset, + __cap_s const *, pset, + __cap_s const *, eset) +d51 3 +a53 3 + __cap_s const *, iset, + __cap_s const *, pset, + __cap_s const *, eset) +d56 4 +a59 1 + * $Log$ +@ diff --git a/libcap/RCS/cap_text.c,v b/libcap/RCS/cap_text.c,v new file mode 100644 index 0000000..d537f75 --- /dev/null +++ b/libcap/RCS/cap_text.c,v @@ -0,0 +1,996 @@ +head 1.4; +access; +symbols; +locks; strict; +comment @ * @; + + +1.4 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 97.05.04.05.37.00; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.4 +log +@updated for 2.1.104 +@ +text +@/* + * $Id: cap_text.c,v 1.3 1997/05/04 05:37:00 morgan Exp morgan $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@@linux.kernel.org> + * Copyright (c) 1997 Andrew Main <zefram@@dcs.warwick.ac.uk> + * + * See end of file for Log. + * + * This file deals with exchanging internal and textual + * representations of capability sets. + */ + +#define LIBCAP_PLEASE_INCLUDE_ARRAY +#include "libcap.h" + +#include <ctype.h> +#include <stdio.h> + +char *strdup(const char *s); + +/* Maximum output text length (16 per cap) */ +#define CAP_TEXT_SIZE (16*__CAP_BITS) + +#define LIBCAP_EFF 01 +#define LIBCAP_INH 02 +#define LIBCAP_PER 04 + +/* + * Parse a textual representation of capabilities, returning an internal + * representation. + */ + +#define setbits(A,B) _setbits((__cap_s *)A, (__cap_s *)B) +static void _setbits(__cap_s *a, __cap_s *b) +{ + int n; + for (n = __CAP_BLKS; n--; ) + a->_blk[n] |= b->_blk[n]; +} + +#define clrbits(A,B) _clrbits((__cap_s *)A, (__cap_s *)B) +static void _clrbits(__cap_s *a, __cap_s *b) +{ + int n; + for (n = __CAP_BLKS; n--; ) + a->_blk[n] &= ~b->_blk[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 int lookupname(char const **strp) +{ + char const *str = *strp; + if (isdigit(*str)) { + unsigned long n = strtoul(str, (char **)&str, 0); + if (n >= __CAP_BITS) + return -1; + *strp = str; + return n; + } else { + char const *s; + int n; + for (n = __CAP_BITS; n--; ) + if (_cap_names[n] && (s = namcmp(str, _cap_names[n]))) { + *strp = s; + return n; + } + return -1; + } +} + +cap_t cap_from_text(const char *str) +{ + cap_t res; + __cap_s allones; + int n; + + if (str == NULL) { + _cap_debug("bad argument"); + errno = EINVAL; + return NULL; + } + + if (!(res = cap_init())) + return NULL; + for (n = __CAP_BLKS; n--; ) + allones._blk[n] = -1; + _cap_debug("%s", str); + + for (;;) { + char op; + int flags = 0, listed=0; + __cap_s list = {{0}}; + + /* skip leading spaces */ + while (isspace((unsigned char)*str)) + str++; + if (!*str) { + _cap_debugcap("e = ", &res->set.effective); + _cap_debugcap("i = ", &res->set.inheritable); + _cap_debugcap("p = ", &res->set.permitted); + return res; + } + + /* identify caps specified by this clause */ + if (isalnum((unsigned char)*str) || *str == '_') { + for (;;) { + if (namcmp(str, "all")) { + str += 3; + list = allones; + } else { + n = lookupname(&str); + if (n == -1) + goto bad; + list.raise_cap(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 + list = allones; + + /* 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->set.effective, &list); + clrbits(&res->set.inheritable, &list); + clrbits(&res->set.permitted, &list); + /* fall through */ + if (op == 'M') + goto minus; + case '+': + if (flags & LIBCAP_EFF) + setbits(&res->set.effective, &list); + if (flags & LIBCAP_INH) + setbits(&res->set.inheritable, &list); + if (flags & LIBCAP_PER) + setbits(&res->set.permitted, &list); + break; + case '-': + minus: + if (flags & LIBCAP_EFF) + clrbits(&res->set.effective, &list); + if (flags & LIBCAP_INH) + clrbits(&res->set.inheritable, &list); + if (flags & LIBCAP_PER) + clrbits(&res->set.permitted, &list); + 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); + errno = EINVAL; + return NULL; +} + +/* + * 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((__cap_s *)(&caps->set.effective),capno)) + f |= LIBCAP_EFF; + if (isset_cap((__cap_s *)(&caps->set.inheritable),capno)) + f |= LIBCAP_INH; + if (isset_cap((__cap_s *)(&caps->set.permitted),capno)) + f |= LIBCAP_PER; + + return f; +} + +#define CAP_TEXT_BUFFER_ZONE 100 + +char *cap_to_text(cap_t caps, ssize_t *length_p) +{ + static char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE]; + char *p; + int histo[8] = {0}; + int m, n, t; + + /* Check arguments */ + if (!good_cap_t(caps) || length_p == NULL) { + errno = EINVAL; + return NULL; + } + + _cap_debugcap("e = ", &caps->set.effective); + _cap_debugcap("i = ", &caps->set.inheritable); + _cap_debugcap("p = ", &caps->set.permitted); + + for (n = __CAP_BITS; n--; ) + histo[getstateflags(caps, n)]++; + + for (m=t=7; t--; ) + if (histo[t] > histo[m]) + m = t; + + /* 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_BITS; n++) + if (getstateflags(caps, n) == t) { + if (_cap_names[n]) + p += sprintf(p, "%s,", _cap_names[n]); + else + p += sprintf(p, "%d,", n); + if (p - buf > CAP_TEXT_SIZE) { + errno = ERANGE; + return NULL; + } + } + 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); + *length_p = p - buf; + return (strdup(buf)); +} + +/* + * $Log: cap_text.c,v $ + * Revision 1.3 1997/05/04 05:37:00 morgan + * case sensitvity to capability flags + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * zefram's replacement file with a number of bug fixes from AGM + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.3 +log +@case sensitvity to capability flags +@ +text +@d2 1 +a2 1 + * $Id: cap_text.c,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G Morgan <morgan@@parc.power.net> +d13 1 +d19 2 +d33 2 +a34 1 +static void setbits(__cap_s *a, __cap_s *b) +d41 2 +a42 1 +static void clrbits(__cap_s *a, __cap_s *b) +d108 3 +a110 3 + _cap_debugcap("e = ", &res->set[CAP_EFFECTIVE]); + _cap_debugcap("i = ", &res->set[CAP_INHERITABLE]); + _cap_debugcap("p = ", &res->set[CAP_PERMITTED]); +d124 1 +a124 1 + list._cap_raise(n); +d173 3 +a175 3 + clrbits(&res->set[CAP_EFFECTIVE], &list); + clrbits(&res->set[CAP_INHERITABLE], &list); + clrbits(&res->set[CAP_PERMITTED], &list); +d181 1 +a181 1 + setbits(&res->set[CAP_EFFECTIVE], &list); +d183 1 +a183 1 + setbits(&res->set[CAP_INHERITABLE], &list); +d185 1 +a185 1 + setbits(&res->set[CAP_PERMITTED], &list); +d190 1 +a190 1 + clrbits(&res->set[CAP_EFFECTIVE], &list); +d192 1 +a192 1 + clrbits(&res->set[CAP_INHERITABLE], &list); +d194 1 +a194 1 + clrbits(&res->set[CAP_PERMITTED], &list); +d229 1 +a229 1 + if (caps->set[CAP_EFFECTIVE]._cap_raised(capno)) +d231 1 +a231 1 + if (caps->set[CAP_INHERITABLE]._cap_raised(capno)) +d233 1 +a233 1 + if (caps->set[CAP_PERMITTED]._cap_raised(capno)) +d254 3 +a256 3 + _cap_debugcap("e = ", &caps->set[CAP_EFFECTIVE]); + _cap_debugcap("i = ", &caps->set[CAP_INHERITABLE]); + _cap_debugcap("p = ", &caps->set[CAP_PERMITTED]); +d306 1 +a306 1 + return buf; +d311 3 +@ + + +1.2 +log +@zefram's replacement file with a number of bug fixes from AGM +@ +text +@d2 1 +a2 1 + * $Id: cap_text.c,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +a146 1 + case 'E': +a149 1 + case 'I': +a152 1 + case 'P': +d306 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +d5 1 +d16 1 +d18 2 +a19 64 +/* + * Some static data: + */ + +/* A place to store the capability names */ +static const char * cap_text[__CAP_BITS] = { + +/* + * POSIX capabilities + */ + +/* CAP_CHOWN (0) */ "cap_chown", +/* CAP_DAC_OVERRIDE */ "cap_dac_override", +/* CAP_DAC_READ_SEARCH */ "cap_dac_read_search", +/* CAP_FOWNER */ "cap_fowner", +/* CAP_FSETID */ "cap_fsetid", +/* CAP_KILL (5) */ "cap_kill", +/* CAP_LINK_DIR */ "cap_link_dir", +/* CAP_SETFCAP */ "cap_setfcap", +/* CAP_SETGID */ "cap_setgid", +/* CAP_SETUID */ "cap_setuid", +/* CAP_SIGMASK (10) */ "cap_sigmask", + +/* CAP_MAC_DOWNGRADE (11) */ "cap_mac_downgrade", +/* CAP_MAC_READ */ "cap_mac_read", +/* CAP_MAC_RELABEL_SUB */ "cap_mac_relabel_sub", +/* CAP_MAC_UPGRADE */ "cap_mac_upgrade", +/* CAP_MAC_WRITE */ "cap_mac_write", + +/* CAP_INF_NOFLOAT_OBJ (16) */ "cap_inf_nofloat_obj", +/* CAP_INF_NOFLOAT_SUB */ "cap_inf_nofloat_lab", +/* CAP_INF_RELABEL_OBJ */ "cap_inf_relabel_obj", +/* CAP_INF_RELABEL_SUB */ "cap_inf_relabel_sub", + +/* CAP_AUDIT_CONTROL (20) */ "cap_audit_control", +/* CAP_AUDIT_WRITE */ "cap_audit_write", + +/* (22) reserved for POSIX */ NULL, +/* (23) reserved for POSIX */ NULL, +/* (24) reserved for POSIX */ NULL, +/* (25) reserved for POSIX */ NULL, +/* (26) reserved for POSIX */ NULL, +/* (27) reserved for POSIX */ NULL, +/* (28) reserved for POSIX */ NULL, +/* (29) reserved for POSIX */ NULL, +/* (30) reserved for POSIX */ NULL, +/* (31) reserved for POSIX */ NULL, + +/* + * Linux-specific capabilities + */ + +/* CAP_LINUX_IMMUTABLE (32) */ "cap_linux_immutable", +/* CAP_LINUX_KERNELD */ "cap_linux_kerneld", +/* CAP_LINUX_INSMOD */ "cap_linux_insmod", +/* CAP_LINUX_RMMOD */ "cap_linux_rmmod", +/* CAP_LINUX_RAWIO */ "cap_linux_rawio", +/* CAP_LINUX_ATTENTION */ "cap_linux_attention", +/* CAP_LINUX_RANDOM */ "cap_linux_random", + +/* + * Others.. A number of others have been defined; they do not belong + * to Linux or POSIX. [Subject to change]. + */ +d21 3 +a23 24 +/* CAP_NET_BIND_SERVICE (39) */ "cap_net_bind_service", +/* CAP_NET_BROADCAST */ "cap_net_broadcast", +/* CAP_NET_DEBUG */ "cap_net_debug", +/* CAP_NET_FIREWALL */ "cap_net_firewall", +/* CAP_NET_IFCONFIG */ "cap_net_ifconfig", +/* CAP_NET_PACKET */ "cap_net_packet", +/* CAP_NET_RAW (45) */ "cap_net_raw", +/* CAP_NET_ROUTE */ "cap_net_route", +/* CAP_NET_SETID */ "cap_net_setid", +/* CAP_IPC_LOCK */ "cap_ipc_lock", +/* CAP_IPC_OWNER */ "cap_ipc_owner", +/* CAP_SYS_CHROOT (50) */ "cap_sys_chroot", +/* CAP_SYS_PTRACE */ "cap_sys_ptrace", +/* CAP_SYS_ACCOUNT */ "cap_sys_account", +/* CAP_SYS_ADMIN */ "cap_sys_admin", +/* CAP_SYS_BOOT */ "cap_sys_boot", +/* CAP_SYS_DEVICES (55) */ "cap_sys_devices", +/* CAP_SYS_NICE */ "cap_sys_nice", +/* CAP_SYS_RESOURCE */ "cap_sys_resource", +/* CAP_SYS_TIME */ "cap_sys_time", +/* CAP_SYS_TTY_CONFIG */ "cap_sys_tty_config", +/* CAP_SYS_QUOTA (60) */ "cap_sys_quota", + +}; +d26 2 +a27 1 + * static parsing routines +d30 1 +a30 6 +/* + * Caseless string comparison + */ + +/* caseless string comparison: POSIX does not define this.. */ +static int _strCMP(const char *s, const char *t) +d32 3 +a34 8 + int cf; + + do { + cf = tolower(*s) - tolower(*t); + ++t; + } while (!cf && *s++); + + return cf; +d37 1 +a37 21 +/* + * Locate character (c) in an array of characters (array) + */ + +static int _cap_inarray(char c, const char * array) +{ + int i; + + for (i=0; *array; ++array, ++i) { + if (c == *array) + return i; + } + + return -1; +} + +/* + * Locate a token (tok) in an capability array + */ + +static int _cap_find_token(const char * const tok) +d39 3 +a41 9 + int i; + + for (i=0; i<__CAP_BITS; ++i) { + if (cap_text[i] && !_strCMP(cap_text[i], tok)) { + _cap_debug("located [%s]=%d", cap_text[i], i); + return i; + } + } + return -1; +d44 1 +a44 5 +/* + * This function copies the next clause (returning NULL at end) + */ + +static const char *_cap_get_clause(const char *from, char **to) +d46 3 +a48 6 + const char *begin; + + /* forget last value */ + if (*to) { + free(*to); + *to = NULL; +d50 1 +a50 3 + + /* verify that we have something to search */ + if (from == NULL) { +d52 1 +a52 26 + } + + /* skip leading spaces */ + for (; *from && isspace(*from); ++from); + + /* do we have a clause? */ + if (*from) { + int length; + + /* Skip to next space */ + for (begin = from; *from && !isspace(*from); ++from); + + length = from - begin; + *to = malloc(1 + length); + if (*to == NULL) { + _cap_debug("out of memory"); + errno = ENOMEM; + return NULL; + } + + /* copy clause */ + memcpy(*to, begin, length); + (*to)[length] = '\0'; + } + + return (*from ? from:NULL); +d55 1 +a55 8 +/* + * Read comma separated capabilities and set them in the argument capability + * set. + */ + +static const char * const op_list = "=+-"; + +static char *_cap_parse_caps(char *temp, __cap_s *caps) +d57 7 +a63 21 + char *ops, saved; + const char *tok; + + if (temp == NULL) { + _cap_debug("no capabilities provided"); + return NULL; + } + + /* find first non-capability char (=+-) and save for later writeback */ + for (ops=temp; (saved=*ops) && _cap_inarray(saved, op_list) < 0; ++ops); + *ops = '\0'; + + /* loop through tokens looking up each capability and raising it in caps */ + if (!_strCMP("all", temp)) { + int i; + + /* A little slow but this way we only raise defined capabilities */ + for (i=0; i<__CAP_BITS; ++i) { + if (cap_text[i]) + caps->_cap_raise(i); + } +d65 6 +a70 11 + /* break string into tokens */ + while ((tok = strtok(temp, ","))) { + int cap; + + temp = NULL; + + cap = _cap_find_token(tok); + if (cap == -1) { + _cap_debug("tok=[%s] is not known - ignoring it", tok); + } else { + caps->_cap_raise(cap); +d72 1 +a72 22 + } + } + + /* writeback first operator char */ + *ops = saved; + + /* return operator list */ + return ops; +} + +/* + * read the operator list and set the internal flags accordingly + */ + +static struct __cap_s cap_purge(const struct __cap_s *a, + const struct __cap_s *b) +{ + struct __cap_s result; + register i; + + for (i=0; i<__CAP_BLKS; ++i) { + result._blk[i] = a->_blk[i] & ~b->_blk[i]; +a73 1 + return result; +d76 1 +a76 2 +static struct __cap_s cap_union(const struct __cap_s *a, + const struct __cap_s *b) +d78 3 +a80 2 + struct __cap_s result; + register i; +d82 4 +a85 2 + for (i=0; i<__CAP_BLKS; ++i) { + result._blk[i] = a->_blk[i] | b->_blk[i]; +a86 2 + return result; +} +d88 20 +a107 3 +#define _LIBCAP_EQ 01 +#define _LIBCAP_PL 02 +#define _LIBCAP_MI 03 +d109 16 +a124 38 +static void _cap_parse_ops(char *temp, __cap_s *caps, cap_t cap_d) +{ + unsigned int state=0; + char c; + + while ((c = *temp++)) { + int op; + + /* Is this an operator? */ + if ((op = _cap_inarray(c, op_list)) >= 0) { + c = '\0'; + state = 1+op; + if (*temp && _cap_inarray(*temp, op_list) < 0) + continue; + /* Fall through for immediate action */ + } + switch (c) { + case '\0': + switch ((state & 03)) { + case _LIBCAP_EQ: + memset(&(cap_d->set), 0, 3*sizeof(__cap_s)); + break; + case _LIBCAP_PL: + cap_d->set[CAP_EFFECTIVE] + = cap_union(&cap_d->set[CAP_EFFECTIVE], caps); + cap_d->set[CAP_INHERITABLE] + = cap_union(&cap_d->set[CAP_EFFECTIVE], caps); + cap_d->set[CAP_PERMITTED] + = cap_union(&cap_d->set[CAP_EFFECTIVE], caps); + break; + case _LIBCAP_MI: + cap_d->set[CAP_EFFECTIVE] + = cap_purge(&cap_d->set[CAP_EFFECTIVE], caps); + cap_d->set[CAP_INHERITABLE] + = cap_purge(&cap_d->set[CAP_EFFECTIVE], caps); + cap_d->set[CAP_PERMITTED] + = cap_purge(&cap_d->set[CAP_EFFECTIVE], caps); + break; +d126 38 +a163 15 + break; + case 'e': + case 'E': /* set effective caps */ + switch ((state & 03)) { + case _LIBCAP_EQ: + memset(&(cap_d->set[CAP_EFFECTIVE]), 0, sizeof(__cap_s)); + break; + case _LIBCAP_PL: + cap_d->set[CAP_EFFECTIVE] + = cap_union(&cap_d->set[CAP_EFFECTIVE], caps); + break; + case _LIBCAP_MI: + cap_d->set[CAP_EFFECTIVE] + = cap_purge(&cap_d->set[CAP_EFFECTIVE], caps); + break; +d165 28 +a192 14 + break; + case 'i': + case 'I': + switch ((state & 03)) { + case _LIBCAP_EQ: + memset(&(cap_d->set[CAP_INHERITABLE]), 0, sizeof(__cap_s)); + break; + case _LIBCAP_PL: + cap_d->set[CAP_INHERITABLE] + = cap_union(&cap_d->set[CAP_INHERITABLE], caps); + break; + case _LIBCAP_MI: + cap_d->set[CAP_INHERITABLE] + = cap_purge(&cap_d->set[CAP_INHERITABLE], caps); +d195 11 +a205 15 + break; + case 'p': + case 'P': + switch ((state & 03)) { + case _LIBCAP_EQ: + memset(&(cap_d->set[CAP_PERMITTED]), 0, sizeof(__cap_s)); + break; + case _LIBCAP_PL: + cap_d->set[CAP_PERMITTED] + = cap_union(&cap_d->set[CAP_PERMITTED], caps); + break; + case _LIBCAP_MI: + cap_d->set[CAP_PERMITTED] + = cap_purge(&cap_d->set[CAP_PERMITTED], caps); + break; +d207 2 +a208 4 + break; + default: + _cap_debug("[%c] is ignored", c); + } +d210 5 +d218 3 +a220 1 + * Convert a textual representation to a capability set. +d223 1 +a223 1 +cap_t cap_from_text(const char *verbose) +d225 1 +a225 29 + char *clause=NULL; + cap_t cap_d; + + cap_d = cap_init(); + if (cap_d == NULL) { + _cap_debug("out of memory"); + errno = ENOMEM; + return NULL; + } + + /* Loop through clauses */ + while ((verbose = _cap_get_clause(verbose, &clause))) { + struct __cap_s capabilities; + char *temp = clause; + + /* reset local capability set */ + memset(&capabilities, 0, sizeof(capabilities)); + + /* spin through capabilities listed in this clause */ + temp = _cap_parse_caps(temp, &capabilities); + if (temp) { + /* spin through list of operators? */ + _cap_parse_ops(temp, &capabilities, cap_d); + } + } + + /* return the capability set */ + return cap_d; +} +d227 6 +a232 4 +static int count_bits(struct __cap_s *cap) +{ + register int i,count=0; + register __u32 block=0; +d234 1 +a234 6 + for (i=0; i<__CAP_BLKS; ++i) { + for (block = cap->_blk[i]; block; block >>= 1) { + count += (block&1); + } + } + return count; +a236 10 +/* + * 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. + */ + +#define _LIBCAP_EFF 01 +#define _LIBCAP_INH 02 +#define _LIBCAP_PER 04 + +d239 1 +a239 1 +char *cap_to_text(cap_t cap_d, ssize_t *length_p) +a240 2 + int mone, moni, monp; + unsigned int persist; +d242 3 +a244 1 + int length, i; +d247 1 +a247 1 + if (!good_cap_t(cap_d) || length_p == NULL) { +d252 30 +a281 44 + mone = (count_bits(&cap_d->set[CAP_EFFECTIVE]) > 16) ? 1:0; + moni = (count_bits(&cap_d->set[CAP_INHERITABLE]) > 16) ? 1:0; + monp = (count_bits(&cap_d->set[CAP_PERMITTED]) > 16) ? 1:0; + + *length_p = 0; + length = sprintf(buf, "all%se%si%sp\n", + mone ? "+":"-", + moni ? "+":"-", + monp ? "+":"-" ); + + /* loop through clustering together all caps that are stored in + the same selection of sets.. */ + for (persist=0, i=0; i<=__CAP_BITS; ++i) { + unsigned int this=0; + + /* Which have this capability set? */ + if (i != __CAP_BITS) { + if ((!mone && cap_d->set[CAP_EFFECTIVE]._cap_raised(i)) + || (mone && !cap_d->set[CAP_EFFECTIVE]._cap_raised(i))) + this |= _LIBCAP_EFF; + if ((!moni && cap_d->set[CAP_INHERITABLE]._cap_raised(i)) + || (moni && !cap_d->set[CAP_INHERITABLE]._cap_raised(i))) + this |= _LIBCAP_INH; + if ((!monp && cap_d->set[CAP_PERMITTED]._cap_raised(i)) + || (monp && !cap_d->set[CAP_PERMITTED]._cap_raised(i))) + this |= _LIBCAP_PER; + } else + this = ~0; + + /* should we include this capability? */ + if (this) { + if (persist && (i == __CAP_BITS || this != persist)) { + /* write out actionlist for persistent caps */ + length += sprintf(length+buf, "%s%s%s\n" + , (persist & _LIBCAP_EFF) ? + (mone?"-e":"+e"):"" + , (persist & _LIBCAP_INH) ? + (moni?"-i":"+i"):"" + , (persist & _LIBCAP_PER) ? + (monp?"-p":"+p"):"" + ); + if (length > CAP_TEXT_SIZE) { + errno = ERANGE; + return NULL; +d283 14 +a296 15 + persist=0; + } + if (i == __CAP_BITS) { + /* All done */ + break; + } + + if (cap_text[i]) { + length += sprintf(length+buf, "%s%s", persist? ",":"" + , cap_text[i]); + } else { + _cap_debug("cap [%d] not defined but is set!?", i); + length += sprintf(length+buf, "%s(%d)", persist?",":"", i); + } + if (length > CAP_TEXT_SIZE) { +a299 3 + + /* we may have a new persistent combination */ + persist = this; +a300 3 + } + + /* return text */ +d302 2 +a303 1 + *length_p = strlen(buf); +d308 4 +a311 1 + * $Log$ +@ diff --git a/libcap/RCS/libcap.h,v b/libcap/RCS/libcap.h,v new file mode 100644 index 0000000..dc70111 --- /dev/null +++ b/libcap/RCS/libcap.h,v @@ -0,0 +1,287 @@ +head 1.5; +access; +symbols; +locks; strict; +comment @ * @; + + +1.5 +date 98.06.08.00.15.28; author morgan; state Exp; +branches; +next 1.4; + +1.4 +date 98.06.07.15.58.23; author morgan; state Exp; +branches; +next 1.3; + +1.3 +date 98.05.24.22.54.09; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.57.11; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.32.52; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.5 +log +@accommodate alpha (glibc?) +@ +text +@/* + * $Id: libcap.h,v 1.4 1998/06/07 15:58:23 morgan Exp morgan $ + * + * Copyright (c) 1997 Andrew G Morgan <morgan@@linux.kernel.org> + * + * See end of file for Log. + * + * This file contains internal definitions for the various functions in + * this small capability library. + */ + +#ifndef LIBCAP_H +#define LIBCAP_H + +#include <sys/types.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/capability.h> + +/* include the names for the caps and a definition of __CAP_BITS */ +#include "cap_names.h" + +/* + * 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. + */ + +#define CAP_T_MAGIC 0xCA90D0 +struct _cap_struct { + int magic; + struct __user_cap_header_struct head; + struct __user_cap_data_struct set; +}; + +/* + * Do we match the local kernel? + */ + +#if !defined(_LINUX_CAPABILITY_VERSION) || \ + (_LINUX_CAPABILITY_VERSION != 0x19980330) + +# error "Kernel <linux/capability.h> does not match library" +# error "file "libcap.h" --> fix and recompile libcap" + +#endif + +/* + * kernel API cap set abstraction + */ + +#define NUMBER_OF_CAP_SETS 3 /* effective, inheritable, permitted */ +#define CAP_SET_SIZE (sizeof(struct __user_cap_data_struct)/NUMBER_OF_CAP_SETS) +#define __CAP_BLKS (CAP_SET_SIZE/sizeof(__u32)) +typedef struct { + __u32 _blk[__CAP_BLKS]; +} __cap_s; +#define raise_cap(x) _blk[(x)>>5] |= (1<<((x)&31)) +#define lower_cap(x) _blk[(x)>>5] |= (1<<((x)&31)) +#define isset_cap(y,x) ((y)->_blk[(x)>>5] & (1<<((x)&31))) + +/* + * Private definitions for internal use by the library. + */ + +#define good_cap_t(c) ((c) && (c)->magic == CAP_T_MAGIC) + +/* + * library debugging + */ +#ifdef DEBUG + +#include <stdio.h> +# define _cap_debug(f, x...) { \ + fprintf(stderr, __FUNCTION__ "(" __FILE__ ":%d): ", __LINE__); \ + fprintf(stderr, f, ## x); \ + fprintf(stderr, "\n"); \ +} +# define _cap_debugcap(s, c) \ + fprintf(stderr, __FUNCTION__ "(" __FILE__ ":%d): " s \ + "%08x\n", __LINE__, c) + +#else /* !DEBUG */ + +# define _cap_debug(f, x...) +# define _cap_debugcap(s, c) + +#endif /* DEBUG */ + +/* + * 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); + +#endif /* LIBCAP_H */ + +/* + * $Log: libcap.h,v $ + * Revision 1.4 1998/06/07 15:58:23 morgan + * accommodate real kernel header files :*) + * + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * zefram's replacement file with a number of bug fixes from AGM + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ +@ + + +1.4 +log +@accommodate real kernel header files :*) +@ +text +@d2 1 +a2 1 + * $Id: libcap.h,v 1.3 1998/05/24 22:54:09 morgan Exp morgan $ +d15 1 +d110 3 +@ + + +1.3 +log +@updated for 2.1.104 +@ +text +@d2 1 +a2 1 + * $Id: libcap.h,v 1.2 1997/04/28 00:57:11 morgan Exp morgan $ +d36 2 +a37 2 + struct _user_cap_header_struct head; + struct _user_cap_data_struct set; +d57 1 +a57 1 +#define CAP_SET_SIZE (sizeof(struct _user_cap_data_struct)/NUMBER_OF_CAP_SETS) +d109 3 +@ + + +1.2 +log +@zefram's replacement file with a number of bug fixes from AGM +@ +text +@d2 1 +a2 1 + * $Id: libcap.h,v 1.1 1997/04/21 04:32:52 morgan Exp morgan $ +d4 1 +a4 1 + * Copyright (c) 1997 Andrew G Morgan <morgan@@parc.power.net> +d21 3 +d36 2 +a37 1 + struct __cap_s set[3]; +d45 1 +a45 1 + (_LINUX_CAPABILITY_VERSION != 0x19970420) +d53 14 +d85 1 +a85 2 + "%08x %08x %08x %08x\n", __LINE__, \ + (c)->_blk[0], (c)->_blk[1], (c)->_blk[2], (c)->_blk[3]) +d100 4 +a103 10 +int _setproccap(size_t, __cap_s const *,__cap_s const *, __cap_s const *); +int _getproccap(size_t, __cap_s *,__cap_s *, __cap_s *); +int _setfilecap(char const *, size_t, __cap_s const *, + __cap_s const *, __cap_s const *); +int _getfilecap(char const *, size_t, __cap_s *, __cap_s *, __cap_s *); +int _fsetfilecap(int, size_t, __cap_s const *, + __cap_s const *, __cap_s const *); +int _fgetfilecap(int, size_t, __cap_s *, __cap_s *, __cap_s *); + +extern char const *_cap_names[__CAP_BITS]; +d109 3 +@ + + +1.1 +log +@Initial revision +@ +text +@d2 1 +a2 1 + * $Id$ +d19 1 +a19 2 + +#include <linux/capability.h> +d22 1 +a22 1 + * This is a pointer to an struct containing three consecutive +a47 8 +#include <sys/capability.h> + +/* + * System calls + */ + +#include <linux/unistd.h> + +d63 1 +a63 1 + fprintf(stderr, "\n"); +d65 4 +d73 1 +d77 5 +a81 2 +/* These are semi-public prototypes -- perhaps they should be moved to + <sys/capability.h> ? */ +d84 1 +a84 1 +int _getproccap(size_t, __cap_s const *,__cap_s const *, __cap_s const *); +d87 1 +a87 2 +int _getfilecap(char const *, size_t, __cap_s const *, + __cap_s const *, __cap_s const *); +d90 3 +a92 2 +int _fgetfilecap(int, size_t, __cap_s const *, + __cap_s const *, __cap_s const *); +d97 4 +a100 1 + * $Log$ +@ diff --git a/libcap/_makenames.c b/libcap/_makenames.c new file mode 100644 index 0000000..5ef7192 --- /dev/null +++ b/libcap/_makenames.c @@ -0,0 +1,79 @@ +/* + * $Id: _makenames.c,v 1.4 1998/06/07 15:50:12 morgan Exp $ + * + * Copyright (c) 1997-8 Andrew G. Morgan <morgan@linux.kernel.org> + * + * This is a file to make the capability <-> string mappings for + * libcap. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <linux/capability.h> + +/* + * #include 'sed' generated array + */ + +struct { + int index; + const char *name; +} const list[] = { +#include "cap_names.sed" + {-1, NULL} +}; + +/* 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; + } + 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); +} + +/* + * $Log: _makenames.c,v $ + * Revision 1.4 1998/06/07 15:50:12 morgan + * updated to accommodate kernel's real header file :*) + * + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/05/04 05:35:46 morgan + * cleaned up to #include sed output. also generates whole cap_names.c file + * + * Revision 1.1 1997/04/28 00:57:11 morgan + * Initial revision + * + */ diff --git a/libcap/cap_alloc.c b/libcap/cap_alloc.c new file mode 100644 index 0000000..3d9e7ab --- /dev/null +++ b/libcap/cap_alloc.c @@ -0,0 +1,90 @@ +/* + * $Id: cap_alloc.c,v 1.3 1998/05/24 22:54:09 morgan Exp $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with allocation and deallocation of internal + * capability sets as specified by POSIX.1e (formerlly, POSIX 6). + */ + +#include "libcap.h" + +/* + * This function duplicates an internal capability set (x3) 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_t) malloc( sizeof(*cap_d) ); + if (result == NULL) { + _cap_debug("out of memory"); + errno = ENOMEM; + return NULL; + } + + memcpy(result, cap_d, sizeof(*cap_d)); + + return result; +} + + +/* + * Scrub and then liberate an internal capability set. + */ + +int cap_free(cap_t *cap_d_p) +{ + if ( cap_d_p && good_cap_t(*cap_d_p) ) { + memset(*cap_d_p, 0, sizeof(**cap_d_p)); + free(*cap_d_p); + *cap_d_p = NULL; + + return 0; + } else { + _cap_debug("no capability to liberate"); + errno = EINVAL; + return -1; + } +} + +/* + * Obtain a blank set of capabilities + */ + +cap_t cap_init(void) +{ + cap_t result = (cap_t) calloc( 1, sizeof(*result) ); + + if (result) { + result->magic = CAP_T_MAGIC; + result->head.version = _LINUX_CAPABILITY_VERSION; + } else { + errno = ENOMEM; + } + return result; +} + +/* + * $Log: cap_alloc.c,v $ + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ diff --git a/libcap/cap_extint.c b/libcap/cap_extint.c new file mode 100644 index 0000000..5f17f2c --- /dev/null +++ b/libcap/cap_extint.c @@ -0,0 +1,142 @@ +/* + * $Id: cap_extint.c,v 1.3 1998/05/24 22:54:09 morgan Exp $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with exchanging internal and external + * representations of capability sets. + */ + +#include "libcap.h" + +/* + * External representation for capabilities. (exported as a fixed + * length (void *)) + */ +#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; + __u32 *from = (__u32 *) &(cap_d->set); + 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 = *from++; + + 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(). + */ + +/* + * XXX - need to take a little more care when importing small + * capability sets. + */ + +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; + __u32 * to = (__u32 *) &cap_d->set; + + /* 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/4); ++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; + + *to++ = val; + } + } + + /* all done */ + return cap_d; +} + +/* + * $Log: cap_extint.c,v $ + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ diff --git a/libcap/cap_file.c b/libcap/cap_file.c new file mode 100644 index 0000000..0cb4114 --- /dev/null +++ b/libcap/cap_file.c @@ -0,0 +1,117 @@ +/* + * $Id: cap_file.c,v 1.5 1998/05/24 22:54:09 morgan Exp $ + * + * Copyright (c) 1997 Andrew G Morgan <morgan@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with setting capabilities on files. + */ + +#include "libcap.h" + +/* + * 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) { + _cap_debug("getting fildes capabilities"); + + /* fill the capability sets via a system call */ + if (_fgetfilecap(fildes, sizeof(struct __cap_s), + &result->set[CAP_INHERITABLE], + &result->set[CAP_PERMITTED], + &result->set[CAP_EFFECTIVE] )) { + cap_free(&result); + } + } + + return result; +} + +/* + * Set the capabilities on a named file. + */ + +cap_t cap_get_file(const char *filename) +{ + cap_t result; + + /* allocate a new capability set */ + result = cap_init(); + if (result) { + _cap_debug("getting named file capabilities"); + + /* fill the capability sets via a system call */ + if (_getfilecap(filename, sizeof(struct __cap_s), + &result->set[CAP_INHERITABLE], + &result->set[CAP_PERMITTED], + &result->set[CAP_EFFECTIVE] )) + cap_free(&result); + } + + 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) +{ + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting fildes capabilities"); + return _fsetfilecap(fildes, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +} + +/* + * Set the capabilities of a named file. + */ + +int cap_set_file(const char *filename, cap_t cap_d) +{ + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting filename capabilities"); + return _setfilecap(filename, sizeof(struct __cap_s), + &cap_d->set[CAP_INHERITABLE], + &cap_d->set[CAP_PERMITTED], + &cap_d->set[CAP_EFFECTIVE] ); +} + +/* + * $Log: cap_file.c,v $ + * Revision 1.5 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.4 1997/05/14 05:17:13 morgan + * bug-fix from zefram (errno no set on success) + * + * Revision 1.3 1997/05/04 05:35:46 morgan + * fixed errno setting. syscalls do this part + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ diff --git a/libcap/cap_flag.c b/libcap/cap_flag.c new file mode 100644 index 0000000..7d8f967 --- /dev/null +++ b/libcap/cap_flag.c @@ -0,0 +1,122 @@ +/* + * $Id: cap_flag.c,v 1.4 1998/09/20 23:07:59 morgan Exp $ + * + * Copyright (c) 1997-8 Andrew G. Morgan <morgan@linux.kernel.org> + * + * See end of file for Log. + * + * 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) { + __cap_s *cap_p = (__cap_s *) (set*CAP_SET_SIZE + + (__u8 *) &cap_d->set); + + *raised = isset_cap(cap_p,value) ? 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, 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]; + __cap_s *cap_p = (__cap_s *) (set*CAP_SET_SIZE + + (__u8 *) &cap_d->set); + + if (raise == CAP_SET) { + cap_p->raise_cap(value); + } else { + cap_p->lower_cap(value); + } + } + } + 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->set), 0, sizeof(cap_d->set)); + return 0; + + } else { + + _cap_debug("invalid pointer"); + errno = EINVAL; + return -1; + + } +} + +/* + * $Log: cap_flag.c,v $ + * Revision 1.4 1998/09/20 23:07:59 morgan + * fixed lower bound check on 'set'. + * + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c new file mode 100644 index 0000000..35c640c --- /dev/null +++ b/libcap/cap_proc.c @@ -0,0 +1,100 @@ +/* + * $Id: cap_proc.c,v 1.5 1998/05/24 22:54:09 morgan Exp $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@linux.kernel.org> + * + * See end of file for Log. + * + * This file deals with setting capabilities on processes. + */ + +#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->set)) { + cap_free(&result); + } + } + + return result; +} + +int cap_set_proc(cap_t cap_d) +{ + if (!good_cap_t(cap_d)) { + errno = EINVAL; + return -1; + } + + _cap_debug("setting process capabilities"); + return capset(&cap_d->head, &cap_d->set); +} + +/* 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->set); + cap_d->head.pid = 0; + + return error; +} + +/* 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->set); + cap_d->head.pid = 0; + + return error; +} + +/* + * $Log: cap_proc.c,v $ + * Revision 1.5 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.4 1997/05/14 05:17:13 morgan + * bug-fix from zefram (errno no set on success) + * + * Revision 1.3 1997/05/04 05:35:46 morgan + * fixed errno setting. syscalls do this part + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ diff --git a/libcap/cap_sys.c b/libcap/cap_sys.c new file mode 100644 index 0000000..896f5f2 --- /dev/null +++ b/libcap/cap_sys.c @@ -0,0 +1,36 @@ +/* + * $Id: cap_sys.c,v 1.4 1998/06/08 00:14:01 morgan Exp $ + * + * Copyright (c) 1997-8 Andrew G. Morgan <morgan@linux.kernel.org> + * + * This file contains the system calls for getting and setting + * capabilities + */ + +#include "libcap.h" +#define __LIBRARY__ +#include <linux/unistd.h> + +_syscall2(int, capget, + cap_user_header_t, header, + cap_user_data_t, data) + +_syscall2(int, capset, + cap_user_header_t, header, + const cap_user_data_t, data) + +/* + * $Log: cap_sys.c,v $ + * Revision 1.4 1998/06/08 00:14:01 morgan + * change to accommodate alpha (glibc?) + * + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * fixes and zefram's patches + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ diff --git a/libcap/cap_text.c b/libcap/cap_text.c new file mode 100644 index 0000000..53b51d0 --- /dev/null +++ b/libcap/cap_text.c @@ -0,0 +1,323 @@ +/* + * $Id: cap_text.c,v 1.4 1998/05/24 22:54:09 morgan Exp $ + * + * Copyright (c) 1997-8 Andrew G Morgan <morgan@linux.kernel.org> + * Copyright (c) 1997 Andrew Main <zefram@dcs.warwick.ac.uk> + * + * See end of file for Log. + * + * This file deals with exchanging internal and textual + * representations of capability sets. + */ + +#define LIBCAP_PLEASE_INCLUDE_ARRAY +#include "libcap.h" + +#include <ctype.h> +#include <stdio.h> + +char *strdup(const char *s); + +/* Maximum output text length (16 per cap) */ +#define CAP_TEXT_SIZE (16*__CAP_BITS) + +#define LIBCAP_EFF 01 +#define LIBCAP_INH 02 +#define LIBCAP_PER 04 + +/* + * Parse a textual representation of capabilities, returning an internal + * representation. + */ + +#define setbits(A,B) _setbits((__cap_s *)A, (__cap_s *)B) +static void _setbits(__cap_s *a, __cap_s *b) +{ + int n; + for (n = __CAP_BLKS; n--; ) + a->_blk[n] |= b->_blk[n]; +} + +#define clrbits(A,B) _clrbits((__cap_s *)A, (__cap_s *)B) +static void _clrbits(__cap_s *a, __cap_s *b) +{ + int n; + for (n = __CAP_BLKS; n--; ) + a->_blk[n] &= ~b->_blk[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 int lookupname(char const **strp) +{ + char const *str = *strp; + if (isdigit(*str)) { + unsigned long n = strtoul(str, (char **)&str, 0); + if (n >= __CAP_BITS) + return -1; + *strp = str; + return n; + } else { + char const *s; + int n; + for (n = __CAP_BITS; n--; ) + if (_cap_names[n] && (s = namcmp(str, _cap_names[n]))) { + *strp = s; + return n; + } + return -1; + } +} + +cap_t cap_from_text(const char *str) +{ + cap_t res; + __cap_s allones; + int n; + + if (str == NULL) { + _cap_debug("bad argument"); + errno = EINVAL; + return NULL; + } + + if (!(res = cap_init())) + return NULL; + for (n = __CAP_BLKS; n--; ) + allones._blk[n] = -1; + _cap_debug("%s", str); + + for (;;) { + char op; + int flags = 0, listed=0; + __cap_s list = {{0}}; + + /* skip leading spaces */ + while (isspace((unsigned char)*str)) + str++; + if (!*str) { + _cap_debugcap("e = ", &res->set.effective); + _cap_debugcap("i = ", &res->set.inheritable); + _cap_debugcap("p = ", &res->set.permitted); + return res; + } + + /* identify caps specified by this clause */ + if (isalnum((unsigned char)*str) || *str == '_') { + for (;;) { + if (namcmp(str, "all")) { + str += 3; + list = allones; + } else { + n = lookupname(&str); + if (n == -1) + goto bad; + list.raise_cap(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 + list = allones; + + /* 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->set.effective, &list); + clrbits(&res->set.inheritable, &list); + clrbits(&res->set.permitted, &list); + /* fall through */ + if (op == 'M') + goto minus; + case '+': + if (flags & LIBCAP_EFF) + setbits(&res->set.effective, &list); + if (flags & LIBCAP_INH) + setbits(&res->set.inheritable, &list); + if (flags & LIBCAP_PER) + setbits(&res->set.permitted, &list); + break; + case '-': + minus: + if (flags & LIBCAP_EFF) + clrbits(&res->set.effective, &list); + if (flags & LIBCAP_INH) + clrbits(&res->set.inheritable, &list); + if (flags & LIBCAP_PER) + clrbits(&res->set.permitted, &list); + 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); + errno = EINVAL; + return NULL; +} + +/* + * 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((__cap_s *)(&caps->set.effective),capno)) + f |= LIBCAP_EFF; + if (isset_cap((__cap_s *)(&caps->set.inheritable),capno)) + f |= LIBCAP_INH; + if (isset_cap((__cap_s *)(&caps->set.permitted),capno)) + f |= LIBCAP_PER; + + return f; +} + +#define CAP_TEXT_BUFFER_ZONE 100 + +char *cap_to_text(cap_t caps, ssize_t *length_p) +{ + static char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE]; + char *p; + int histo[8] = {0}; + int m, n, t; + + /* Check arguments */ + if (!good_cap_t(caps) || length_p == NULL) { + errno = EINVAL; + return NULL; + } + + _cap_debugcap("e = ", &caps->set.effective); + _cap_debugcap("i = ", &caps->set.inheritable); + _cap_debugcap("p = ", &caps->set.permitted); + + for (n = __CAP_BITS; n--; ) + histo[getstateflags(caps, n)]++; + + for (m=t=7; t--; ) + if (histo[t] > histo[m]) + m = t; + + /* 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_BITS; n++) + if (getstateflags(caps, n) == t) { + if (_cap_names[n]) + p += sprintf(p, "%s,", _cap_names[n]); + else + p += sprintf(p, "%d,", n); + if (p - buf > CAP_TEXT_SIZE) { + errno = ERANGE; + return NULL; + } + } + 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); + *length_p = p - buf; + return (strdup(buf)); +} + +/* + * $Log: cap_text.c,v $ + * Revision 1.4 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.3 1997/05/04 05:37:00 morgan + * case sensitvity to capability flags + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * zefram's replacement file with a number of bug fixes from AGM + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ diff --git a/libcap/include/sys/RCS/capability.h,v b/libcap/include/sys/RCS/capability.h,v new file mode 100644 index 0000000..3e65886 --- /dev/null +++ b/libcap/include/sys/RCS/capability.h,v @@ -0,0 +1,197 @@ +head 1.3; +access; +symbols; +locks; strict; +comment @ * @; + + +1.3 +date 98.05.24.22.53.05; author morgan; state Exp; +branches; +next 1.2; + +1.2 +date 97.04.28.00.56.38; author morgan; state Exp; +branches; +next 1.1; + +1.1 +date 97.04.21.04.33.43; author morgan; state Exp; +branches; +next ; + + +desc +@first take +@ + + +1.3 +log +@updated for 2.1.104 +@ +text +@/* + * <sys/capability.h> + * + * + * Copyright (C) 1997 Aleph One + * Copyright (C) 1997-8 Andrew G. Morgan <morgan@@linux.kernel.org> + * + * POSIX.1e Standard: 25.2 Capabilities <sys/capability.h> + */ + +#ifndef _SYS_CAPABILITY_H +#define _SYS_CAPABILITY_H + +/* + * This file complements the kernel file by providing prototype + * information for the user library. + */ + +#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 */ +cap_t cap_dup(cap_t); +int cap_free(cap_t *); +cap_t cap_init(void); + +/* libcap/cap_flag.c */ +int cap_get_flag(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *); +int cap_set_flag(cap_t, cap_flag_t, int, cap_value_t *, cap_flag_value_t); +int cap_clear(cap_t); + +/* libcap/cap_file.c */ +cap_t cap_get_fd(int); +cap_t cap_get_file(const char *); +int cap_set_fd(int, cap_t); +int cap_set_file(const char *, cap_t); + +/* libcap/cap_proc.c */ +cap_t cap_get_proc(void); +int cap_set_proc(cap_t); + +/* libcap/cap_extint.c */ +ssize_t cap_size(cap_t); +ssize_t cap_copy_ext(void *, cap_t, ssize_t); +cap_t cap_copy_int(const void *); + +/* libcap/cap_text.c */ +cap_t cap_from_text(const char *); +char * cap_to_text(cap_t, ssize_t *); + +/* + * Linux capability system calls: defined in libcap but only available + * if the following _POSIX_SOURCE is _undefined_ + */ + +#if !defined(_POSIX_SOURCE) + +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); +extern char const *_cap_names[]; + +#endif /* !defined(_POSIX_SOURCE) */ + +#endif /* _SYS_CAPABILITY_H */ +@ + + +1.2 +log +@update with zefram's fixes +@ +text +@d5 2 +a6 2 + * Copyright (C) 1997 Aleph One + * Copyright (C) 1997 Andrew G. Morgan <morgan@@parc.power.net> +a21 21 + * Linux capability system calls: defined in libcap but only available + * if the following _POSIX_SOURCE is _undefined_ + */ + +#if !defined(_POSIX_SOURCE) + +int _setproccap(size_t, __cap_s const *,__cap_s const *, __cap_s const *); +int _getproccap(size_t, __cap_s *,__cap_s *, __cap_s *); +int _setfilecap(char const *, size_t, __cap_s const *, + __cap_s const *, __cap_s const *); +int _getfilecap(char const *, size_t, __cap_s *, __cap_s *, __cap_s *); +int _fsetfilecap(int, size_t, __cap_s const *, + __cap_s const *, __cap_s const *); +int _fgetfilecap(int, size_t, __cap_s *, __cap_s *, __cap_s *); + +/* libcap/cap_names.c */ +extern char const *_cap_names[__CAP_BITS]; + +#endif /* !defined(_POSIX_SOURCE) */ + +/* +d44 2 +a45 2 + CAP_INHERITABLE=1, /* Specifies the inheritable flag */ + CAP_PERMITTED=2 /* Specifies the permitted flag */ +d88 15 +@ + + +1.1 +log +@Initial revision +@ +text +@d14 5 +d22 2 +a23 2 + * This file compliments the kernel file by providing prototype + * information for the user library. +d26 16 +a81 1 +ssize_t cap_size(cap_t); +d102 1 +a107 2 + +#define CAP_TEXT_SIZE 2048 /* Maximum text length (16 per cap) */ +@ diff --git a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h new file mode 100644 index 0000000..dd27978 --- /dev/null +++ b/libcap/include/sys/capability.h @@ -0,0 +1,104 @@ +/* + * <sys/capability.h> + * + * + * Copyright (C) 1997 Aleph One + * Copyright (C) 1997-8 Andrew G. Morgan <morgan@linux.kernel.org> + * + * POSIX.1e Standard: 25.2 Capabilities <sys/capability.h> + */ + +#ifndef _SYS_CAPABILITY_H +#define _SYS_CAPABILITY_H + +/* + * This file complements the kernel file by providing prototype + * information for the user library. + */ + +#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 */ +cap_t cap_dup(cap_t); +int cap_free(cap_t *); +cap_t cap_init(void); + +/* libcap/cap_flag.c */ +int cap_get_flag(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *); +int cap_set_flag(cap_t, cap_flag_t, int, cap_value_t *, cap_flag_value_t); +int cap_clear(cap_t); + +/* libcap/cap_file.c */ +cap_t cap_get_fd(int); +cap_t cap_get_file(const char *); +int cap_set_fd(int, cap_t); +int cap_set_file(const char *, cap_t); + +/* libcap/cap_proc.c */ +cap_t cap_get_proc(void); +int cap_set_proc(cap_t); + +/* libcap/cap_extint.c */ +ssize_t cap_size(cap_t); +ssize_t cap_copy_ext(void *, cap_t, ssize_t); +cap_t cap_copy_int(const void *); + +/* libcap/cap_text.c */ +cap_t cap_from_text(const char *); +char * cap_to_text(cap_t, ssize_t *); + +/* + * Linux capability system calls: defined in libcap but only available + * if the following _POSIX_SOURCE is _undefined_ + */ + +#if !defined(_POSIX_SOURCE) + +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); +extern char const *_cap_names[]; + +#endif /* !defined(_POSIX_SOURCE) */ + +#endif /* _SYS_CAPABILITY_H */ diff --git a/libcap/libcap.h b/libcap/libcap.h new file mode 100644 index 0000000..2036583 --- /dev/null +++ b/libcap/libcap.h @@ -0,0 +1,125 @@ +/* + * $Id: libcap.h,v 1.5 1998/06/08 00:15:28 morgan Exp $ + * + * Copyright (c) 1997 Andrew G Morgan <morgan@linux.kernel.org> + * + * See end of file for Log. + * + * This file contains internal definitions for the various functions in + * this small capability library. + */ + +#ifndef LIBCAP_H +#define LIBCAP_H + +#include <sys/types.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/capability.h> + +/* include the names for the caps and a definition of __CAP_BITS */ +#include "cap_names.h" + +/* + * 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. + */ + +#define CAP_T_MAGIC 0xCA90D0 +struct _cap_struct { + int magic; + struct __user_cap_header_struct head; + struct __user_cap_data_struct set; +}; + +/* + * Do we match the local kernel? + */ + +#if !defined(_LINUX_CAPABILITY_VERSION) || \ + (_LINUX_CAPABILITY_VERSION != 0x19980330) + +# error "Kernel <linux/capability.h> does not match library" +# error "file "libcap.h" --> fix and recompile libcap" + +#endif + +/* + * kernel API cap set abstraction + */ + +#define NUMBER_OF_CAP_SETS 3 /* effective, inheritable, permitted */ +#define CAP_SET_SIZE (sizeof(struct __user_cap_data_struct)/NUMBER_OF_CAP_SETS) +#define __CAP_BLKS (CAP_SET_SIZE/sizeof(__u32)) +typedef struct { + __u32 _blk[__CAP_BLKS]; +} __cap_s; +#define raise_cap(x) _blk[(x)>>5] |= (1<<((x)&31)) +#define lower_cap(x) _blk[(x)>>5] |= (1<<((x)&31)) +#define isset_cap(y,x) ((y)->_blk[(x)>>5] & (1<<((x)&31))) + +/* + * Private definitions for internal use by the library. + */ + +#define good_cap_t(c) ((c) && (c)->magic == CAP_T_MAGIC) + +/* + * library debugging + */ +#ifdef DEBUG + +#include <stdio.h> +# define _cap_debug(f, x...) { \ + fprintf(stderr, __FUNCTION__ "(" __FILE__ ":%d): ", __LINE__); \ + fprintf(stderr, f, ## x); \ + fprintf(stderr, "\n"); \ +} +# define _cap_debugcap(s, c) \ + fprintf(stderr, __FUNCTION__ "(" __FILE__ ":%d): " s \ + "%08x\n", __LINE__, c) + +#else /* !DEBUG */ + +# define _cap_debug(f, x...) +# define _cap_debugcap(s, c) + +#endif /* DEBUG */ + +/* + * 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); + +#endif /* LIBCAP_H */ + +/* + * $Log: libcap.h,v $ + * Revision 1.5 1998/06/08 00:15:28 morgan + * accommodate alpha (glibc?) + * + * Revision 1.4 1998/06/07 15:58:23 morgan + * accommodate real kernel header files :*) + * + * Revision 1.3 1998/05/24 22:54:09 morgan + * updated for 2.1.104 + * + * Revision 1.2 1997/04/28 00:57:11 morgan + * zefram's replacement file with a number of bug fixes from AGM + * + * Revision 1.1 1997/04/21 04:32:52 morgan + * Initial revision + * + */ |