1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
/*
* $Id: cap_sys.c,v 1.1.1.1.4.2 2001/01/16 07:38:25 agmorgan Exp $
*
* Copyright (c) 1997-2000 Andrew G. Morgan <morgan@linux.kernel.org>
*
* This file contains the system calls for getting and setting
* capabilities
*/
#include "libcap.h"
#define __LIBRARY__
#if !defined(__GLIBC__) || __GLIBC__ < 2 || __GLIBC_MINOR__ < 2
#include <linux/unistd.h>
_syscall2(int, capget,
cap_user_header_t, header,
cap_user_data_t, data)
_syscall2(int, capset,
cap_user_header_t, header,
const cap_user_data_t, data)
#endif
/* library defaults to agreeing with the kernel under which it was
compiled */
unsigned int _libcap_kernel_version = 0;
unsigned int _libcap_kernel_features = 0;
/* internally resync the library's idea of the kernel api */
void _libcap_establish_api(void)
{
struct __user_cap_header_struct ch;
struct __user_cap_data_struct cs;
if (_libcap_kernel_version) {
_cap_debug("already identified kernal api 0x%.8x",
_libcap_kernel_version);
return;
}
memset(&ch, 0, sizeof(ch));
memset(&cs, 0, sizeof(cs));
(void) capget(&ch, &cs);
switch (ch.version) {
case 0x19980330:
_libcap_kernel_version = 0x19980330;
_libcap_kernel_features = CAP_FEATURE_PROC|CAP_FEATURE_TO_32;
break;
case 0x20000603:
_libcap_kernel_version = 0x20000603;
_libcap_kernel_features =
CAP_FEATURE_PROC|CAP_FEATURE_FILE|CAP_FEATURE_TO_32;
break;
case 0x20010113:
_libcap_kernel_version = 0x20010113;
_libcap_kernel_features = CAP_FEATURE_PROC|CAP_FEATURE_FILE;
break;
default:
_libcap_kernel_version = 0x00000000;
_libcap_kernel_features = 0x00000000;
}
_cap_debug("(%x) version: %x, features: %x\n", ch.version,
_libcap_kernel_version, _libcap_kernel_features);
}
/*
* This library has been compiled for n=__CAP_BLKS __u32's per cap
* set this may not agree with the kernel that this library is
* running against. As such, we allow for dynamic compensation for
* what the kernel gives/expects with this routine.
*/
int _libcap_n1_to_n2(cap_t cap_d, int n1, int n2)
{
if (!good_cap_t(cap_d)) {
_cap_debug("invalid cap_d");
errno = EINVAL;
return -1;
}
if (n1 > __CAP_BLKS) {
_cap_debug("n1 = %d vs %d --> too large", n1, __CAP_BLKS);
errno = EINVAL;
return -1;
}
if (n2 > __CAP_BLKS) {
_cap_debug("n2 = %d vs %d --> too large", n2, __CAP_BLKS);
errno = EINVAL;
return -1;
}
if (n1 <= 0 || n2 <= 0) {
errno = EINVAL;
return -1;
}
if (n1 > n2) {
/* we need to compress */
__u32 *src, *dest;
int i, j;
src = n1 + (__u32 *) &cap_d->set;
dest = n2 + (__u32 *) &cap_d->set;
for (i=1; i<3; ++i) {
for (j=0; j<n2; ++j) {
dest[j] = src[j];
}
dest += n2;
src += n1;
}
memset(dest, 0, (__CAP_BLKS - n2) * 3 * sizeof(__u32));
} else if (n1 < n2) {
/* we need to expand */
__u32 *src, *dest;
int i, j;
src = 2*n1 + (__u32 *) &cap_d->set;
dest = 2*n2 + (__u32 *) &cap_d->set;
for (i=1; i<3; ++i) {
for (j=0; j<n1; ++j) {
dest[j] = src[j];
}
while (j<n2) {
dest[j++] = 0;
}
dest -= n2;
src -= n1;
}
memset(dest, 0, (__CAP_BLKS - n2) * 3 * sizeof(__u32));
} else {
/* nothing to do */
_cap_debug("called for no reason (%d)", n1);
}
return 0;
}
|