diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-03 20:33:30 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-03 20:33:30 -0700 |
commit | c591394f75d0462d9d9a17d66c1bcf800181a294 (patch) | |
tree | 14dded8222a14c5f1f77c27a8c0e1d96ba2ec574 /src | |
download | libcap-ng-c591394f75d0462d9d9a17d66c1bcf800181a294.tar.gz libcap-ng-c591394f75d0462d9d9a17d66c1bcf800181a294.tar.bz2 libcap-ng-c591394f75d0462d9d9a17d66c1bcf800181a294.zip |
Imported Upstream version 0.6.6upstream/0.6.6
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 38 | ||||
-rw-r--r-- | src/Makefile.in | 771 | ||||
-rw-r--r-- | src/cap-ng.c | 949 | ||||
-rw-r--r-- | src/cap-ng.h | 91 | ||||
-rw-r--r-- | src/captab.h | 69 | ||||
-rw-r--r-- | src/libcap-ng.pc.in | 11 | ||||
-rw-r--r-- | src/lookup_table.c | 115 | ||||
-rw-r--r-- | src/test/Makefile.am | 28 | ||||
-rw-r--r-- | src/test/Makefile.in | 607 | ||||
-rw-r--r-- | src/test/lib_test.c | 160 | ||||
-rw-r--r-- | src/test/thread_test.c | 53 |
11 files changed, 2892 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..6362fc2 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,38 @@ +# Makefile.am -- +# Copyright 2009 Red Hat Inc., Durham, North Carolina. +# All Rights Reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Authors: +# Steve Grubb <sgrubb@redhat.com> +# + +SUBDIRS = test +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libcap-ng.pc +DISTCLEANFILES = $(pkgconfig_DATA) +CLEANFILES = $(BUILT_SOURCES) +CONFIG_CLEAN_FILES = *.loT *.rej *.orig +AM_CFLAGS = -fPIC -DPIC -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE +INCLUDES = -I. -I${top_srcdir} +lib_LTLIBRARIES = libcap-ng.la +include_HEADERS = cap-ng.h +noinst_HEADERS = captab.h +libcap_ng_la_SOURCES = cap-ng.c lookup_table.c +libcap_ng_la_LIBADD = +libcap_ng_la_DEPENDENCIES = $(libcap_ng_la_SOURCES) ../config.h +libcap_ng_la_LDFLAGS = -Wl,-z,relro + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..d3077e0 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,771 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am -- +# Copyright 2009 Red Hat Inc., Durham, North Carolina. +# All Rights Reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Authors: +# Steve Grubb <sgrubb@redhat.com> +# + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src +DIST_COMMON = $(include_HEADERS) $(noinst_HEADERS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/libcap-ng.pc.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am_libcap_ng_la_OBJECTS = cap-ng.lo lookup_table.lo +libcap_ng_la_OBJECTS = $(am_libcap_ng_la_OBJECTS) +libcap_ng_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libcap_ng_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libcap_ng_la_SOURCES) +DIST_SOURCES = $(libcap_ng_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +DATA = $(pkgconfig_DATA) +HEADERS = $(include_HEADERS) $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG = @DEBUG@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +swig_found = @swig_found@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = test +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libcap-ng.pc +DISTCLEANFILES = $(pkgconfig_DATA) +CLEANFILES = $(BUILT_SOURCES) +CONFIG_CLEAN_FILES = *.loT *.rej *.orig +AM_CFLAGS = -fPIC -DPIC -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE +INCLUDES = -I. -I${top_srcdir} +lib_LTLIBRARIES = libcap-ng.la +include_HEADERS = cap-ng.h +noinst_HEADERS = captab.h +libcap_ng_la_SOURCES = cap-ng.c lookup_table.c +libcap_ng_la_LIBADD = +libcap_ng_la_DEPENDENCIES = $(libcap_ng_la_SOURCES) ../config.h +libcap_ng_la_LDFLAGS = -Wl,-z,relro +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +libcap-ng.pc: $(top_builddir)/config.status $(srcdir)/libcap-ng.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libcap-ng.la: $(libcap_ng_la_OBJECTS) $(libcap_ng_la_DEPENDENCIES) + $(libcap_ng_la_LINK) -rpath $(libdir) $(libcap_ng_la_OBJECTS) $(libcap_ng_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cap-ng.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lookup_table.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-includeHEADERS install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \ + uninstall-pkgconfigDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-includeHEADERS uninstall-libLTLIBRARIES \ + uninstall-pkgconfigDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/cap-ng.c b/src/cap-ng.c new file mode 100644 index 0000000..b68aa62 --- /dev/null +++ b/src/cap-ng.c @@ -0,0 +1,949 @@ +/* libcap-ng.c -- + * Copyright 2009-10 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Steve Grubb <sgrubb@redhat.com> + */ + +#include "config.h" +#include "cap-ng.h" +#include <string.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <sys/prctl.h> +#include <grp.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <errno.h> +#include <byteswap.h> +#ifdef HAVE_SYSCALL_H +#include <sys/syscall.h> +#endif +#ifdef HAVE_LINUX_SECUREBITS_H +#include <linux/securebits.h> +#endif + +/* + * Some milestones of when things became available: + * 2.6.24 kernel XATTR_NAME_CAPS + * 2.6.25 kernel PR_CAPBSET_DROP, CAPABILITY_VERSION_2 + * 2.6.26 kernel PR_SET_SECUREBITS, SECURE_*_LOCKED, VERSION_3 + */ + +/* External syscall prototypes */ +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); + +// Local defines +#define MASK(x) (1U << (x)) +#ifdef PR_CAPBSET_DROP +#define UPPER_MASK ~(unsigned)((~0U)<<(CAP_LAST_CAP-31)) +#else +// For v1 systems UPPER_MASK will never be used +#define UPPER_MASK (unsigned)(~0U) +#endif + +// Re-define cap_valid so its uniform between V1 and V3 +#undef cap_valid +#define cap_valid(x) ((x) <= CAP_LAST_CAP) + +// If we don't have the xattr library, then we can't +// compile-in file system capabilities +#ifndef HAVE_ATTR_XATTR_H +#undef VFS_CAP_U32 +#endif + +#ifdef VFS_CAP_U32 + #include <attr/xattr.h> + #if __BYTE_ORDER == __BIG_ENDIAN + #define FIXUP(x) bswap_32(x) + #else + #define FIXUP(x) (x) + #endif +#endif + +#ifndef _LINUX_CAPABILITY_VERSION_1 +#define _LINUX_CAPABILITY_VERSION_1 0x19980330 +#endif +#ifndef _LINUX_CAPABILITY_VERSION_2 +#define _LINUX_CAPABILITY_VERSION_2 0x20071026 +#endif +#ifndef _LINUX_CAPABILITY_VERSION_3 +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 +#endif + +// This public API went private in the 2.6.36 kernel - hope it never changes +#ifndef XATTR_CAPS_SUFFIX +#define XATTR_CAPS_SUFFIX "capability" +#endif +#ifndef XATTR_SECURITY_PREFIX +#define XATTR_SECURITY_PREFIX "security." +#endif +#ifndef XATTR_NAME_CAPS +#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX +#endif + + +/* Child processes can't get caps back */ +#ifndef SECURE_NOROOT +#define SECURE_NOROOT 0 +#endif +#ifndef SECURE_NOROOT_LOCKED +#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */ +#endif +/* Setuid apps run by uid 0 don't get caps back */ +#ifndef SECURE_NO_SETUID_FIXUP +#define SECURE_NO_SETUID_FIXUP 2 +#endif +#ifndef SECURE_NO_SETUID_FIXUP_LOCKED +#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */ +#endif + +// States: new, allocated, initted, updated, applied +typedef enum { CAPNG_NEW, CAPNG_ERROR, CAPNG_ALLOCATED, CAPNG_INIT, + CAPNG_UPDATED, CAPNG_APPLIED } capng_states_t; + +// Create an easy data struct out of the kernel definitions +typedef union { + struct __user_cap_data_struct v1; + struct __user_cap_data_struct v3[2]; +} cap_data_t; + +// This struct keeps all state info +struct cap_ng +{ + int cap_ver; + struct __user_cap_header_struct hdr; + cap_data_t data; + capng_states_t state; + __u32 bounds[2]; +}; + +// Global variables with per thread uniqueness +static __thread struct cap_ng m = { 1, + {0, 0}, + { {0, 0, 0} }, + CAPNG_NEW, + {0, 0} }; + + +static void init(void) +{ + if (m.state != CAPNG_NEW) + return; + + memset(&m.hdr, 0, sizeof(m.hdr)); + (void)capget(&m.hdr, NULL); // Returns -EINVAL + if (m.hdr.version == _LINUX_CAPABILITY_VERSION_3 || + m.hdr.version == _LINUX_CAPABILITY_VERSION_2) { + m.cap_ver = 3; + } else if (m.hdr.version == _LINUX_CAPABILITY_VERSION_1) { + m.cap_ver = 1; + } else { + m.state = CAPNG_ERROR; + return; + } + + memset(&m.data, 0, sizeof(cap_data_t)); +#ifdef HAVE_SYSCALL_H + m.hdr.pid = (unsigned)syscall(__NR_gettid); +#else + m.hdr.pid = (unsigned)getpid(); +#endif + m.state = CAPNG_ALLOCATED; +} + +void capng_clear(capng_select_t set) +{ + if (m.state == CAPNG_NEW) + init(); + if (m.state == CAPNG_ERROR) + return; + + if (set & CAPNG_SELECT_CAPS) + memset(&m.data, 0, sizeof(cap_data_t)); +#ifdef PR_CAPBSET_DROP + if (set & CAPNG_SELECT_BOUNDS) + memset(m.bounds, 0, sizeof(m.bounds)); +#endif + m.state = CAPNG_INIT; +} + +void capng_fill(capng_select_t set) +{ + if (m.state == CAPNG_NEW) + init(); + if (m.state == CAPNG_ERROR) + return; + + if (set & CAPNG_SELECT_CAPS) { + if (m.cap_ver == 1) { + m.data.v1.effective = 0x7FFFFFFFU; + m.data.v1.permitted = 0x7FFFFFFFU; + m.data.v1.inheritable = 0; + } else { + m.data.v3[0].effective = 0xFFFFFFFFU; + m.data.v3[0].permitted = 0xFFFFFFFFU; + m.data.v3[0].inheritable = 0; + m.data.v3[1].effective = 0xFFFFFFFFU; + m.data.v3[1].permitted = 0xFFFFFFFFU; + m.data.v3[1].inheritable = 0; + } + } +#ifdef PR_CAPBSET_DROP + if (set & CAPNG_SELECT_BOUNDS) { + unsigned i; + for (i=0; i<sizeof(m.bounds)/sizeof(__u32); i++) + m.bounds[i] = 0xFFFFFFFFU; + } +#endif + m.state = CAPNG_INIT; +} + +void capng_setpid(int pid) +{ + if (m.state == CAPNG_NEW) + init(); + if (m.state == CAPNG_ERROR) + return; + + m.hdr.pid = pid; +} + +#ifdef PR_CAPBSET_DROP +static int get_bounding_set(void) +{ + char buf[64]; + FILE *f; + + snprintf(buf, sizeof(buf), "/proc/%u/status", m.hdr.pid ? m.hdr.pid : +#ifdef HAVE_SYSCALL_H + (unsigned)syscall(__NR_gettid)); +#else + (unsigned)getpid(); +#endif + f = fopen(buf, "r"); + if (f == NULL) + return -1; + __fsetlocking(f, FSETLOCKING_BYCALLER); + while (fgets(buf, sizeof(buf), f)) { + if (strncmp(buf, "CapB", 4)) + continue; + sscanf(buf, "CapBnd: %08x%08x", &m.bounds[1], &m.bounds[0]); + fclose(f); + return 0; + } + fclose(f); + return -1; +} +#endif + +int capng_get_caps_process(void) +{ + int rc; + + if (m.state == CAPNG_NEW) + init(); + if (m.state == CAPNG_ERROR) + return -1; + + rc = capget((cap_user_header_t)&m.hdr, (cap_user_data_t)&m.data); + if (rc == 0) { + m.state = CAPNG_INIT; +#ifdef PR_CAPBSET_DROP + rc = get_bounding_set(); + if (rc < 0) + m.state = CAPNG_ERROR; +#endif + } + + return rc; +} + +#ifdef VFS_CAP_U32 +static int load_data(const struct vfs_cap_data *filedata, int size) +{ + unsigned int magic; + + if (m.cap_ver == 1) + return -1; // Should never get here but just in case + + magic = FIXUP(filedata->magic_etc); + switch (magic & VFS_CAP_REVISION_MASK) + { + case VFS_CAP_REVISION_1: + m.cap_ver = 1; + if (size != XATTR_CAPS_SZ_1) + return -1; + break; + case VFS_CAP_REVISION_2: + m.cap_ver = 2; + if (size != XATTR_CAPS_SZ_2) + return -1; + break; + default: + return -1; + } + + // Now stuff the data structures + m.data.v3[0].permitted = FIXUP(filedata->data[0].permitted); + m.data.v3[1].permitted = FIXUP(filedata->data[1].permitted); + m.data.v3[0].inheritable = FIXUP(filedata->data[0].inheritable); + m.data.v3[1].inheritable = FIXUP(filedata->data[1].inheritable); + if (magic & VFS_CAP_FLAGS_EFFECTIVE) { + m.data.v3[0].effective = + m.data.v3[0].permitted | m.data.v3[0].inheritable; + m.data.v3[1].effective = + m.data.v3[1].permitted | m.data.v3[1].inheritable; + } else { + m.data.v3[0].effective = 0; + m.data.v3[1].effective = 0; + } + return 0; +} +#endif + +int capng_get_caps_fd(int fd) +{ +#ifndef VFS_CAP_U32 + return -1; +#else + int rc; + struct vfs_cap_data filedata; + + if (m.state == CAPNG_NEW) + init(); + if (m.state == CAPNG_ERROR) + return -1; + + rc = fgetxattr(fd, XATTR_NAME_CAPS, &filedata, sizeof(filedata)); + if (rc <= 0) + return -1; + + rc = load_data(&filedata, rc); + if (rc == 0) + m.state = CAPNG_INIT; + + return rc; +#endif +} + +static void v1_update(capng_act_t action, unsigned int capability, __u32 *data) +{ + if (action == CAPNG_ADD) + *data |= MASK(capability); + else + *data &= ~(MASK(capability)); +} + +static void update_effective(capng_act_t action, unsigned int capability, + unsigned int idx) +{ + if (action == CAPNG_ADD) + m.data.v3[idx].effective |= MASK(capability); + else + m.data.v3[idx].effective &= ~(MASK(capability)); +} + +static void update_permitted(capng_act_t action, unsigned int capability, + unsigned int idx) +{ + if (action == CAPNG_ADD) + m.data.v3[idx].permitted |= MASK(capability); + else + m.data.v3[idx].permitted &= ~(MASK(capability)); +} + +static void update_inheritable(capng_act_t action, unsigned int capability, + unsigned int idx) +{ + if (action == CAPNG_ADD) + m.data.v3[idx].inheritable |= MASK(capability); + else + m.data.v3[idx].inheritable &= ~(MASK(capability)); +} + +static void update_bounding_set(capng_act_t action, unsigned int capability, + unsigned int idx) +{ +#ifdef PR_CAPBSET_DROP + if (action == CAPNG_ADD) + m.bounds[idx] |= MASK(capability); + else + m.bounds[idx] &= ~(MASK(capability)); +#endif +} + +int capng_update(capng_act_t action, capng_type_t type, unsigned int capability) +{ + // Before updating, we expect that the data is initialized to something + if (m.state < CAPNG_INIT) + return -1; + if (!cap_valid(capability)) { + errno = EINVAL; + return -1; + } + + if (m.cap_ver == 1) { + if (CAPNG_EFFECTIVE & type) + v1_update(action, capability, &m.data.v1.effective); + if (CAPNG_PERMITTED & type) + v1_update(action, capability, &m.data.v1.permitted); + if (CAPNG_INHERITABLE & type) + v1_update(action, capability, &m.data.v1.inheritable); + } else { + int idx; + + if (capability > 31) { + idx = capability>>5; + capability %= 32; + } else + idx = 0; + + if (CAPNG_EFFECTIVE & type) + update_effective(action, capability, idx); + if (CAPNG_PERMITTED & type) + update_permitted(action, capability, idx); + if (CAPNG_INHERITABLE & type) + update_inheritable(action, capability, idx); + if (CAPNG_BOUNDING_SET & type) + update_bounding_set(action, capability, idx); + } + + m.state = CAPNG_UPDATED; + return 0; +} + +int capng_updatev(capng_act_t action, capng_type_t type, + unsigned int capability, ...) +{ + int rc; + unsigned int cap; + va_list ap; + + rc = capng_update(action, type, capability); + if (rc) + return rc; + va_start(ap, capability); + cap = va_arg(ap, unsigned int); + while (cap_valid(cap)) { + rc = capng_update(action, type, cap); + if (rc) + break; + cap = va_arg(ap, unsigned int); + } + va_end(ap); + + // See if planned exit or invalid + if (cap == (unsigned)-1) + rc = 0; + else { + rc = -1; + errno = EINVAL; + } + + return rc; +} + +int capng_apply(capng_select_t set) +{ + int rc = -1; + + // Before updating, we expect that the data is initialized to something + if (m.state < CAPNG_INIT) + return -1; + + if (set & CAPNG_SELECT_BOUNDS) { +#ifdef PR_CAPBSET_DROP + void *s = capng_save_state(); + capng_get_caps_process(); + if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) { + int i; + capng_restore_state(&s); + rc = 0; + for (i=0; i <= CAP_LAST_CAP && rc == 0; i++) + if (capng_have_capability(CAPNG_BOUNDING_SET, + i) == 0) + rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); + if (rc == 0) + m.state = CAPNG_APPLIED; + } else + capng_restore_state(&s); +#else + rc = 0; +#endif + } + if (set & CAPNG_SELECT_CAPS) { + rc = capset((cap_user_header_t)&m.hdr, + (cap_user_data_t)&m.data); + if (rc == 0) + m.state = CAPNG_APPLIED; + } + return rc; +} + +#ifdef VFS_CAP_U32 +static int save_data(struct vfs_cap_data *filedata, int *size) +{ + // Now stuff the data structures + if (m.cap_ver == 1) { + filedata->data[0].permitted = FIXUP(m.data.v1.permitted); + filedata->data[0].inheritable = FIXUP(m.data.v1.inheritable); + filedata->magic_etc = FIXUP(VFS_CAP_REVISION_1); + *size = XATTR_CAPS_SZ_1; + } else { + int eff; + + if (m.data.v3[0].effective || m.data.v3[1].effective) + eff = VFS_CAP_FLAGS_EFFECTIVE; + else + eff = 0; + filedata->data[0].permitted = FIXUP(m.data.v3[0].permitted); + filedata->data[0].inheritable = FIXUP(m.data.v3[0].inheritable); + filedata->data[1].permitted = FIXUP(m.data.v3[1].permitted); + filedata->data[1].inheritable = FIXUP(m.data.v3[1].inheritable); + filedata->magic_etc = FIXUP(VFS_CAP_REVISION_2 | eff); + *size = XATTR_CAPS_SZ_2; + } + + return 0; +} +#endif + +int capng_apply_caps_fd(int fd) +{ +#ifndef VFS_CAP_U32 + return -1; +#else + int rc, size; + struct vfs_cap_data filedata; + struct stat buf; + + // Before updating, we expect that the data is initialized to something + if (m.state < CAPNG_INIT) + return -1; + + if (fstat(fd, &buf) != 0) + return -1; + if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) { + errno = EINVAL; + return -1; + } + if (capng_have_capabilities(CAPNG_SELECT_CAPS) == CAPNG_NONE) + rc = fremovexattr(fd, XATTR_NAME_CAPS); + else { + save_data(&filedata, &size); + rc = fsetxattr(fd, XATTR_NAME_CAPS, &filedata, size, 0); + } + + if (rc == 0) + m.state = CAPNG_APPLIED; + + return rc; +#endif +} + +// Change uids keeping/removing only certain capabilities +// flag to drop supp groups +int capng_change_id(int uid, int gid, capng_flags_t flag) +{ + int rc, need_setgid, need_setuid; + + // Before updating, we expect that the data is initialized to something + if (m.state < CAPNG_INIT) + return -1; + + // Check the current capabilities +#ifdef PR_CAPBSET_DROP + // If newer kernel, we need setpcap to change the bounding set + if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP) == 0 && + flag & CAPNG_CLEAR_BOUNDING) + capng_update(CAPNG_ADD, + CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP); +#endif + if (gid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETGID)) + need_setgid = 0; + else { + need_setgid = 1; + capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_SETGID); + } + if (uid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETUID)) + need_setuid = 0; + else { + need_setuid = 1; + capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_SETUID); + } + + // Tell system we want to keep caps across uid change + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) + return -2; + + // Change to the temp capabilities + rc = capng_apply(CAPNG_SELECT_CAPS); + if (rc < 0) + return -3; + + // Clear bounding set if needed while we have CAP_SETPCAP + if (flag & CAPNG_CLEAR_BOUNDING) { + capng_clear(CAPNG_BOUNDING_SET); + rc = capng_apply(CAPNG_SELECT_BOUNDS); + if (rc) + return -8; + } + + // Change gid + if (gid != -1) { + rc = setresgid(gid, gid, gid); + if (rc) + return -4; + } + + // See if we need to unload supplemental groups + if ((flag & CAPNG_DROP_SUPP_GRP) && gid != -1) { + if (setgroups(0, NULL)) + return -5; + } + + // Change uid + if (uid != -1) { + rc = setresuid(uid, uid, uid); + if (rc) + return -6; + } + + // Tell it we are done keeping capabilities + rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0); + if (rc) + return -7; + + // Now throw away CAP_SETPCAP so no more changes + if (need_setgid) + capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_SETGID); + if (need_setuid) + capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_SETUID); + + // Now drop setpcap & apply + capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED, + CAP_SETPCAP); + rc = capng_apply(CAPNG_SELECT_CAPS); + if (rc < 0) + return -9; + + // Done + m.state = CAPNG_UPDATED; + return 0; +} + +int capng_lock(void) +{ +#ifdef PR_SET_SECUREBITS + int rc = prctl(PR_SET_SECUREBITS, + 1 << SECURE_NOROOT | + 1 << SECURE_NOROOT_LOCKED | + 1 << SECURE_NO_SETUID_FIXUP | + 1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0); + if (rc) + return -1; +#endif + + return 0; +} + +// -1 - error, 0 - no caps, 1 partial caps, 2 full caps +capng_results_t capng_have_capabilities(capng_select_t set) +{ + int empty = 0, full = 0; + + // First, try to init with current set + if (m.state < CAPNG_INIT) + capng_get_caps_process(); + + // If we still don't have anything, error out + if (m.state < CAPNG_INIT) + return CAPNG_FAIL; + + if (set & CAPNG_SELECT_CAPS) { + if (m.cap_ver == 1) { + if (m.data.v1.effective == 0) + empty = 1; + // after fill, 30 bits starts from upper to lower + else if (m.data.v1.effective == 0x7FFFFFFFU) + full = 1; + // actual capabilities read from system + else if (m.data.v1.effective == 0xFFFFFEFFU) + full = 1; + else + return CAPNG_PARTIAL; + } else { + if (m.data.v3[0].effective == 0) + empty = 1; + else if (m.data.v3[0].effective == 0xFFFFFFFFU) + full = 1; + else + return CAPNG_PARTIAL; + if ((m.data.v3[1].effective & UPPER_MASK) == 0) + empty = 1; + else if ((m.data.v3[1].effective & UPPER_MASK) == + UPPER_MASK) + full = 1; + else + return CAPNG_PARTIAL; + } + } +#ifdef PR_CAPBSET_DROP + if (set & CAPNG_SELECT_BOUNDS) { + if (m.bounds[0] == 0) + empty = 1; + else if (m.bounds[0] == 0xFFFFFFFFU) + full = 1; + else + return CAPNG_PARTIAL; + if ((m.bounds[1] & UPPER_MASK) == 0) + empty = 1; + else if ((m.bounds[1] & UPPER_MASK) == UPPER_MASK) + full = 1; + else + return CAPNG_PARTIAL; + } +#endif + + if (empty == 1 && full == 0) + return CAPNG_NONE; + else if (empty == 0 && full == 1) + return CAPNG_FULL; + + return CAPNG_PARTIAL; +} + +static int check_effective(unsigned int capability, unsigned int idx) +{ + return MASK(capability) & m.data.v3[idx].effective ? 1 : 0; +} + +static int check_permitted(unsigned int capability, unsigned int idx) +{ + return MASK(capability) & m.data.v3[idx].permitted ? 1 : 0; +} + +static int check_inheritable(unsigned int capability, unsigned int idx) +{ + return MASK(capability) & m.data.v3[idx].inheritable ? 1 : 0; +} + +static int bounds_bit_check(unsigned int capability, unsigned int idx) +{ +#ifdef PR_CAPBSET_DROP + return MASK(capability) & m.bounds[idx] ? 1 : 0; +#else + return 0; +#endif +} + +static int v1_check(unsigned int capability, __u32 data) +{ + return MASK(capability) & data ? 1 : 0; +} + +int capng_have_capability(capng_type_t which, unsigned int capability) +{ + // First, try to init with current set + if (m.state < CAPNG_INIT) + capng_get_caps_process(); + + // If we still don't have anything, error out + if (m.state < CAPNG_INIT) + return CAPNG_FAIL; + if (m.cap_ver == 1 && capability > 31) + return 0; + if (!cap_valid(capability)) + return 0; + + if (m.cap_ver == 1) { + if (which == CAPNG_EFFECTIVE) + return v1_check(capability, m.data.v1.effective); + else if (which == CAPNG_PERMITTED) + return v1_check(capability, m.data.v1.permitted); + else if (which == CAPNG_INHERITABLE) + return v1_check(capability, m.data.v1.inheritable); + } else { + unsigned int idx; + + if (capability > 31) { + idx = capability>>5; + capability %= 32; + } else + idx = 0; + + if (which == CAPNG_EFFECTIVE) + return check_effective(capability, idx); + else if (which == CAPNG_PERMITTED) + return check_permitted(capability, idx); + else if (which == CAPNG_INHERITABLE) + return check_inheritable(capability, idx); + else if (which == CAPNG_BOUNDING_SET) + return bounds_bit_check(capability, idx); + } + return 0; +} + +char *capng_print_caps_numeric(capng_print_t where, capng_select_t set) +{ + char *ptr = NULL; + + if (m.state < CAPNG_INIT) + return ptr; + + if (where == CAPNG_PRINT_STDOUT) { + if (set & CAPNG_SELECT_CAPS) { + if (m.cap_ver == 1) { + printf( "Effective: %08X\n" + "Permitted: %08X\n" + "Inheritable: %08X\n", + m.data.v1.effective, + m.data.v1.permitted, + m.data.v1.inheritable); + } else { + printf( "Effective: %08X, %08X\n" + "Permitted: %08X, %08X\n" + "Inheritable: %08X, %08X\n", + m.data.v3[1].effective & UPPER_MASK, + m.data.v3[0].effective, + m.data.v3[1].permitted & UPPER_MASK, + m.data.v3[0].permitted, + m.data.v3[1].inheritable & UPPER_MASK, + m.data.v3[0].inheritable); + + } + } +#ifdef PR_CAPBSET_DROP + if (set & CAPNG_SELECT_BOUNDS) + printf("Bounding Set: %08X, %08X\n", + m.bounds[1] & UPPER_MASK, m.bounds[0]); +#endif + } else if (where == CAPNG_PRINT_BUFFER) { + if (set & CAPNG_SELECT_CAPS) { + // Make it big enough for bounding set, too + ptr = malloc(160); + if (m.cap_ver == 1) { + snprintf(ptr, 160, + "Effective: %08X\n" + "Permitted: %08X\n" + "Inheritable: %08X\n", + m.data.v1.effective, + m.data.v1.permitted, + m.data.v1.inheritable); + } else { + snprintf(ptr, 160, + "Effective: %08X, %08X\n" + "Permitted: %08X, %08X\n" + "Inheritable: %08X, %08X\n", + m.data.v3[1].effective & UPPER_MASK, + m.data.v3[0].effective, + m.data.v3[1].permitted & UPPER_MASK, + m.data.v3[0].permitted, + m.data.v3[1].inheritable & UPPER_MASK, + m.data.v3[0].inheritable); + } + } + if (set & CAPNG_SELECT_BOUNDS) { +#ifdef PR_CAPBSET_DROP + char *s; + if (ptr == NULL ){ + ptr = malloc(40); + if (ptr == NULL) + return ptr; + *ptr = 0; + s = ptr; + } else + s = ptr + strlen(ptr); + snprintf(s, 40, "Bounding Set: %08X, %08X\n", + m.bounds[1] & UPPER_MASK, m.bounds[0]); +#endif + } + } + + return ptr; +} + +char *capng_print_caps_text(capng_print_t where, capng_type_t which) +{ + unsigned int i; + int once = 0, cnt = 0; + char *ptr = NULL; + + if (m.state < CAPNG_INIT) + return ptr; + + for (i=0; i<=CAP_LAST_CAP; i++) { + if (capng_have_capability(which, i)) { + const char *n = capng_capability_to_name(i); + if (where == CAPNG_PRINT_STDOUT) { + if (once == 0) { + printf("%s", n); + once++; + } else + printf(", %s", n); + } else if (where == CAPNG_PRINT_BUFFER) { + int len; + if (once == 0) { + ptr = malloc(CAP_LAST_CAP*18); + if (ptr == NULL) + return ptr; + len = sprintf(ptr+cnt, "%s", n); + once++; + } else + len = sprintf(ptr+cnt, ", %s", n); + if (len > 0) + cnt+=len; + } + } + } + if (once == 0) { + if (where == CAPNG_PRINT_STDOUT) + printf("none"); + else + ptr = strdup("none"); + } + return ptr; +} + +void *capng_save_state(void) +{ + void *ptr = malloc(sizeof(m)); + if (ptr) + memcpy(ptr, &m, sizeof(m)); + return ptr; +} + +void capng_restore_state(void **state) +{ + if (state) { + void *ptr = *state; + if (ptr) + memcpy(&m, ptr, sizeof(m)); + free(ptr); + *state = NULL; + } +} + diff --git a/src/cap-ng.h b/src/cap-ng.h new file mode 100644 index 0000000..89d63af --- /dev/null +++ b/src/cap-ng.h @@ -0,0 +1,91 @@ +/* libcap-ng.h -- + * Copyright 2009 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Steve Grubb <sgrubb@redhat.com> + */ + +#ifndef LIBCAP_NG_HEADER +#define LIBCAP_NG_HEADER + +#include <stdint.h> +#include <linux/capability.h> +#include <unistd.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CAP_LAST_CAP +#define CAP_LAST_CAP CAP_AUDIT_CONTROL +#endif + +typedef enum { CAPNG_DROP, CAPNG_ADD } capng_act_t; +typedef enum { CAPNG_EFFECTIVE=1, CAPNG_PERMITTED=2, + CAPNG_INHERITABLE=4, CAPNG_BOUNDING_SET=8 } capng_type_t; +typedef enum { CAPNG_SELECT_CAPS = 16, CAPNG_SELECT_BOUNDS = 32, + CAPNG_SELECT_BOTH = 48 } capng_select_t; +typedef enum { CAPNG_FAIL=-1, CAPNG_NONE, CAPNG_PARTIAL, + CAPNG_FULL } capng_results_t; +typedef enum { CAPNG_PRINT_STDOUT, CAPNG_PRINT_BUFFER } capng_print_t; +typedef enum { CAPNG_NO_FLAG=0, CAPNG_DROP_SUPP_GRP=1, + CAPNG_CLEAR_BOUNDING=2 } capng_flags_t; + + +// These functions manipulate process capabilities +void capng_clear(capng_select_t set); +void capng_fill(capng_select_t set); +void capng_setpid(int pid); +int capng_get_caps_process(void); +int capng_update(capng_act_t action, capng_type_t type,unsigned int capability); +int capng_updatev(capng_act_t action, capng_type_t type, + unsigned int capability, ...); + +// These functions apply the capabilities previously setup to a process +int capng_apply(capng_select_t set); +int capng_lock(void); +int capng_change_id(int uid, int gid, capng_flags_t flag); + +// These functions are used for file based capabilities +int capng_get_caps_fd(int fd); +int capng_apply_caps_fd(int fd); + +// These functions check capability bits +capng_results_t capng_have_capabilities(capng_select_t set); +int capng_have_capability(capng_type_t which, unsigned int capability); + +// These functions printout capabilities +char *capng_print_caps_numeric(capng_print_t where, capng_select_t set); +char *capng_print_caps_text(capng_print_t where, capng_type_t which); + +// These functions convert between numeric and text string +int capng_name_to_capability(const char *name); +const char *capng_capability_to_name(unsigned int capability); + +// These function should be used when you suspect a third party library +// may use libcap-ng also and want to make sure it doesn't alter something +// important. Otherwise you shouldn't need to call these. +void *capng_save_state(void); +void capng_restore_state(void **state); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/captab.h b/src/captab.h new file mode 100644 index 0000000..46a617c --- /dev/null +++ b/src/captab.h @@ -0,0 +1,69 @@ +/* captab.h -- + * Copyright 2009,2011 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Steve Grubb <sgrubb@redhat.com> + */ + +_S(CAP_CHOWN, "chown" ) +_S(CAP_DAC_OVERRIDE, "dac_override" ) +_S(CAP_DAC_READ_SEARCH, "dac_read_search" ) +_S(CAP_FOWNER, "fowner" ) +_S(CAP_FSETID, "fsetid" ) +_S(CAP_KILL, "kill" ) +_S(CAP_SETGID, "setgid" ) +_S(CAP_SETUID, "setuid" ) +_S(CAP_SETPCAP, "setpcap" ) +_S(CAP_LINUX_IMMUTABLE, "linux_immutable" ) +_S(CAP_NET_BIND_SERVICE, "net_bind_service" ) +_S(CAP_NET_BROADCAST, "net_broadcast" ) +_S(CAP_NET_ADMIN, "net_admin" ) +_S(CAP_NET_RAW, "net_raw" ) +_S(CAP_IPC_LOCK, "ipc_lock" ) +_S(CAP_IPC_OWNER, "ipc_owner" ) +_S(CAP_SYS_MODULE, "sys_module" ) +_S(CAP_SYS_RAWIO, "sys_rawio" ) +_S(CAP_SYS_CHROOT, "sys_chroot" ) +_S(CAP_SYS_PTRACE, "sys_ptrace" ) +_S(CAP_SYS_PACCT, "sys_psacct" ) +_S(CAP_SYS_ADMIN, "sys_admin" ) +_S(CAP_SYS_BOOT, "sys_boot" ) +_S(CAP_SYS_NICE, "sys_nice" ) +_S(CAP_SYS_RESOURCE, "sys_resource" ) +_S(CAP_SYS_TIME, "sys_time" ) +_S(CAP_SYS_TTY_CONFIG, "sys_tty_config" ) +_S(CAP_MKNOD, "mknod" ) +_S(CAP_LEASE, "lease" ) +_S(CAP_AUDIT_WRITE, "audit_write" ) +_S(CAP_AUDIT_CONTROL, "audit_control" ) +#ifdef CAP_SETFCAP +_S(CAP_SETFCAP, "setfcap" ) +#endif +#ifdef CAP_MAC_OVERRIDE +_S(CAP_MAC_OVERRIDE, "mac_override" ) +#endif +#ifdef CAP_MAC_ADMIN +_S(CAP_MAC_ADMIN, "mac_admin" ) +#endif +#ifdef CAP_SYSLOG +_S(CAP_SYSLOG, "syslog" ) +#endif +#ifdef CAP_WAKE_ALARM +_S(CAP_WAKE_ALARM, "wake_alarm" ) +#endif + diff --git a/src/libcap-ng.pc.in b/src/libcap-ng.pc.in new file mode 100644 index 0000000..ff1074b --- /dev/null +++ b/src/libcap-ng.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libcap-ng +Description: An alternate posix capabilities library. +Version: @VERSION@ +Libs: -L${libdir} -lcap-ng +Cflags: -I${includedir} + diff --git a/src/lookup_table.c b/src/lookup_table.c new file mode 100644 index 0000000..e12eb3d --- /dev/null +++ b/src/lookup_table.c @@ -0,0 +1,115 @@ +/* lookup_table.c -- + * Copyright 2009 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Steve Grubb <sgrubb@redhat.com> + */ + +#include "config.h" +#include <stddef.h> +#include <linux/capability.h> +#include <strings.h> + + +#ifndef CAP_LAST_CAP +#define CAP_LAST_CAP CAP_AUDIT_CONTROL +#endif +#undef cap_valid +#define cap_valid(x) ((x) <= CAP_LAST_CAP) + + +struct transtab { + int value; + int offset; +}; + +#define MSGSTRFIELD(line) MSGSTRFIELD1(line) +#define MSGSTRFIELD1(line) str##line + + +/* To create the following tables in a DSO-friendly way we split them in + two separate variables: a long string which is created by concatenating + all strings referenced in the table and the table itself, which uses + offsets instead of string pointers. To do this without increasing + the maintenance burden we use a lot of preprocessor magic. All the + maintainer has to do is to add a new entry to the included file and + recompile. */ + +static const union captab_msgstr_t { + struct { +#define _S(n, s) char MSGSTRFIELD(__LINE__)[sizeof (s)]; +#include "captab.h" +#undef _S + }; + char str[0]; +} captab_msgstr = { { +#define _S(n, s) s, +#include "captab.h" +#undef _S +} }; +static const struct transtab captab[] = { +#define _S(n, s) { n, offsetof(union captab_msgstr_t, \ + MSGSTRFIELD(__LINE__)) }, +#include "captab.h" +#undef _S +}; +#define CAP_NG_CAPABILITY_NAMES (sizeof(captab)/sizeof(captab[0])) + + + + +static int capng_lookup_name(const struct transtab *table, + const char *tabstr, size_t length, const char *name) +{ + size_t i; + + for (i = 0; i < length; i++) { + if (!strcasecmp(tabstr + table[i].offset, name)) + return table[i].value; + } + return -1; +} + +static const char *capng_lookup_number(const struct transtab *table, + const char *tabstr, size_t length, + int number) +{ + size_t i; + + for (i = 0; i < length; i++) { + if (table[i].value == number) + return tabstr + table[i].offset; + } + return NULL; +} + +int capng_name_to_capability(const char *name) +{ + return capng_lookup_name(captab, captab_msgstr.str, + CAP_NG_CAPABILITY_NAMES, name); +} + +const char *capng_capability_to_name(unsigned int capability) +{ + if (!cap_valid(capability)) + return NULL; + + return capng_lookup_number(captab, captab_msgstr.str, + CAP_NG_CAPABILITY_NAMES, capability); +} + diff --git a/src/test/Makefile.am b/src/test/Makefile.am new file mode 100644 index 0000000..f3963cf --- /dev/null +++ b/src/test/Makefile.am @@ -0,0 +1,28 @@ +# Makefile.am -- +# Copyright 2009,10 Red Hat Inc., Durham, North Carolina. +# All Rights Reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Authors: +# Steve Grubb <sgrubb@redhat.com> +# + +INCLUDES = -I${top_srcdir} -I${top_srcdir}/src +check_PROGRAMS = lib_test thread_test +TESTS = $(check_PROGRAMS) + +lib_test_LDADD = ${top_builddir}/src/libcap-ng.la +thread_test_LDADD = ${top_builddir}/src/libcap-ng.la -lpthread diff --git a/src/test/Makefile.in b/src/test/Makefile.in new file mode 100644 index 0000000..a52c2de --- /dev/null +++ b/src/test/Makefile.in @@ -0,0 +1,607 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am -- +# Copyright 2009,10 Red Hat Inc., Durham, North Carolina. +# All Rights Reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Authors: +# Steve Grubb <sgrubb@redhat.com> +# +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +check_PROGRAMS = lib_test$(EXEEXT) thread_test$(EXEEXT) +subdir = src/test +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +lib_test_SOURCES = lib_test.c +lib_test_OBJECTS = lib_test.$(OBJEXT) +lib_test_DEPENDENCIES = ${top_builddir}/src/libcap-ng.la +thread_test_SOURCES = thread_test.c +thread_test_OBJECTS = thread_test.$(OBJEXT) +thread_test_DEPENDENCIES = ${top_builddir}/src/libcap-ng.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = lib_test.c thread_test.c +DIST_SOURCES = lib_test.c thread_test.c +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG = @DEBUG@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +swig_found = @swig_found@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I${top_srcdir} -I${top_srcdir}/src +TESTS = $(check_PROGRAMS) +lib_test_LDADD = ${top_builddir}/src/libcap-ng.la +thread_test_LDADD = ${top_builddir}/src/libcap-ng.la -lpthread +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/test/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/test/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +lib_test$(EXEEXT): $(lib_test_OBJECTS) $(lib_test_DEPENDENCIES) + @rm -f lib_test$(EXEEXT) + $(LINK) $(lib_test_OBJECTS) $(lib_test_LDADD) $(LIBS) +thread_test$(EXEEXT): $(thread_test_OBJECTS) $(thread_test_DEPENDENCIES) + @rm -f thread_test$(EXEEXT) + $(LINK) $(thread_test_OBJECTS) $(thread_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_test.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/test/lib_test.c b/src/test/lib_test.c new file mode 100644 index 0000000..f6cb893 --- /dev/null +++ b/src/test/lib_test.c @@ -0,0 +1,160 @@ +/* lib_test.c -- simple libcap-ng test suite + * Copyright 2009 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Steve Grubb <sgrubb@redhat.com> + */ + +#include "config.h" +#include "../cap-ng.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + + +int main(void) +{ + int rc, i, len, last = CAP_LAST_CAP; + char *text; + void *saved; + + puts("Doing basic bit tests..."); + capng_clear(CAPNG_SELECT_BOTH); + if (capng_have_capabilities(CAPNG_SELECT_BOTH) != CAPNG_NONE) { + puts("Failed clearing capabilities"); + abort(); + } + saved = capng_save_state(); + capng_fill(CAPNG_SELECT_BOTH); + if (capng_have_capabilities(CAPNG_SELECT_BOTH) != CAPNG_FULL) { + puts("Failed filling capabilities"); + abort(); + } + // Need to detect if version 1 or 2 capabilities + text = capng_print_caps_numeric(CAPNG_PRINT_BUFFER, CAPNG_SELECT_CAPS); + len = strlen(text); + free(text); + if (len < 80 && last > 30) // The kernel & headers are mismatched + last = 30; + // Now test that restore still works + capng_restore_state(&saved); + if (capng_have_capabilities(CAPNG_SELECT_BOTH) != CAPNG_NONE) { + puts("Failed restoring capabilities"); + abort(); + } + printf("Doing advanced bit tests for %d capabilities...\n", last); + for (i=0; i<=last; i++) { + capng_clear(CAPNG_SELECT_BOTH); + rc = capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i); + if (rc) { + puts("Failed update test 1"); + abort(); + } + rc = capng_have_capability(CAPNG_EFFECTIVE, i); + if (rc == 0) { + puts("Failed have capability test 1"); + capng_print_caps_numeric(CAPNG_PRINT_STDOUT, + CAPNG_SELECT_CAPS); + abort(); + } + if(capng_have_capabilities(CAPNG_SELECT_CAPS)!=CAPNG_PARTIAL){ + puts("Failed have capabilities test 1"); + capng_print_caps_numeric(CAPNG_PRINT_STDOUT, + CAPNG_SELECT_CAPS); + abort(); + } +#if CAP_LAST_CAP > 31 + rc = capng_update(CAPNG_ADD, CAPNG_BOUNDING_SET, i); + if (rc) { + puts("Failed bset update test 2"); + abort(); + } + rc = capng_have_capability(CAPNG_BOUNDING_SET, i); + if (rc == 0) { + puts("Failed bset have capability test 2"); + capng_print_caps_numeric(CAPNG_PRINT_STDOUT, + CAPNG_SELECT_BOTH); + abort(); + } + if(capng_have_capabilities(CAPNG_SELECT_BOUNDS)!=CAPNG_PARTIAL){ + puts("Failed bset have capabilities test 2"); + capng_print_caps_numeric(CAPNG_PRINT_STDOUT, + CAPNG_SELECT_BOTH); + abort(); + } +#endif + text=capng_print_caps_text(CAPNG_PRINT_BUFFER, CAPNG_EFFECTIVE); + if (text == NULL) { + puts("Failed getting print text to buffer"); + abort(); + } + if (strcmp(text, capng_capability_to_name(i))) { + puts("Failed print text comparison"); + printf("%s != %s\n", text, + capng_capability_to_name(i)); + abort(); + } + free(text); + // Now make sure the mask part is working + capng_fill(CAPNG_SELECT_BOTH); + rc = capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, i); + if (rc) { + puts("Failed update test 3"); + abort(); + } + // Should be partial + if(capng_have_capabilities(CAPNG_SELECT_CAPS)!=CAPNG_PARTIAL){ + puts("Failed have capabilities test 3"); + capng_print_caps_numeric(CAPNG_PRINT_STDOUT, + CAPNG_SELECT_CAPS); + abort(); + } + // Add back the bit and should be full capabilities + rc = capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i); + if (rc) { + puts("Failed update test 4"); + abort(); + } + if (capng_have_capabilities(CAPNG_SELECT_CAPS) != CAPNG_FULL){ + puts("Failed have capabilities test 4"); + capng_print_caps_numeric(CAPNG_PRINT_STDOUT, + CAPNG_SELECT_CAPS); + abort(); + } + } + // Now test the updatev function + capng_clear(CAPNG_SELECT_BOTH); + rc = capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE, + CAP_CHOWN, CAP_FOWNER, CAP_KILL, -1); + if (rc) { + puts("Failed updatev test"); + abort(); + } + rc = capng_have_capability(CAPNG_EFFECTIVE, CAP_CHOWN) && + capng_have_capability(CAPNG_EFFECTIVE, CAP_FOWNER) && + capng_have_capability(CAPNG_EFFECTIVE, CAP_KILL); + if (rc == 0) { + puts("Failed have updatev capability test"); + capng_print_caps_numeric(CAPNG_PRINT_STDOUT, + CAPNG_SELECT_CAPS); + abort(); + } + + return EXIT_SUCCESS; +} + diff --git a/src/test/thread_test.c b/src/test/thread_test.c new file mode 100644 index 0000000..c5ba030 --- /dev/null +++ b/src/test/thread_test.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include <stdlib.h> +#include <cap-ng.h> +#include <pthread.h> + +//#define DEBUG 1 + +pthread_t thread1, thread2; + +void *thread1_main(void *arg) +{ + capng_fill(CAPNG_SELECT_BOTH); +#ifdef DEBUG + printf("thread1 filled capabilities\n"); +#endif + sleep(2); + if (capng_have_capabilities(CAPNG_SELECT_CAPS) < CAPNG_FULL) { + printf("Capabilities missing when there should be some\n"); + exit(1); + } +#ifdef DEBUG + printf("SUCCESS: Full capabilities reported\n"); +#endif + return NULL; +} + +void *thread2_main(void *arg) +{ + sleep(1); +#ifdef DEBUG + printf("thread2 getting capabilities\n"); +#endif + capng_get_caps_process(); + if (capng_have_capabilities(CAPNG_SELECT_CAPS) != CAPNG_NONE) { + printf("Detected capabilities when there should not be any\n"); + exit(1); + } + capng_clear(CAPNG_SELECT_BOTH); +#ifdef DEBUG + printf("SUCCESS: No capabilities reported\n"); +#endif + return NULL; +} + +int main(void) +{ + printf("Testing thread separation of capabilities\n"); + pthread_create(&thread1, NULL, thread1_main, NULL); + pthread_create(&thread2, NULL, thread2_main, NULL); + sleep(3); + return 0; +} + |