File: cap_sys.c

package info (click to toggle)
libcap2 0.cvs.20010529-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 496 kB
  • ctags: 240
  • sloc: ansic: 1,606; makefile: 147
file content (151 lines) | stat: -rw-r--r-- 3,286 bytes parent folder | download | duplicates (2)
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;
}