[PATCH] libselinux: refactor AVC netlink code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch removes duplication in the AVC netlink code
by introducing helper functions.

Did some basic testing and confirmed that messages are
received and processed.

More patches to follow.

Signed-off-by: Eamon Walsh <ewalsh@xxxxxxxxxxxxx>
---

avc_internal.c |  289 +++++++++++++++++++++------------------------------------
1 file changed, 107 insertions(+), 182 deletions(-)


Index: libselinux/src/avc_internal.c
===================================================================
--- libselinux/src/avc_internal.c	(revision 2662)
+++ libselinux/src/avc_internal.c	(working copy)
@@ -89,221 +89,146 @@
	close(fd);
}

-int avc_netlink_check_nb(void)
+static int avc_netlink_receive(char *buf, unsigned buflen)
{
	int rc;
	struct sockaddr_nl nladdr;
	socklen_t nladdrlen = sizeof nladdr;
-	char buf[1024];
-	struct nlmsghdr *nlh;
+	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;

-	while (1) {
-		rc = recvfrom(fd, buf, sizeof(buf), 0,
-			      (struct sockaddr *)&nladdr, &nladdrlen);
-		if (rc < 0) {
-			if (errno == EINTR)
-				continue;
-			if (errno != EAGAIN) {
-				avc_log("%s:  socket error during read: %d\n",
-					avc_prefix, errno);
-			} else {
-				errno = 0;
-				rc = 0;
-			}
-			goto out;
-		}
+	rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr,
+		      &nladdrlen);
+	if (rc < 0)
+		return rc;

-		if (nladdrlen != sizeof nladdr) {
-			avc_log
-			    ("%s:  warning: netlink address truncated, len %d?\n",
-			     avc_prefix, nladdrlen);
-			rc = -1;
-			goto out;
-		}
+	if (nladdrlen != sizeof nladdr) {
+		avc_log("%s:  warning: netlink address truncated, len %d?\n",
+			avc_prefix, nladdrlen);
+		return -1;
+	}

-		if (nladdr.nl_pid) {
-			avc_log
-			    ("%s:  warning: received spoofed netlink packet from: %d\n",
-			     avc_prefix, nladdr.nl_pid);
-			continue;
-		}
+	if (nladdr.nl_pid) {
+		avc_log("%s:  warning: received spoofed netlink packet from: %d\n",
+			avc_prefix, nladdr.nl_pid);
+		return -1;
+	}

-		if (rc == 0) {
-			avc_log("%s:  warning: received EOF on socket\n",
-				avc_prefix);
-			goto out;
-		}
+	if (rc == 0) {
+		avc_log("%s:  warning: received EOF on netlink socket\n",
+			avc_prefix);
+		errno = EBADFD;
+		return -1;
+	}

-		nlh = (struct nlmsghdr *)buf;
+	if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > (unsigned)rc) {
+		avc_log("%s:  warning: incomplete netlink message\n",
+			avc_prefix);
+		return -1;
+	}

-		if (nlh->nlmsg_flags & MSG_TRUNC
-		    || nlh->nlmsg_len > (unsigned)rc) {
-			avc_log("%s:  warning: incomplete netlink message\n",
-				avc_prefix);
-			goto out;
-		}
+	return 0;
+}

-		rc = 0;
-		switch (nlh->nlmsg_type) {
-		case NLMSG_ERROR:{
-				struct nlmsgerr *err = NLMSG_DATA(nlh);
+static int avc_netlink_process(char *buf)
+{
+	int rc;
+	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;

-				/* Netlink ack */
-				if (err->error == 0)
-					break;
+	switch (nlh->nlmsg_type) {
+	case NLMSG_ERROR:{
+		struct nlmsgerr *err = NLMSG_DATA(nlh);

-				errno = -err->error;
-				avc_log("%s:  netlink error: %d\n", avc_prefix,
-					errno);
-				rc = -1;
-				goto out;
-			}
+		/* Netlink ack */
+		if (err->error == 0)
+			break;

-		case SELNL_MSG_SETENFORCE:{
-				struct selnl_msg_setenforce *msg =
-				    NLMSG_DATA(nlh);
-				avc_log
-				    ("%s:  received setenforce notice (enforcing=%d)\n",
-				     avc_prefix, msg->val);
-				avc_enforcing = msg->val;
-				if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
-					avc_log
-					    ("%s:  cache reset returned %d (errno %d)\n",
-					     avc_prefix, rc, errno);
-					goto out;
-				}
-				break;
-			}
+		errno = -err->error;
+		avc_log("%s:  netlink error: %d\n", avc_prefix, errno);
+		return -1;
+	}

-		case SELNL_MSG_POLICYLOAD:{
-				struct selnl_msg_policyload *msg =
-				    NLMSG_DATA(nlh);
-				avc_log
-				    ("%s:  received policyload notice (seqno=%d)\n",
-				     avc_prefix, msg->seqno);
-				rc = avc_ss_reset(msg->seqno);
-				if (rc < 0) {
-					avc_log
-					    ("%s:  cache reset returned %d (errno %d)\n",
-					     avc_prefix, rc, errno);
-					goto out;
-				}
-				break;
-			}
+	case SELNL_MSG_SETENFORCE:{
+		struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
+		avc_log("%s:  received setenforce notice (enforcing=%d)\n",
+			avc_prefix, msg->val);
+		avc_enforcing = msg->val;
+		if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
+			avc_log("%s:  cache reset returned %d (errno %d)\n",
+				avc_prefix, rc, errno);
+			return rc;
+		}
+		break;
+	}

-		default:
-			avc_log("%s:  warning: unknown netlink message %d\n",
-				avc_prefix, nlh->nlmsg_type);
+	case SELNL_MSG_POLICYLOAD:{
+		struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
+		avc_log("%s:  received policyload notice (seqno=%d)\n",
+			avc_prefix, msg->seqno);
+		rc = avc_ss_reset(msg->seqno);
+		if (rc < 0) {
+			avc_log("%s:  cache reset returned %d (errno %d)\n",
+				avc_prefix, rc, errno);
+			return rc;
		}
+		break;
	}
-      out:
-	return rc;
+
+	default:
+		avc_log("%s:  warning: unknown netlink message %d\n",
+			avc_prefix, nlh->nlmsg_type);
+	}
+	return 0;
}

-/* run routine for the netlink listening thread */
-void avc_netlink_loop(void)
+int avc_netlink_check_nb(void)
{
-	int ret;
-	struct sockaddr_nl nladdr;
-	socklen_t nladdrlen = sizeof nladdr;
+	int rc;
	char buf[1024];
-	struct nlmsghdr *nlh;

	while (1) {
-		ret =
-		    recvfrom(fd, buf, sizeof(buf), 0,
-			     (struct sockaddr *)&nladdr, &nladdrlen);
-		if (ret < 0) {
-			if (errno == EINTR)
+		errno = 0;
+		rc = avc_netlink_receive(buf, sizeof(buf));
+		if (rc < 0) {
+			if (errno == EWOULDBLOCK)
+				return 0;
+			if (errno == 0 || errno == EINTR)
				continue;
-			avc_log("%s:  netlink thread: recvfrom: error %d\n",
-				avc_prefix, errno);
-			goto out;
+			else {
+				avc_log("%s:  netlink recvfrom: error %d\n",
+					avc_prefix, errno);
+				return rc;
+			}
		}

-		if (nladdrlen != sizeof nladdr) {
-			avc_log
-			    ("%s:  warning: netlink address truncated, len %d?\n",
-			     avc_prefix, nladdrlen);
-			ret = -1;
-			goto out;
-		}
+		(void)avc_netlink_process(buf);
+	}
+	return 0;
+}

-		if (nladdr.nl_pid) {
-			avc_log
-			    ("%s:  warning: received spoofed netlink packet from: %d\n",
-			     avc_prefix, nladdr.nl_pid);
-			continue;
-		}
+/* run routine for the netlink listening thread */
+void avc_netlink_loop(void)
+{
+	int rc;
+	char buf[1024];

-		if (ret == 0) {
-			avc_log("%s:  netlink thread: received EOF on socket\n",
-				avc_prefix);
-			goto out;
-		}
-
-		nlh = (struct nlmsghdr *)buf;
-
-		if (nlh->nlmsg_flags & MSG_TRUNC
-		    || nlh->nlmsg_len > (unsigned)ret) {
-			avc_log
-			    ("%s:  netlink thread: incomplete netlink message\n",
-			     avc_prefix);
-			goto out;
-		}
-
-		switch (nlh->nlmsg_type) {
-		case NLMSG_ERROR:{
-				struct nlmsgerr *err = NLMSG_DATA(nlh);
-
-				/* Netlink ack */
-				if (err->error == 0)
-					break;
-
-				avc_log("%s:  netlink thread: msg: error %d\n",
-					avc_prefix, -err->error);
-				goto out;
-			}
-
-		case SELNL_MSG_SETENFORCE:{
-				struct selnl_msg_setenforce *msg =
-				    NLMSG_DATA(nlh);
-				avc_log
-				    ("%s:  received setenforce notice (enforcing=%d)\n",
-				     avc_prefix, msg->val);
-				avc_enforcing = msg->val;
-				if (avc_enforcing && (ret = avc_ss_reset(0)) < 0) {
-					avc_log
-					    ("%s:  cache reset returned %d (errno %d)\n",
-					     avc_prefix, ret, errno);
-					goto out;
-				}
+	while (1) {
+		errno = 0;
+		rc = avc_netlink_receive(buf, sizeof(buf));
+		if (rc < 0) {
+			if (errno == 0 || errno == EINTR)
+				continue;
+			else {
+				avc_log("%s:  netlink recvfrom: error %d\n",
+					avc_prefix, errno);
				break;
			}
-
-		case SELNL_MSG_POLICYLOAD:{
-				struct selnl_msg_policyload *msg =
-				    NLMSG_DATA(nlh);
-				avc_log
-				    ("%s:  received policyload notice (seqno=%d)\n",
-				     avc_prefix, msg->seqno);
-				ret = avc_ss_reset(msg->seqno);
-				if (ret < 0) {
-					avc_log
-					    ("%s:  netlink thread: cache reset returned %d (errno %d)\n",
-					     avc_prefix, ret, errno);
-					goto out;
-				}
-				break;
-			}
-
-		default:
-			avc_log
-			    ("%s:  netlink thread: warning: unknown msg type %d\n",
-			     avc_prefix, nlh->nlmsg_type);
		}
+
+		rc = avc_netlink_process(buf);
+		if (rc < 0)
+			break;
	}
-      out:
+
	close(fd);
	avc_netlink_trouble = 1;
	avc_log("%s:  netlink thread: errors encountered, terminating\n",

--
Eamon Walsh <ewalsh@xxxxxxxxxxxxx>
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux