-
Notifications
You must be signed in to change notification settings - Fork 7
/
caplib.c
138 lines (106 loc) · 2.63 KB
/
caplib.c
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
/* Tony Cheneau <tony.cheneau@nist.gov> */
/* This software was developed by employees of the National Institute of
Standards and Technology (NIST), and others.
This software has been contributed to the public domain.
Pursuant to title 15 Untied States Code Section 105, works of NIST
employees are not subject to copyright protection in the United States
and are considered to be in the public domain.
As a result, a formal license is not needed to use this software.
This software is provided "AS IS."
NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
AND DATA ACCURACY. NIST does not warrant or make any representations
regarding the use of the software or the results thereof, including but
not limited to the correctness, accuracy, reliability or usefulness of
this software. */
/* this code is heavily borrowed from the iputils project */
#include "caplib.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <asm-generic/errno-base.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
static int uid;
static uid_t euid;
int limit_capabilities(void)
{
cap_t cap_p;
const cap_value_t caps[] = {
CAP_NET_ADMIN,
CAP_NET_RAW,
};
int i;
cap_p = cap_init();
if (!cap_p) {
perror("cap_get_proc");
return -1;
}
for (i = 0; i < ARRAY_SIZE(caps); i++) {
if (cap_clear(cap_p) < 0) {
perror("cap_clear");
return -1;
}
if (cap_set_flag(cap_p, CAP_PERMITTED, ARRAY_SIZE(caps) - i, caps + i, CAP_SET) < 0) {
perror("cap_set_flag");
return -1;
}
if (cap_set_proc(cap_p) < 0)
continue;
break;
}
if (i == ARRAY_SIZE(caps)) {
perror("cap_set_proc");
if (errno != EPERM)
return -1;
}
if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
perror("prctl");
return -1;
}
if (setuid(getuid()) < 0) {
perror("setuid");
return -1;
}
if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
perror("prctl");
return -1;
}
cap_free(cap_p);
uid = getuid();
euid = geteuid();
return 0;
}
int modify_capability(cap_value_t cap, cap_flag_value_t on)
{
cap_t cap_p = cap_get_proc();
if (!cap_p) {
perror("cap_get_proc");
return -1;
}
if (cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &cap, on) < 0) {
perror("cap_set_flag");
return -1;
}
if (cap_set_proc(cap_p) < 0) {
perror("cap_set_proc");
return -1;
}
if (cap_free(cap_p) < 0) {
perror("cap_free");
return -1;
}
return 0;
}
int drop_capabilities(void)
{
cap_t cap = cap_init();
if (cap_set_proc(cap) < 0) {
perror("cap_set_proc");
return -1;
}
cap_free(cap);
return 0;
}