diff options
author | Andrew Morgan <morgan@kernel.org> | 2007-11-07 22:14:24 -0800 |
---|---|---|
committer | Andrew Morgan <morgan@kernel.org> | 2007-11-07 22:14:24 -0800 |
commit | f782a9792f375581307a0c60d7f985c19aa6b439 (patch) | |
tree | d1e934ce6abbe013e8d3414478bef1c0a7435f78 | |
parent | ea4e5f8e08bf8af459378dac24d42fdbbcdb2e73 (diff) | |
download | libcap-f782a9792f375581307a0c60d7f985c19aa6b439.tar.gz |
This is libcap-2.00.libcap-2.00
This revision of libcap has support for 32-bit and 64-bit capabilities.
It also supports filesystem capabilities of both sizes.
-rw-r--r-- | Make.Rules | 6 | ||||
-rw-r--r-- | libcap/cap_file.c | 31 | ||||
-rw-r--r-- | libcap/include/linux/capability.h | 472 | ||||
-rw-r--r-- | libcap/libcap.h | 9 | ||||
-rw-r--r-- | pam_cap/Makefile | 9 |
5 files changed, 512 insertions, 15 deletions
@@ -40,8 +40,8 @@ LIBDIR=$(FAKEROOT)$(lib_prefix)/$(lib) # common defines for libcap LIBTITLE=libcap -VERSION=1 -MINOR=99 +VERSION=2 +MINOR=00 # # Compilation specifics @@ -56,7 +56,7 @@ WARNINGS=-fPIC -Wall -Wwrite-strings \ LD=$(CC) -Wl,-x -shared LDFLAGS=#-g -KERNEL_HEADERS = /usr/include +KERNEL_HEADERS = $(topdir)/libcap/include SYSTEM_HEADERS = /usr/include IPATH += -I$(topdir)/libcap/include -I$(KERNEL_HEADERS) INCS=$(topdir)/libcap/include/sys/capability.h diff --git a/libcap/cap_file.c b/libcap/cap_file.c index f1020a9..16b2f73 100644 --- a/libcap/cap_file.c +++ b/libcap/cap_file.c @@ -13,6 +13,7 @@ #include "libcap.h" #ifdef VFS_CAP_U32 + #if VFS_CAP_U32 != __CAP_BLKS # error VFS representation of capabilities is not the same size as kernel #endif @@ -23,7 +24,8 @@ #define FIXUP_32BITS(x) (x) #endif -static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result) +static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result, + int bytes) { __u32 magic_etc; unsigned tocopy, i; @@ -33,12 +35,14 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result) #ifdef VFS_CAP_REVISION_1 case VFS_CAP_REVISION_1: tocopy = VFS_CAP_U32_1; + bytes -= XATTR_CAPS_SZ_1; break; #endif #ifdef VFS_CAP_REVISION_2 case VFS_CAP_REVISION_2: tocopy = VFS_CAP_U32_2; + bytes -= XATTR_CAPS_SZ_2; break; #endif @@ -48,6 +52,15 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result) return result; } + /* + * Verify that we loaded exactly the right number of bytes + */ + if (bytes != 0) { + cap_free(result); + result = NULL; + return result; + } + for (i=0; i < tocopy; i++) { result->u[i].flat[CAP_INHERITABLE] = FIXUP_32BITS(rawvfscap->data[i].inheritable); @@ -154,16 +167,18 @@ cap_t cap_get_fd(int fildes) result = cap_init(); if (result) { struct vfs_cap_data rawvfscap; + int sizeofcaps; _cap_debug("getting fildes capabilities"); /* fill the capability sets via a system call */ - if (sizeof(rawvfscap) != fgetxattr(fildes, XATTR_NAME_CAPS, - &rawvfscap, sizeof(rawvfscap))) { + sizeofcaps = fgetxattr(fildes, XATTR_NAME_CAPS, + &rawvfscap, sizeof(rawvfscap)); + if (sizeofcaps < sizeof(rawvfscap.magic_etc)) { cap_free(result); result = NULL; } else { - result = _fcaps_load(&rawvfscap, result); + result = _fcaps_load(&rawvfscap, result, sizeofcaps); } } @@ -182,16 +197,18 @@ cap_t cap_get_file(const char *filename) result = cap_init(); if (result) { struct vfs_cap_data rawvfscap; + int sizeofcaps; _cap_debug("getting filename capabilities"); /* fill the capability sets via a system call */ - if (sizeof(rawvfscap) != getxattr(filename, XATTR_NAME_CAPS, - &rawvfscap, sizeof(rawvfscap))) { + sizeofcaps = getxattr(filename, XATTR_NAME_CAPS, + &rawvfscap, sizeof(rawvfscap)); + if (sizeofcaps < sizeof(rawvfscap.magic_etc)) { cap_free(result); result = NULL; } else { - result = _fcaps_load(&rawvfscap, result); + result = _fcaps_load(&rawvfscap, result, sizeofcaps); } } diff --git a/libcap/include/linux/capability.h b/libcap/include/linux/capability.h new file mode 100644 index 0000000..94663b4 --- /dev/null +++ b/libcap/include/linux/capability.h @@ -0,0 +1,472 @@ +/* + * This is <linux/capability.h> + * + * Andrew G. Morgan <morgan@kernel.org> + * Alexander Kjeldaas <astor@guardian.no> + * with help from Aleph1, Roland Buresund and Andrew Main. + * + * See here for the libcap library ("POSIX draft" compliance): + * + * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/ + */ + +#ifndef _LINUX_CAPABILITY_H +#define _LINUX_CAPABILITY_H + +#include <linux/types.h> +#include <linux/compiler.h> + +struct task_struct; + +/* User-level do most of the mapping between kernel and user + capabilities based on the version tag given by the kernel. The + kernel might be somewhat backwards compatible, but don't bet on + it. */ + +/* Note, cap_t, is defined by POSIX (draft) to be an "opaque" pointer to + a set of three capability sets. The transposition of 3*the + following structure to such a composite is better handled in a user + library since the draft standard requires the use of malloc/free + etc.. */ + +#define _LINUX_CAPABILITY_VERSION_1 0x19980330 +#define _LINUX_CAPABILITY_U32S_1 1 + +#define _LINUX_CAPABILITY_VERSION_2 0x20071026 +#define _LINUX_CAPABILITY_U32S_2 2 + +#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2 +#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_2 + +typedef struct __user_cap_header_struct { + __u32 version; + int pid; +} __user *cap_user_header_t; + +typedef struct __user_cap_data_struct { + __u32 effective; + __u32 permitted; + __u32 inheritable; +} __user *cap_user_data_t; + + +#define XATTR_CAPS_SUFFIX "capability" +#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX + +#define VFS_CAP_REVISION_MASK 0xFF000000 +#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK +#define VFS_CAP_FLAGS_EFFECTIVE 0x000001 + +#define VFS_CAP_REVISION_1 0x01000000 +#define VFS_CAP_U32_1 1 +#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1)) + +#define VFS_CAP_REVISION_2 0x02000000 +#define VFS_CAP_U32_2 2 +#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2)) + +#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2 +#define VFS_CAP_U32 VFS_CAP_U32_2 +#define VFS_CAP_REVISION VFS_CAP_REVISION_2 + + +struct vfs_cap_data { + __le32 magic_etc; /* Little endian */ + struct { + __le32 permitted; /* Little endian */ + __le32 inheritable; /* Little endian */ + } data[VFS_CAP_U32]; +}; + +#ifdef __KERNEL__ + +typedef struct kernel_cap_struct { + __u32 cap[_LINUX_CAPABILITY_U32S]; +} kernel_cap_t; + +#define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct)) +#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t)) + +#endif + + +/** + ** POSIX-draft defined capabilities. + **/ + +/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this + overrides the restriction of changing file ownership and group + ownership. */ + +#define CAP_CHOWN 0 + +/* Override all DAC access, including ACL execute access if + [_POSIX_ACL] is defined. Excluding DAC access covered by + CAP_LINUX_IMMUTABLE. */ + +#define CAP_DAC_OVERRIDE 1 + +/* Overrides all DAC restrictions regarding read and search on files + and directories, including ACL restrictions if [_POSIX_ACL] is + defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */ + +#define CAP_DAC_READ_SEARCH 2 + +/* Overrides all restrictions about allowed operations on files, where + file owner ID must be equal to the user ID, except where CAP_FSETID + is applicable. It doesn't override MAC and DAC restrictions. */ + +#define CAP_FOWNER 3 + +/* Overrides the following restrictions that the effective user ID + shall match the file owner ID when setting the S_ISUID and S_ISGID + bits on that file; that the effective group ID (or one of the + supplementary group IDs) shall match the file owner ID when setting + the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are + cleared on successful return from chown(2) (not implemented). */ + +#define CAP_FSETID 4 + +/* Overrides the restriction that the real or effective user ID of a + process sending a signal must match the real or effective user ID + of the process receiving the signal. */ + +#define CAP_KILL 5 + +/* Allows setgid(2) manipulation */ +/* Allows setgroups(2) */ +/* Allows forged gids on socket credentials passing. */ + +#define CAP_SETGID 6 + +/* Allows set*uid(2) manipulation (including fsuid). */ +/* Allows forged pids on socket credentials passing. */ + +#define CAP_SETUID 7 + + +/** + ** Linux-specific capabilities + **/ + +/* Without VFS support for capabilities: + * Transfer any capability in your permitted set to any pid, + * remove any capability in your permitted set from any pid + * With VFS support for capabilities (neither of above, but) + * Add any capability to the current process' inheritable set + */ + +#define CAP_SETPCAP 8 + +/* Allow modification of S_IMMUTABLE and S_APPEND file attributes */ + +#define CAP_LINUX_IMMUTABLE 9 + +/* Allows binding to TCP/UDP sockets below 1024 */ +/* Allows binding to ATM VCIs below 32 */ + +#define CAP_NET_BIND_SERVICE 10 + +/* Allow broadcasting, listen to multicast */ + +#define CAP_NET_BROADCAST 11 + +/* Allow interface configuration */ +/* Allow administration of IP firewall, masquerading and accounting */ +/* Allow setting debug option on sockets */ +/* Allow modification of routing tables */ +/* Allow setting arbitrary process / process group ownership on + sockets */ +/* Allow binding to any address for transparent proxying */ +/* Allow setting TOS (type of service) */ +/* Allow setting promiscuous mode */ +/* Allow clearing driver statistics */ +/* Allow multicasting */ +/* Allow read/write of device-specific registers */ +/* Allow activation of ATM control sockets */ + +#define CAP_NET_ADMIN 12 + +/* Allow use of RAW sockets */ +/* Allow use of PACKET sockets */ + +#define CAP_NET_RAW 13 + +/* Allow locking of shared memory segments */ +/* Allow mlock and mlockall (which doesn't really have anything to do + with IPC) */ + +#define CAP_IPC_LOCK 14 + +/* Override IPC ownership checks */ + +#define CAP_IPC_OWNER 15 + +/* Insert and remove kernel modules - modify kernel without limit */ +/* Modify cap_bset */ +#define CAP_SYS_MODULE 16 + +/* Allow ioperm/iopl access */ +/* Allow sending USB messages to any device via /proc/bus/usb */ + +#define CAP_SYS_RAWIO 17 + +/* Allow use of chroot() */ + +#define CAP_SYS_CHROOT 18 + +/* Allow ptrace() of any process */ + +#define CAP_SYS_PTRACE 19 + +/* Allow configuration of process accounting */ + +#define CAP_SYS_PACCT 20 + +/* Allow configuration of the secure attention key */ +/* Allow administration of the random device */ +/* Allow examination and configuration of disk quotas */ +/* Allow configuring the kernel's syslog (printk behaviour) */ +/* Allow setting the domainname */ +/* Allow setting the hostname */ +/* Allow calling bdflush() */ +/* Allow mount() and umount(), setting up new smb connection */ +/* Allow some autofs root ioctls */ +/* Allow nfsservctl */ +/* Allow VM86_REQUEST_IRQ */ +/* Allow to read/write pci config on alpha */ +/* Allow irix_prctl on mips (setstacksize) */ +/* Allow flushing all cache on m68k (sys_cacheflush) */ +/* Allow removing semaphores */ +/* Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores + and shared memory */ +/* Allow locking/unlocking of shared memory segment */ +/* Allow turning swap on/off */ +/* Allow forged pids on socket credentials passing */ +/* Allow setting readahead and flushing buffers on block devices */ +/* Allow setting geometry in floppy driver */ +/* Allow turning DMA on/off in xd driver */ +/* Allow administration of md devices (mostly the above, but some + extra ioctls) */ +/* Allow tuning the ide driver */ +/* Allow access to the nvram device */ +/* Allow administration of apm_bios, serial and bttv (TV) device */ +/* Allow manufacturer commands in isdn CAPI support driver */ +/* Allow reading non-standardized portions of pci configuration space */ +/* Allow DDI debug ioctl on sbpcd driver */ +/* Allow setting up serial ports */ +/* Allow sending raw qic-117 commands */ +/* Allow enabling/disabling tagged queuing on SCSI controllers and sending + arbitrary SCSI commands */ +/* Allow setting encryption key on loopback filesystem */ +/* Allow setting zone reclaim policy */ + +#define CAP_SYS_ADMIN 21 + +/* Allow use of reboot() */ + +#define CAP_SYS_BOOT 22 + +/* Allow raising priority and setting priority on other (different + UID) processes */ +/* Allow use of FIFO and round-robin (realtime) scheduling on own + processes and setting the scheduling algorithm used by another + process. */ +/* Allow setting cpu affinity on other processes */ + +#define CAP_SYS_NICE 23 + +/* Override resource limits. Set resource limits. */ +/* Override quota limits. */ +/* Override reserved space on ext2 filesystem */ +/* Modify data journaling mode on ext3 filesystem (uses journaling + resources) */ +/* NOTE: ext2 honors fsuid when checking for resource overrides, so + you can override using fsuid too */ +/* Override size restrictions on IPC message queues */ +/* Allow more than 64hz interrupts from the real-time clock */ +/* Override max number of consoles on console allocation */ +/* Override max number of keymaps */ + +#define CAP_SYS_RESOURCE 24 + +/* Allow manipulation of system clock */ +/* Allow irix_stime on mips */ +/* Allow setting the real-time clock */ + +#define CAP_SYS_TIME 25 + +/* Allow configuration of tty devices */ +/* Allow vhangup() of tty */ + +#define CAP_SYS_TTY_CONFIG 26 + +/* Allow the privileged aspects of mknod() */ + +#define CAP_MKNOD 27 + +/* Allow taking of leases on files */ + +#define CAP_LEASE 28 + +#define CAP_AUDIT_WRITE 29 + +#define CAP_AUDIT_CONTROL 30 + +#define CAP_SETFCAP 31 + +/* + * Bit location of each capability (used by user-space library and kernel) + */ + +#define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */ +#define CAP_TO_MASK(x) (1 << ((x) & 31)) /* mask for indexed __u32 */ + +#ifdef __KERNEL__ + +/* + * Internal kernel functions only + */ + +#define CAP_FOR_EACH_U32(__capi) \ + for (__capi=0; __capi<_LINUX_CAPABILITY_U32S; ++__capi) + +# define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \ + |CAP_TO_MASK(CAP_DAC_OVERRIDE) \ + |CAP_TO_MASK(CAP_DAC_READ_SEARCH) \ + |CAP_TO_MASK(CAP_FOWNER) \ + |CAP_TO_MASK(CAP_FSETID)) + +#if _LINUX_CAPABILITY_U32S != 2 +# error Fix up hand-coded capability macro initializers +#else /* HAND-CODED capability initializers */ + +# define CAP_EMPTY_SET {{ 0, 0 }} +# define CAP_FULL_SET {{ ~0, ~0 }} +# define CAP_INIT_EFF_SET {{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }} +# define CAP_FS_SET {{ CAP_FS_MASK_B0, 0 }} +# define CAP_NFSD_SET {{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), 0 }} + +#endif /* _LINUX_CAPABILITY_U32S != 2 */ + +#define CAP_INIT_INH_SET CAP_EMPTY_SET + +# define cap_clear(c) do { (c) = __cap_empty_set; } while (0) +# define cap_set_full(c) do { (c) = __cap_full_set; } while (0) +# define cap_set_init_eff(c) do { (c) = __cap_init_eff_set; } while (0) + +#define cap_raise(c,flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) +#define cap_lower(c,flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) +#define cap_raised(c,flag) ((c).cap[CAP_TO_INDEX(flag)] & CAP_TO_MASK(flag)) + +#define CAP_BOP_ALL(c, a, b, OP) \ +do { \ + unsigned __capi; \ + CAP_FOR_EACH_U32(__capi) { \ + c.cap[__capi] = a.cap[__capi] OP b.cap[__capi]; \ + } \ +} while (0) + +#define CAP_UOP_ALL(c, a, OP) \ +do { \ + unsigned __capi; \ + CAP_FOR_EACH_U32(__capi) { \ + c.cap[__capi] = OP a.cap[__capi]; \ + } \ +} while (0) + +static inline kernel_cap_t cap_combine(const kernel_cap_t a, + const kernel_cap_t b) +{ + kernel_cap_t dest; + CAP_BOP_ALL(dest, a, b, |); + return dest; +} + +static inline kernel_cap_t cap_intersect(const kernel_cap_t a, + const kernel_cap_t b) +{ + kernel_cap_t dest; + CAP_BOP_ALL(dest, a, b, &); + return dest; +} + +static inline kernel_cap_t cap_drop(const kernel_cap_t a, + const kernel_cap_t drop) +{ + kernel_cap_t dest; + CAP_BOP_ALL(dest, a, drop, &~); + return dest; +} + +static inline kernel_cap_t cap_invert(const kernel_cap_t c) +{ + kernel_cap_t dest; + CAP_UOP_ALL(dest, c, ~); + return dest; +} + +static inline int cap_isclear(const kernel_cap_t a) +{ + unsigned __capi; + CAP_FOR_EACH_U32(__capi) { + if (a.cap[__capi] != 0) { + return 0; + } + } + return 1; +} + +static inline int cap_issubset(const kernel_cap_t a, const kernel_cap_t set) +{ + kernel_cap_t dest; + dest = cap_drop(a, set); + return cap_isclear(dest); +} + +/* Used to decide between falling back on the old suser() or fsuser(). */ + +static inline int cap_is_fs_cap(int cap) +{ + const kernel_cap_t __cap_fs_set = CAP_FS_SET; + return !!(CAP_TO_MASK(cap) & __cap_fs_set.cap[CAP_TO_INDEX(cap)]); +} + +static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a) +{ + const kernel_cap_t __cap_fs_set = CAP_FS_SET; + return cap_drop(a, __cap_fs_set); +} + +static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a, + const kernel_cap_t permitted) +{ + const kernel_cap_t __cap_fs_set = CAP_FS_SET; + return cap_combine(a, + cap_intersect(permitted, __cap_fs_set)); +} + +static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a) +{ + const kernel_cap_t __cap_fs_set = CAP_NFSD_SET; + return cap_drop(a, __cap_fs_set); +} + +static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a, + const kernel_cap_t permitted) +{ + const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET; + return cap_combine(a, + cap_intersect(permitted, __cap_nfsd_set)); +} + +extern const kernel_cap_t __cap_empty_set; +extern const kernel_cap_t __cap_full_set; +extern const kernel_cap_t __cap_init_eff_set; + +int capable(int cap); +int __capable(struct task_struct *t, int cap); + +#endif /* __KERNEL__ */ + +#endif /* !_LINUX_CAPABILITY_H */ diff --git a/libcap/libcap.h b/libcap/libcap.h index 820d61a..0e4a167 100644 --- a/libcap/libcap.h +++ b/libcap/libcap.h @@ -60,12 +60,13 @@ */ #ifndef _LINUX_CAPABILITY_U32S -# define _LINUX_CAPABILITY_U32S 1 +# define _LINUX_CAPABILITY_U32S 1 #endif /* ndef _LINUX_CAPABILITY_U32S */ #if defined(VFS_CAP_REVISION_MASK) && !defined(VFS_CAP_U32) -# define VFS_CAP_U32_1 1 -# define VFS_CAP_U32 VFS_CAP_U32_1 +# define VFS_CAP_U32_1 1 +# define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1)) +# define VFS_CAP_U32 VFS_CAP_U32_1 struct _cap_vfs_cap_data { __le32 magic_etc; struct { @@ -73,7 +74,7 @@ struct _cap_vfs_cap_data { __le32 inheritable; } data[VFS_CAP_U32_1]; }; -# define vfs_cap_data _cap_vfs_cap_data +# define vfs_cap_data _cap_vfs_cap_data #endif #ifndef CAP_TO_INDEX diff --git a/pam_cap/Makefile b/pam_cap/Makefile index 453b63c..3b3d266 100644 --- a/pam_cap/Makefile +++ b/pam_cap/Makefile @@ -6,6 +6,13 @@ include ../Make.Rules all: pam_cap.so $(MAKE) testcompile +install: + @echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + @echo "X X" + @echo "X Need to figure out where to install pam_cap.so X" + @echo "X X" + @echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + pam_cap.so: pam_cap.o $(LD) -o pam_cap.so $< $(LIBS) @@ -16,4 +23,4 @@ testcompile: test.c pam_cap.o $(CC) $(CFLAGS) -o $@ $+ -lpam -ldl $(LIBS) clean: - rm -f *.o *.so testcompile + rm -f *.o *.so testcompile *~ |