1f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
2f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Callbacks for user-supplied memory allocation, supplemental
3f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * auditing, and locking routines.
4f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *
5f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
6f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *
7f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Netlink code derived in part from sample code by
8f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * James Morris <jmorris@redhat.com>.
9f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
10f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
11f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <errno.h>
12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdio.h>
13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdlib.h>
14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdint.h>
15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <unistd.h>
16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <fcntl.h>
17f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <string.h>
18f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <poll.h>
19f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/types.h>
20f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/socket.h>
21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <linux/types.h>
22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <linux/netlink.h>
23f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "callbacks.h"
24f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "selinux_netlink.h"
25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "avc_internal.h"
26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#ifndef NETLINK_SELINUX
28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define NETLINK_SELINUX 7
29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#endif
30f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
31f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* callback pointers */
32f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid *(*avc_func_malloc) (size_t) = NULL;
33f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid (*avc_func_free) (void *) = NULL;
34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
35f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid (*avc_func_log) (const char *, ...) = NULL;
36f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid (*avc_func_audit) (void *, security_class_t, char *, size_t) = NULL;
37f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
38f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_using_threads = 0;
39f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_app_main_loop = 0;
40f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid *(*avc_func_create_thread) (void (*)(void)) = NULL;
41f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid (*avc_func_stop_thread) (void *) = NULL;
42f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
43f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid *(*avc_func_alloc_lock) (void) = NULL;
44f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid (*avc_func_get_lock) (void *) = NULL;
45f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid (*avc_func_release_lock) (void *) = NULL;
46f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid (*avc_func_free_lock) (void *) = NULL;
47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* message prefix string and avc enforcing mode */
49f074036424618c130dacb3464465a8b40bffef5Stephen Smalleychar avc_prefix[AVC_PREFIX_SIZE] = "uavc";
50f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_running = 0;
51f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_enforcing = 1;
52f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_setenforce = 0;
53f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_netlink_trouble = 0;
54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* netlink socket code */
56d181826941c365f66b00a7f5accfd42bc09c19d6Stephen Smalleystatic int fd = -1;
57f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
58f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_netlink_open(int blocking)
59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int len, rc = 0;
61f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct sockaddr_nl addr;
62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
63c01e95f737527e068edcacb1179affca9f62a52dEric Paris	fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_SELINUX);
64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (fd < 0) {
65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = fd;
66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto out;
67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
68c01e95f737527e068edcacb1179affca9f62a52dEric Paris
69f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (!blocking && fcntl(fd, F_SETFL, O_NONBLOCK)) {
70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		close(fd);
71d181826941c365f66b00a7f5accfd42bc09c19d6Stephen Smalley		fd = -1;
72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = -1;
73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto out;
74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	len = sizeof(addr);
77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	memset(&addr, 0, len);
79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	addr.nl_family = AF_NETLINK;
80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	addr.nl_groups = SELNL_GRP_AVC;
81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (bind(fd, (struct sockaddr *)&addr, len) < 0) {
83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		close(fd);
84d181826941c365f66b00a7f5accfd42bc09c19d6Stephen Smalley		fd = -1;
85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = -1;
86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto out;
87f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley      out:
89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return rc;
90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
91f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
92f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_netlink_close(void)
93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
94d181826941c365f66b00a7f5accfd42bc09c19d6Stephen Smalley	if (fd >= 0)
95d181826941c365f66b00a7f5accfd42bc09c19d6Stephen Smalley		close(fd);
96d181826941c365f66b00a7f5accfd42bc09c19d6Stephen Smalley	fd = -1;
97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
98f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
99f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int avc_netlink_receive(char *buf, unsigned buflen, int blocking)
100f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
101f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int rc;
102f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct pollfd pfd = { fd, POLLIN | POLLPRI, 0 };
103f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct sockaddr_nl nladdr;
104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	socklen_t nladdrlen = sizeof nladdr;
105f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
106f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
107689383dc7dd425b6026c97d49642b0c608602577Stephen Smalley	do {
108689383dc7dd425b6026c97d49642b0c608602577Stephen Smalley		rc = poll(&pfd, 1, (blocking ? -1 : 0));
109689383dc7dd425b6026c97d49642b0c608602577Stephen Smalley	} while (rc < 0 && errno == EINTR);
110f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
111f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (rc == 0 && !blocking) {
112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		errno = EWOULDBLOCK;
113f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
114f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
115f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	else if (rc < 1) {
116f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_ERROR, "%s:  netlink poll: error %d\n",
117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix, errno);
118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return rc;
119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
120f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
121f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr,
122f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		      &nladdrlen);
123f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (rc < 0)
124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return rc;
125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
126f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (nladdrlen != sizeof nladdr) {
127f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_WARNING,
128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  warning: netlink address truncated, len %d?\n",
129f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix, nladdrlen);
130f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
131f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
132f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
133f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (nladdr.nl_pid) {
134f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_WARNING,
135f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  warning: received spoofed netlink packet from: %d\n",
136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix, nladdr.nl_pid);
137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (rc == 0) {
141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_WARNING,
142f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  warning: received EOF on netlink socket\n",
143f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix);
144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		errno = EBADFD;
145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > (unsigned)rc) {
149f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_WARNING,
150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  warning: incomplete netlink message\n",
151f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix);
152f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
153f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
154f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
155f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return 0;
156f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
157f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
158f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int avc_netlink_process(char *buf)
159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
160f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int rc;
161f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	switch (nlh->nlmsg_type) {
164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	case NLMSG_ERROR:{
165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		struct nlmsgerr *err = NLMSG_DATA(nlh);
166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		/* Netlink ack */
168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (err->error == 0)
169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			break;
170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		errno = -err->error;
172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_ERROR,
173f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  netlink error: %d\n", avc_prefix, errno);
174f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		return -1;
175f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
176f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
177f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	case SELNL_MSG_SETENFORCE:{
178f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
179f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_INFO,
180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  received setenforce notice (enforcing=%d)\n",
181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix, msg->val);
182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (avc_setenforce)
183f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			break;
184f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_enforcing = msg->val;
185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_log(SELINUX_ERROR,
187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				"%s:  cache reset returned %d (errno %d)\n",
188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				avc_prefix, rc, errno);
189f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return rc;
190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = selinux_netlink_setenforce(msg->val);
192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0)
193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return rc;
194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		break;
195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
197f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	case SELNL_MSG_POLICYLOAD:{
198f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
199f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_INFO,
200f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  received policyload notice (seqno=%d)\n",
201f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix, msg->seqno);
202f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = avc_ss_reset(msg->seqno);
203f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0) {
204f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_log(SELINUX_ERROR,
205f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				"%s:  cache reset returned %d (errno %d)\n",
206f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				avc_prefix, rc, errno);
207f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return rc;
208f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
209f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = selinux_netlink_policyload(msg->seqno);
210f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0)
211f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return rc;
212f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		break;
213f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
214f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
215f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	default:
216f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_log(SELINUX_WARNING,
217f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			"%s:  warning: unknown netlink message %d\n",
218f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			avc_prefix, nlh->nlmsg_type);
219f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
220f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return 0;
221f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
222f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
223f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_netlink_check_nb(void)
224f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
225f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int rc;
226f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char buf[1024] __attribute__ ((aligned));
227f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
228f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	while (1) {
229f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		errno = 0;
230f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = avc_netlink_receive(buf, sizeof(buf), 0);
231f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0) {
232f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (errno == EWOULDBLOCK)
233f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				return 0;
234f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (errno == 0 || errno == EINTR)
235f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				continue;
236f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			else {
237f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				avc_log(SELINUX_ERROR,
238f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					"%s:  netlink recvfrom: error %d\n",
239f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					avc_prefix, errno);
240f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				return rc;
241f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
242f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
243f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
244f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		(void)avc_netlink_process(buf);
245f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
246f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return 0;
247f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
248f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
249f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* run routine for the netlink listening thread */
250f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_netlink_loop(void)
251f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
252f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int rc;
253f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char buf[1024] __attribute__ ((aligned));
254f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
255f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	while (1) {
256f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		errno = 0;
257f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = avc_netlink_receive(buf, sizeof(buf), 1);
258f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0) {
259f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (errno == 0 || errno == EINTR)
260f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				continue;
261f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			else {
262f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				avc_log(SELINUX_ERROR,
263f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					"%s:  netlink recvfrom: error %d\n",
264f074036424618c130dacb3464465a8b40bffef5Stephen Smalley					avc_prefix, errno);
265f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				break;
266f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
267f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
268f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
269f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		rc = avc_netlink_process(buf);
270f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (rc < 0)
271f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			break;
272f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
273f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
274f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	close(fd);
275d181826941c365f66b00a7f5accfd42bc09c19d6Stephen Smalley	fd = -1;
276f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	avc_netlink_trouble = 1;
277f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	avc_log(SELINUX_ERROR,
278f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		"%s:  netlink thread: errors encountered, terminating\n",
279f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		avc_prefix);
280f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
281f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
282f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint avc_netlink_acquire_fd(void)
283f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
284f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    avc_app_main_loop = 1;
285f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
286f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    return fd;
287f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
288f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
289f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid avc_netlink_release_fd(void)
290f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
291f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    avc_app_main_loop = 0;
292f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
293