[ghau51/ghau40,v7,12/12] libaudit: add support to get and set capcontid on a task

Submitted by Richard Guy Briggs on Sept. 19, 2019, 1:27 a.m.

Details

Message ID 1568856472-10173-13-git-send-email-rgb@redhat.com
State New
Series "add support for audit container identifier"
Headers show

Commit Message

Richard Guy Briggs Sept. 19, 2019, 1:27 a.m.
Add support to be able to set a capability to allow a task to set the
audit container identifier of descendants.

See: https://github.com/linux-audit/audit-userspace/issues/51
See: https://github.com/linux-audit/audit-kernel/issues/90
See: https://github.com/linux-audit/audit-testsuite/issues/64
See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID

Add the audit_get_capcontid() and audit_set_capcontid() calls analogous
to CAP_AUDIT_CONTROL for descendant user namespaces.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
---
 docs/Makefile.am  |  1 +
 lib/libaudit.c    | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/libaudit.h    | 14 +++++++++
 lib/msg_typetab.h |  2 ++
 lib/netlink.c     |  4 +++
 5 files changed, 106 insertions(+)

Patch hide | download patch | download mbox

diff --git a/docs/Makefile.am b/docs/Makefile.am
index 821182315806..8b0e5c2c3730 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -29,6 +29,7 @@  auditd.conf.5 auditd-plugins.5 \
 audit_delete_rule_data.3 audit_detect_machine.3 \
 audit_encode_nv_string.3 audit_getloginuid.3 \
 audit_get_reply.3 audit_get_session.3 audit_get_containerid.3 audit_set_containerid.3 \
+audit_get_capcontid.3 audit_set_capcontid.3 \
 audit_log_acct_message.3 audit_log_user_avc_message.3 \
 audit_log_user_command.3 audit_log_user_comm_message.3 \
 audit_log_user_message.3 audit_log_semanage_message.3 \
diff --git a/lib/libaudit.c b/lib/libaudit.c
index 62e1a2a64ee5..08998610c66a 100644
--- a/lib/libaudit.c
+++ b/lib/libaudit.c
@@ -1026,6 +1026,91 @@  uint32_t audit_get_session(void)
 }
 
 /*
+ * This function will retrieve the capability container identifier or -2 if
+ * there is an error.
+ */
+uint32_t audit_get_capcontid(pid_t pid)
+{
+        if ((audit_get_features() & AUDIT_FEATURE_BITMAP_CONTAINERID) == 0) {
+		return -2;
+	} else {
+                struct audit_reply rep;
+                int i;
+                int timeout = 40; /* tenths of seconds */
+                struct pollfd pfd[1];
+                int fd = audit_open();
+		struct audit_capcontid_status cs;
+                int rc;
+
+		if (fd < 0) {
+                        audit_msg(audit_priority(errno), "Error openning get capcontid req (%s)", strerror(-rc));
+			return -2;
+		}
+		cs.pid = pid;
+                rc = audit_send(fd, AUDIT_GET_CONTID, &cs, sizeof(cs));
+                if (rc < 0 && rc != -EINVAL) {
+			audit_close(fd);
+                        audit_msg(audit_priority(errno), "Error sending set capcontid req (%s)", strerror(-rc));
+                        return -2;
+                }
+                pfd[0].fd = fd;
+                pfd[0].events = POLLIN;
+
+                for (i = 0; i < timeout; i++) {
+                        do {
+                                rc = poll(pfd, 1, 100);
+                        } while (rc < 0 && errno == EINTR);
+                        rc = audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING,0); 
+                        if (rc > 0) {
+                                /* If we get done or error, break out */
+                                if (rep.type == NLMSG_DONE ||
+                                        rep.type == NLMSG_ERROR)
+                                        break;
+
+                                /* If its not get_contid, keep looping */
+                                if (rep.type != AUDIT_GET_CAPCONTID)
+                                        continue;
+
+                                /* Found it... */
+				audit_close(fd);
+				if (rep.capcontid->pid == pid)
+                                	return rep.capcontid->cap;
+				else
+					return -2;
+			}
+		}
+		audit_close(fd);
+		return -2;
+	}
+}
+
+/*
+ * This function returns 0 on success and 1 on failure
+ */
+int audit_set_capcontid(pid_t pid, uint32_t capcontid)
+{
+        if ((audit_get_features() & AUDIT_FEATURE_BITMAP_CONTAINERID) == 0) {
+		return -2;
+	} else {
+		int rc;
+		int seq;
+                int fd = audit_open();
+		struct audit_capcontid_status cs = { pid, capcontid };
+
+		if (fd < 0) {
+                        audit_msg(audit_priority(errno), "Error openning set capcontid req (%s)", strerror(-rc));
+			return 1;
+		}
+		rc = audit_send(fd, AUDIT_SET_CAPCONTID, &cs, sizeof(cs));
+		if (rc < 0) {
+			audit_msg(audit_priority(errno), "Error sending set capcontid request (%s)", strerror(-rc));
+			return 1;
+		}
+		return 0;
+	}
+}
+
+/*
  * This function will retrieve the audit container identifier or -2 if
  * there is an error.
  */
diff --git a/lib/libaudit.h b/lib/libaudit.h
index 717724e8fbbb..8067ef30f427 100644
--- a/lib/libaudit.h
+++ b/lib/libaudit.h
@@ -275,6 +275,14 @@  extern "C" {
 #define AUDIT_GET_SESSIONID	1026    /* get current process sessionid */
 #endif
 
+#ifndef AUDIT_GET_CAPCONTID
+#define AUDIT_GET_CAPCONTID	1027    /* get contid of specified pid */
+#endif
+
+#ifndef AUDIT_SET_CAPCONTID
+#define AUDIT_SET_CAPCONTID	1028    /* set contid of specified pid */
+#endif
+
 #ifndef AUDIT_MMAP
 #define AUDIT_MMAP		1323 /* Descriptor and flags in mmap */
 #endif
@@ -532,6 +540,11 @@  struct audit_message {
 // internal - forward declaration
 struct daemon_conf;
 
+struct audit_capcontid_status {
+	pid_t		pid;
+	uint32_t	cap;
+};
+
 struct audit_cont_status {
 	pid_t		pid;
 	uint64_t	id;
@@ -559,6 +572,7 @@  struct audit_reply {
 #endif
 #ifdef AUDIT_FEATURE_BITMAP_CONTAINERID
 	struct audit_cont_status	*cont;
+	struct audit_capcontid_status	*capcontid;
 #endif
 	};
 };
diff --git a/lib/msg_typetab.h b/lib/msg_typetab.h
index 9f2b137dc7f8..f510e9790ea4 100644
--- a/lib/msg_typetab.h
+++ b/lib/msg_typetab.h
@@ -50,6 +50,8 @@  _S(AUDIT_LOGIN,                      "LOGIN"                         )
 //_S(AUDIT_GET_LOGINUID,               "GET_LOGINUID"                  )
 //_S(AUDIT_SET_LOGINUID,               "SET_LOGINUID"                  )
 //_S(AUDIT_GET_SESSIONID,              "GET_SESSIONID"                 )
+//_S(AUDIT_GET_CAPCONTID,              "GET_CAPCONTID"                 )
+_S(AUDIT_SET_CAPCONTID,              "SET_CAPCONTID"                 )
 _S(AUDIT_CONTAINER_OP,               "CONTAINER_OP"                  )
 _S(AUDIT_USER_AUTH,                  "USER_AUTH"                     )
 _S(AUDIT_USER_ACCT,                  "USER_ACCT"                     )
diff --git a/lib/netlink.c b/lib/netlink.c
index d177b865a79e..d378b32e0ff6 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -154,6 +154,7 @@  static int adjust_reply(struct audit_reply *rep, int len)
 #endif
 #ifdef AUDIT_FEATURE_BITMAP_CONTAINERID
 	rep->cont     = NULL;
+	rep->capcontid = NULL;
 #endif
 	if (!NLMSG_OK(rep->nlh, (unsigned int)len)) {
 		if (len == sizeof(rep->msg)) {
@@ -201,6 +202,9 @@  static int adjust_reply(struct audit_reply *rep, int len)
 		case AUDIT_SIGNAL_INFO2:
 			rep->signal_info2 = NLMSG_DATA(rep->nlh);
 			break;
+		case AUDIT_GET_CAPCONTID:
+			rep->capcontid = NLMSG_DATA(rep->nlh);
+			break;
 		case AUDIT_GET_CONTID:
 			rep->cont = NLMSG_DATA(rep->nlh);
 			break;