1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker * sestatus.c
3*2d543d20SAndroid Build Coastguard Worker *
4*2d543d20SAndroid Build Coastguard Worker * APIs to reference SELinux kernel status page (/selinux/status)
5*2d543d20SAndroid Build Coastguard Worker *
6*2d543d20SAndroid Build Coastguard Worker * Author: KaiGai Kohei <[email protected]>
7*2d543d20SAndroid Build Coastguard Worker *
8*2d543d20SAndroid Build Coastguard Worker */
9*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
10*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
11*2d543d20SAndroid Build Coastguard Worker #include <sched.h>
12*2d543d20SAndroid Build Coastguard Worker #include <sys/mman.h>
13*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
14*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
15*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
16*2d543d20SAndroid Build Coastguard Worker #include "avc_internal.h"
17*2d543d20SAndroid Build Coastguard Worker #include "policy.h"
18*2d543d20SAndroid Build Coastguard Worker
19*2d543d20SAndroid Build Coastguard Worker /*
20*2d543d20SAndroid Build Coastguard Worker * copied from the selinux/include/security.h
21*2d543d20SAndroid Build Coastguard Worker */
22*2d543d20SAndroid Build Coastguard Worker struct selinux_status_t
23*2d543d20SAndroid Build Coastguard Worker {
24*2d543d20SAndroid Build Coastguard Worker uint32_t version; /* version number of this structure */
25*2d543d20SAndroid Build Coastguard Worker uint32_t sequence; /* sequence number of seqlock logic */
26*2d543d20SAndroid Build Coastguard Worker uint32_t enforcing; /* current setting of enforcing mode */
27*2d543d20SAndroid Build Coastguard Worker uint32_t policyload; /* times of policy reloaded */
28*2d543d20SAndroid Build Coastguard Worker uint32_t deny_unknown; /* current setting of deny_unknown */
29*2d543d20SAndroid Build Coastguard Worker /* version > 0 support above status */
30*2d543d20SAndroid Build Coastguard Worker } __attribute((packed));
31*2d543d20SAndroid Build Coastguard Worker
32*2d543d20SAndroid Build Coastguard Worker /*
33*2d543d20SAndroid Build Coastguard Worker * `selinux_status'
34*2d543d20SAndroid Build Coastguard Worker *
35*2d543d20SAndroid Build Coastguard Worker * NULL : not initialized yet
36*2d543d20SAndroid Build Coastguard Worker * MAP_FAILED : opened, but fallback-mode
37*2d543d20SAndroid Build Coastguard Worker * Valid Pointer : opened and mapped correctly
38*2d543d20SAndroid Build Coastguard Worker */
39*2d543d20SAndroid Build Coastguard Worker static struct selinux_status_t *selinux_status = NULL;
40*2d543d20SAndroid Build Coastguard Worker static uint32_t last_seqno;
41*2d543d20SAndroid Build Coastguard Worker static uint32_t last_policyload;
42*2d543d20SAndroid Build Coastguard Worker
43*2d543d20SAndroid Build Coastguard Worker static uint32_t fallback_sequence;
44*2d543d20SAndroid Build Coastguard Worker static int fallback_enforcing;
45*2d543d20SAndroid Build Coastguard Worker static int fallback_policyload;
46*2d543d20SAndroid Build Coastguard Worker
47*2d543d20SAndroid Build Coastguard Worker static void *fallback_netlink_thread = NULL;
48*2d543d20SAndroid Build Coastguard Worker
49*2d543d20SAndroid Build Coastguard Worker /*
50*2d543d20SAndroid Build Coastguard Worker * read_sequence
51*2d543d20SAndroid Build Coastguard Worker *
52*2d543d20SAndroid Build Coastguard Worker * A utility routine to reference kernel status page according to
53*2d543d20SAndroid Build Coastguard Worker * seqlock logic. Since selinux_status->sequence is an odd value during
54*2d543d20SAndroid Build Coastguard Worker * the kernel status page being updated, we try to synchronize completion
55*2d543d20SAndroid Build Coastguard Worker * of this updating, but we assume it is rare.
56*2d543d20SAndroid Build Coastguard Worker * The sequence is almost even number.
57*2d543d20SAndroid Build Coastguard Worker *
58*2d543d20SAndroid Build Coastguard Worker * __sync_synchronize is a portable memory barrier for various kind
59*2d543d20SAndroid Build Coastguard Worker * of architecture that is supported by GCC.
60*2d543d20SAndroid Build Coastguard Worker */
read_sequence(struct selinux_status_t * status)61*2d543d20SAndroid Build Coastguard Worker static inline uint32_t read_sequence(struct selinux_status_t *status)
62*2d543d20SAndroid Build Coastguard Worker {
63*2d543d20SAndroid Build Coastguard Worker uint32_t seqno = 0;
64*2d543d20SAndroid Build Coastguard Worker
65*2d543d20SAndroid Build Coastguard Worker do {
66*2d543d20SAndroid Build Coastguard Worker /*
67*2d543d20SAndroid Build Coastguard Worker * No need for sched_yield() in the first trial of
68*2d543d20SAndroid Build Coastguard Worker * this loop.
69*2d543d20SAndroid Build Coastguard Worker */
70*2d543d20SAndroid Build Coastguard Worker if (seqno & 0x0001)
71*2d543d20SAndroid Build Coastguard Worker sched_yield();
72*2d543d20SAndroid Build Coastguard Worker
73*2d543d20SAndroid Build Coastguard Worker seqno = status->sequence;
74*2d543d20SAndroid Build Coastguard Worker
75*2d543d20SAndroid Build Coastguard Worker __sync_synchronize();
76*2d543d20SAndroid Build Coastguard Worker
77*2d543d20SAndroid Build Coastguard Worker } while (seqno & 0x0001);
78*2d543d20SAndroid Build Coastguard Worker
79*2d543d20SAndroid Build Coastguard Worker return seqno;
80*2d543d20SAndroid Build Coastguard Worker }
81*2d543d20SAndroid Build Coastguard Worker
82*2d543d20SAndroid Build Coastguard Worker /*
83*2d543d20SAndroid Build Coastguard Worker * selinux_status_updated
84*2d543d20SAndroid Build Coastguard Worker *
85*2d543d20SAndroid Build Coastguard Worker * It returns whether something has been happened since the last call.
86*2d543d20SAndroid Build Coastguard Worker * Because `selinux_status->sequence' shall be always incremented on
87*2d543d20SAndroid Build Coastguard Worker * both of setenforce/policyreload events, so differences from the last
88*2d543d20SAndroid Build Coastguard Worker * value informs us something has been happened.
89*2d543d20SAndroid Build Coastguard Worker */
selinux_status_updated(void)90*2d543d20SAndroid Build Coastguard Worker int selinux_status_updated(void)
91*2d543d20SAndroid Build Coastguard Worker {
92*2d543d20SAndroid Build Coastguard Worker uint32_t curr_seqno;
93*2d543d20SAndroid Build Coastguard Worker uint32_t tmp_seqno;
94*2d543d20SAndroid Build Coastguard Worker uint32_t enforcing;
95*2d543d20SAndroid Build Coastguard Worker uint32_t policyload;
96*2d543d20SAndroid Build Coastguard Worker
97*2d543d20SAndroid Build Coastguard Worker if (selinux_status == NULL) {
98*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
99*2d543d20SAndroid Build Coastguard Worker return -1;
100*2d543d20SAndroid Build Coastguard Worker }
101*2d543d20SAndroid Build Coastguard Worker
102*2d543d20SAndroid Build Coastguard Worker if (selinux_status == MAP_FAILED) {
103*2d543d20SAndroid Build Coastguard Worker if (avc_netlink_check_nb() < 0)
104*2d543d20SAndroid Build Coastguard Worker return -1;
105*2d543d20SAndroid Build Coastguard Worker
106*2d543d20SAndroid Build Coastguard Worker curr_seqno = fallback_sequence;
107*2d543d20SAndroid Build Coastguard Worker } else {
108*2d543d20SAndroid Build Coastguard Worker curr_seqno = read_sequence(selinux_status);
109*2d543d20SAndroid Build Coastguard Worker }
110*2d543d20SAndroid Build Coastguard Worker
111*2d543d20SAndroid Build Coastguard Worker /*
112*2d543d20SAndroid Build Coastguard Worker * `curr_seqno' is always even-number, so it does not match with
113*2d543d20SAndroid Build Coastguard Worker * `last_seqno' being initialized to odd-number in the first call.
114*2d543d20SAndroid Build Coastguard Worker * We never return 'something was updated' in the first call,
115*2d543d20SAndroid Build Coastguard Worker * because this function focuses on status-updating since the last
116*2d543d20SAndroid Build Coastguard Worker * invocation.
117*2d543d20SAndroid Build Coastguard Worker */
118*2d543d20SAndroid Build Coastguard Worker if (last_seqno & 0x0001)
119*2d543d20SAndroid Build Coastguard Worker last_seqno = curr_seqno;
120*2d543d20SAndroid Build Coastguard Worker
121*2d543d20SAndroid Build Coastguard Worker if (last_seqno == curr_seqno)
122*2d543d20SAndroid Build Coastguard Worker return 0;
123*2d543d20SAndroid Build Coastguard Worker
124*2d543d20SAndroid Build Coastguard Worker /* sequence must not be changed during references */
125*2d543d20SAndroid Build Coastguard Worker do {
126*2d543d20SAndroid Build Coastguard Worker enforcing = selinux_status->enforcing;
127*2d543d20SAndroid Build Coastguard Worker policyload = selinux_status->policyload;
128*2d543d20SAndroid Build Coastguard Worker tmp_seqno = curr_seqno;
129*2d543d20SAndroid Build Coastguard Worker curr_seqno = read_sequence(selinux_status);
130*2d543d20SAndroid Build Coastguard Worker } while (tmp_seqno != curr_seqno);
131*2d543d20SAndroid Build Coastguard Worker
132*2d543d20SAndroid Build Coastguard Worker if (avc_enforcing != (int) enforcing) {
133*2d543d20SAndroid Build Coastguard Worker if (avc_process_setenforce(enforcing) < 0)
134*2d543d20SAndroid Build Coastguard Worker return -1;
135*2d543d20SAndroid Build Coastguard Worker }
136*2d543d20SAndroid Build Coastguard Worker if (last_policyload != policyload) {
137*2d543d20SAndroid Build Coastguard Worker if (avc_process_policyload(policyload) < 0)
138*2d543d20SAndroid Build Coastguard Worker return -1;
139*2d543d20SAndroid Build Coastguard Worker last_policyload = policyload;
140*2d543d20SAndroid Build Coastguard Worker }
141*2d543d20SAndroid Build Coastguard Worker last_seqno = curr_seqno;
142*2d543d20SAndroid Build Coastguard Worker
143*2d543d20SAndroid Build Coastguard Worker return 1;
144*2d543d20SAndroid Build Coastguard Worker }
145*2d543d20SAndroid Build Coastguard Worker
146*2d543d20SAndroid Build Coastguard Worker /*
147*2d543d20SAndroid Build Coastguard Worker * selinux_status_getenforce
148*2d543d20SAndroid Build Coastguard Worker *
149*2d543d20SAndroid Build Coastguard Worker * It returns the current performing mode of SELinux.
150*2d543d20SAndroid Build Coastguard Worker * 1 means currently we run in enforcing mode, or 0 means permissive mode.
151*2d543d20SAndroid Build Coastguard Worker */
selinux_status_getenforce(void)152*2d543d20SAndroid Build Coastguard Worker int selinux_status_getenforce(void)
153*2d543d20SAndroid Build Coastguard Worker {
154*2d543d20SAndroid Build Coastguard Worker uint32_t seqno;
155*2d543d20SAndroid Build Coastguard Worker uint32_t enforcing;
156*2d543d20SAndroid Build Coastguard Worker
157*2d543d20SAndroid Build Coastguard Worker if (selinux_status == NULL) {
158*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
159*2d543d20SAndroid Build Coastguard Worker return -1;
160*2d543d20SAndroid Build Coastguard Worker }
161*2d543d20SAndroid Build Coastguard Worker
162*2d543d20SAndroid Build Coastguard Worker if (selinux_status == MAP_FAILED) {
163*2d543d20SAndroid Build Coastguard Worker if (avc_netlink_check_nb() < 0)
164*2d543d20SAndroid Build Coastguard Worker return -1;
165*2d543d20SAndroid Build Coastguard Worker
166*2d543d20SAndroid Build Coastguard Worker return fallback_enforcing;
167*2d543d20SAndroid Build Coastguard Worker }
168*2d543d20SAndroid Build Coastguard Worker
169*2d543d20SAndroid Build Coastguard Worker /* sequence must not be changed during references */
170*2d543d20SAndroid Build Coastguard Worker do {
171*2d543d20SAndroid Build Coastguard Worker seqno = read_sequence(selinux_status);
172*2d543d20SAndroid Build Coastguard Worker
173*2d543d20SAndroid Build Coastguard Worker enforcing = selinux_status->enforcing;
174*2d543d20SAndroid Build Coastguard Worker
175*2d543d20SAndroid Build Coastguard Worker } while (seqno != read_sequence(selinux_status));
176*2d543d20SAndroid Build Coastguard Worker
177*2d543d20SAndroid Build Coastguard Worker return enforcing ? 1 : 0;
178*2d543d20SAndroid Build Coastguard Worker }
179*2d543d20SAndroid Build Coastguard Worker
180*2d543d20SAndroid Build Coastguard Worker /*
181*2d543d20SAndroid Build Coastguard Worker * selinux_status_policyload
182*2d543d20SAndroid Build Coastguard Worker *
183*2d543d20SAndroid Build Coastguard Worker * It returns times of policy reloaded on the running system.
184*2d543d20SAndroid Build Coastguard Worker * Note that it is not a reliable value on fallback-mode until it receives
185*2d543d20SAndroid Build Coastguard Worker * the first event message via netlink socket, so, a correct usage of this
186*2d543d20SAndroid Build Coastguard Worker * value is to compare it with the previous value to detect policy reloaded
187*2d543d20SAndroid Build Coastguard Worker * event.
188*2d543d20SAndroid Build Coastguard Worker */
selinux_status_policyload(void)189*2d543d20SAndroid Build Coastguard Worker int selinux_status_policyload(void)
190*2d543d20SAndroid Build Coastguard Worker {
191*2d543d20SAndroid Build Coastguard Worker uint32_t seqno;
192*2d543d20SAndroid Build Coastguard Worker uint32_t policyload;
193*2d543d20SAndroid Build Coastguard Worker
194*2d543d20SAndroid Build Coastguard Worker if (selinux_status == NULL) {
195*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
196*2d543d20SAndroid Build Coastguard Worker return -1;
197*2d543d20SAndroid Build Coastguard Worker }
198*2d543d20SAndroid Build Coastguard Worker
199*2d543d20SAndroid Build Coastguard Worker if (selinux_status == MAP_FAILED) {
200*2d543d20SAndroid Build Coastguard Worker if (avc_netlink_check_nb() < 0)
201*2d543d20SAndroid Build Coastguard Worker return -1;
202*2d543d20SAndroid Build Coastguard Worker
203*2d543d20SAndroid Build Coastguard Worker return fallback_policyload;
204*2d543d20SAndroid Build Coastguard Worker }
205*2d543d20SAndroid Build Coastguard Worker
206*2d543d20SAndroid Build Coastguard Worker /* sequence must not be changed during references */
207*2d543d20SAndroid Build Coastguard Worker do {
208*2d543d20SAndroid Build Coastguard Worker seqno = read_sequence(selinux_status);
209*2d543d20SAndroid Build Coastguard Worker
210*2d543d20SAndroid Build Coastguard Worker policyload = selinux_status->policyload;
211*2d543d20SAndroid Build Coastguard Worker
212*2d543d20SAndroid Build Coastguard Worker } while (seqno != read_sequence(selinux_status));
213*2d543d20SAndroid Build Coastguard Worker
214*2d543d20SAndroid Build Coastguard Worker return policyload;
215*2d543d20SAndroid Build Coastguard Worker }
216*2d543d20SAndroid Build Coastguard Worker
217*2d543d20SAndroid Build Coastguard Worker /*
218*2d543d20SAndroid Build Coastguard Worker * selinux_status_deny_unknown
219*2d543d20SAndroid Build Coastguard Worker *
220*2d543d20SAndroid Build Coastguard Worker * It returns a guideline to handle undefined object classes or permissions.
221*2d543d20SAndroid Build Coastguard Worker * 0 means SELinux treats policy queries on undefined stuff being allowed,
222*2d543d20SAndroid Build Coastguard Worker * however, 1 means such queries are denied.
223*2d543d20SAndroid Build Coastguard Worker */
selinux_status_deny_unknown(void)224*2d543d20SAndroid Build Coastguard Worker int selinux_status_deny_unknown(void)
225*2d543d20SAndroid Build Coastguard Worker {
226*2d543d20SAndroid Build Coastguard Worker uint32_t seqno;
227*2d543d20SAndroid Build Coastguard Worker uint32_t deny_unknown;
228*2d543d20SAndroid Build Coastguard Worker
229*2d543d20SAndroid Build Coastguard Worker if (selinux_status == NULL) {
230*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
231*2d543d20SAndroid Build Coastguard Worker return -1;
232*2d543d20SAndroid Build Coastguard Worker }
233*2d543d20SAndroid Build Coastguard Worker
234*2d543d20SAndroid Build Coastguard Worker if (selinux_status == MAP_FAILED)
235*2d543d20SAndroid Build Coastguard Worker return security_deny_unknown();
236*2d543d20SAndroid Build Coastguard Worker
237*2d543d20SAndroid Build Coastguard Worker /* sequence must not be changed during references */
238*2d543d20SAndroid Build Coastguard Worker do {
239*2d543d20SAndroid Build Coastguard Worker seqno = read_sequence(selinux_status);
240*2d543d20SAndroid Build Coastguard Worker
241*2d543d20SAndroid Build Coastguard Worker deny_unknown = selinux_status->deny_unknown;
242*2d543d20SAndroid Build Coastguard Worker
243*2d543d20SAndroid Build Coastguard Worker } while (seqno != read_sequence(selinux_status));
244*2d543d20SAndroid Build Coastguard Worker
245*2d543d20SAndroid Build Coastguard Worker return deny_unknown ? 1 : 0;
246*2d543d20SAndroid Build Coastguard Worker }
247*2d543d20SAndroid Build Coastguard Worker
248*2d543d20SAndroid Build Coastguard Worker /*
249*2d543d20SAndroid Build Coastguard Worker * callback routines for fallback case using netlink socket
250*2d543d20SAndroid Build Coastguard Worker */
fallback_cb_setenforce(int enforcing)251*2d543d20SAndroid Build Coastguard Worker static int fallback_cb_setenforce(int enforcing)
252*2d543d20SAndroid Build Coastguard Worker {
253*2d543d20SAndroid Build Coastguard Worker fallback_sequence += 2;
254*2d543d20SAndroid Build Coastguard Worker fallback_enforcing = enforcing;
255*2d543d20SAndroid Build Coastguard Worker
256*2d543d20SAndroid Build Coastguard Worker return 0;
257*2d543d20SAndroid Build Coastguard Worker }
258*2d543d20SAndroid Build Coastguard Worker
fallback_cb_policyload(int policyload)259*2d543d20SAndroid Build Coastguard Worker static int fallback_cb_policyload(int policyload)
260*2d543d20SAndroid Build Coastguard Worker {
261*2d543d20SAndroid Build Coastguard Worker fallback_sequence += 2;
262*2d543d20SAndroid Build Coastguard Worker fallback_policyload = policyload;
263*2d543d20SAndroid Build Coastguard Worker
264*2d543d20SAndroid Build Coastguard Worker return 0;
265*2d543d20SAndroid Build Coastguard Worker }
266*2d543d20SAndroid Build Coastguard Worker
267*2d543d20SAndroid Build Coastguard Worker /*
268*2d543d20SAndroid Build Coastguard Worker * selinux_status_open
269*2d543d20SAndroid Build Coastguard Worker *
270*2d543d20SAndroid Build Coastguard Worker * It tries to open and mmap kernel status page (/selinux/status).
271*2d543d20SAndroid Build Coastguard Worker * Since Linux 2.6.37 or later supports this feature, we may run
272*2d543d20SAndroid Build Coastguard Worker * fallback routine using a netlink socket on older kernels, if
273*2d543d20SAndroid Build Coastguard Worker * the supplied `fallback' is not zero.
274*2d543d20SAndroid Build Coastguard Worker * It returns 0 on success, -1 on error or 1 when we are ready to
275*2d543d20SAndroid Build Coastguard Worker * use these interfaces, but netlink socket was opened as fallback
276*2d543d20SAndroid Build Coastguard Worker * instead of the kernel status page.
277*2d543d20SAndroid Build Coastguard Worker */
selinux_status_open(int fallback)278*2d543d20SAndroid Build Coastguard Worker int selinux_status_open(int fallback)
279*2d543d20SAndroid Build Coastguard Worker {
280*2d543d20SAndroid Build Coastguard Worker int fd;
281*2d543d20SAndroid Build Coastguard Worker char path[PATH_MAX];
282*2d543d20SAndroid Build Coastguard Worker long pagesize;
283*2d543d20SAndroid Build Coastguard Worker uint32_t seqno;
284*2d543d20SAndroid Build Coastguard Worker
285*2d543d20SAndroid Build Coastguard Worker if (selinux_status != NULL) {
286*2d543d20SAndroid Build Coastguard Worker return (selinux_status == MAP_FAILED) ? 1 : 0;
287*2d543d20SAndroid Build Coastguard Worker }
288*2d543d20SAndroid Build Coastguard Worker
289*2d543d20SAndroid Build Coastguard Worker if (!selinux_mnt) {
290*2d543d20SAndroid Build Coastguard Worker errno = ENOENT;
291*2d543d20SAndroid Build Coastguard Worker return -1;
292*2d543d20SAndroid Build Coastguard Worker }
293*2d543d20SAndroid Build Coastguard Worker
294*2d543d20SAndroid Build Coastguard Worker pagesize = sysconf(_SC_PAGESIZE);
295*2d543d20SAndroid Build Coastguard Worker if (pagesize < 0)
296*2d543d20SAndroid Build Coastguard Worker return -1;
297*2d543d20SAndroid Build Coastguard Worker
298*2d543d20SAndroid Build Coastguard Worker snprintf(path, sizeof(path), "%s/status", selinux_mnt);
299*2d543d20SAndroid Build Coastguard Worker fd = open(path, O_RDONLY | O_CLOEXEC);
300*2d543d20SAndroid Build Coastguard Worker if (fd < 0)
301*2d543d20SAndroid Build Coastguard Worker goto error;
302*2d543d20SAndroid Build Coastguard Worker
303*2d543d20SAndroid Build Coastguard Worker selinux_status = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
304*2d543d20SAndroid Build Coastguard Worker close(fd);
305*2d543d20SAndroid Build Coastguard Worker if (selinux_status == MAP_FAILED) {
306*2d543d20SAndroid Build Coastguard Worker goto error;
307*2d543d20SAndroid Build Coastguard Worker }
308*2d543d20SAndroid Build Coastguard Worker last_seqno = (uint32_t)(-1);
309*2d543d20SAndroid Build Coastguard Worker
310*2d543d20SAndroid Build Coastguard Worker /* sequence must not be changed during references */
311*2d543d20SAndroid Build Coastguard Worker do {
312*2d543d20SAndroid Build Coastguard Worker seqno = read_sequence(selinux_status);
313*2d543d20SAndroid Build Coastguard Worker
314*2d543d20SAndroid Build Coastguard Worker last_policyload = selinux_status->policyload;
315*2d543d20SAndroid Build Coastguard Worker
316*2d543d20SAndroid Build Coastguard Worker } while (seqno != read_sequence(selinux_status));
317*2d543d20SAndroid Build Coastguard Worker
318*2d543d20SAndroid Build Coastguard Worker /* No need to use avc threads if the kernel status page is available */
319*2d543d20SAndroid Build Coastguard Worker avc_using_threads = 0;
320*2d543d20SAndroid Build Coastguard Worker
321*2d543d20SAndroid Build Coastguard Worker return 0;
322*2d543d20SAndroid Build Coastguard Worker
323*2d543d20SAndroid Build Coastguard Worker error:
324*2d543d20SAndroid Build Coastguard Worker /*
325*2d543d20SAndroid Build Coastguard Worker * If caller wants fallback routine, we try to provide
326*2d543d20SAndroid Build Coastguard Worker * an equivalent functionality using existing netlink
327*2d543d20SAndroid Build Coastguard Worker * socket, although it needs system call invocation to
328*2d543d20SAndroid Build Coastguard Worker * receive event notification.
329*2d543d20SAndroid Build Coastguard Worker */
330*2d543d20SAndroid Build Coastguard Worker if (fallback && avc_netlink_open(0) == 0) {
331*2d543d20SAndroid Build Coastguard Worker union selinux_callback cb;
332*2d543d20SAndroid Build Coastguard Worker
333*2d543d20SAndroid Build Coastguard Worker /* register my callbacks */
334*2d543d20SAndroid Build Coastguard Worker cb.func_setenforce = fallback_cb_setenforce;
335*2d543d20SAndroid Build Coastguard Worker selinux_set_callback(SELINUX_CB_SETENFORCE, cb);
336*2d543d20SAndroid Build Coastguard Worker cb.func_policyload = fallback_cb_policyload;
337*2d543d20SAndroid Build Coastguard Worker selinux_set_callback(SELINUX_CB_POLICYLOAD, cb);
338*2d543d20SAndroid Build Coastguard Worker
339*2d543d20SAndroid Build Coastguard Worker /* mark as fallback mode */
340*2d543d20SAndroid Build Coastguard Worker selinux_status = MAP_FAILED;
341*2d543d20SAndroid Build Coastguard Worker last_seqno = (uint32_t)(-1);
342*2d543d20SAndroid Build Coastguard Worker
343*2d543d20SAndroid Build Coastguard Worker if (avc_using_threads)
344*2d543d20SAndroid Build Coastguard Worker {
345*2d543d20SAndroid Build Coastguard Worker fallback_netlink_thread = avc_create_thread(&avc_netlink_loop);
346*2d543d20SAndroid Build Coastguard Worker }
347*2d543d20SAndroid Build Coastguard Worker
348*2d543d20SAndroid Build Coastguard Worker fallback_sequence = 0;
349*2d543d20SAndroid Build Coastguard Worker fallback_enforcing = security_getenforce();
350*2d543d20SAndroid Build Coastguard Worker fallback_policyload = 0;
351*2d543d20SAndroid Build Coastguard Worker
352*2d543d20SAndroid Build Coastguard Worker return 1;
353*2d543d20SAndroid Build Coastguard Worker }
354*2d543d20SAndroid Build Coastguard Worker selinux_status = NULL;
355*2d543d20SAndroid Build Coastguard Worker
356*2d543d20SAndroid Build Coastguard Worker return -1;
357*2d543d20SAndroid Build Coastguard Worker }
358*2d543d20SAndroid Build Coastguard Worker
359*2d543d20SAndroid Build Coastguard Worker /*
360*2d543d20SAndroid Build Coastguard Worker * selinux_status_close
361*2d543d20SAndroid Build Coastguard Worker *
362*2d543d20SAndroid Build Coastguard Worker * It unmap and close the kernel status page, or close netlink socket
363*2d543d20SAndroid Build Coastguard Worker * if fallback mode.
364*2d543d20SAndroid Build Coastguard Worker */
selinux_status_close(void)365*2d543d20SAndroid Build Coastguard Worker void selinux_status_close(void)
366*2d543d20SAndroid Build Coastguard Worker {
367*2d543d20SAndroid Build Coastguard Worker long pagesize;
368*2d543d20SAndroid Build Coastguard Worker
369*2d543d20SAndroid Build Coastguard Worker /* not opened */
370*2d543d20SAndroid Build Coastguard Worker if (selinux_status == NULL)
371*2d543d20SAndroid Build Coastguard Worker return;
372*2d543d20SAndroid Build Coastguard Worker
373*2d543d20SAndroid Build Coastguard Worker /* fallback-mode */
374*2d543d20SAndroid Build Coastguard Worker if (selinux_status == MAP_FAILED)
375*2d543d20SAndroid Build Coastguard Worker {
376*2d543d20SAndroid Build Coastguard Worker if (avc_using_threads)
377*2d543d20SAndroid Build Coastguard Worker avc_stop_thread(fallback_netlink_thread);
378*2d543d20SAndroid Build Coastguard Worker
379*2d543d20SAndroid Build Coastguard Worker avc_netlink_release_fd();
380*2d543d20SAndroid Build Coastguard Worker avc_netlink_close();
381*2d543d20SAndroid Build Coastguard Worker selinux_status = NULL;
382*2d543d20SAndroid Build Coastguard Worker return;
383*2d543d20SAndroid Build Coastguard Worker }
384*2d543d20SAndroid Build Coastguard Worker
385*2d543d20SAndroid Build Coastguard Worker pagesize = sysconf(_SC_PAGESIZE);
386*2d543d20SAndroid Build Coastguard Worker /* not much we can do other than leak memory */
387*2d543d20SAndroid Build Coastguard Worker if (pagesize > 0)
388*2d543d20SAndroid Build Coastguard Worker munmap(selinux_status, pagesize);
389*2d543d20SAndroid Build Coastguard Worker selinux_status = NULL;
390*2d543d20SAndroid Build Coastguard Worker
391*2d543d20SAndroid Build Coastguard Worker last_seqno = (uint32_t)(-1);
392*2d543d20SAndroid Build Coastguard Worker }
393