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