[PATCH ghau51/ghau40 v7 10/12] contid: switch from /proc to netlink

From: Richard Guy Briggs
Date: Wed Sep 18 2019 - 21:29:15 EST


Add the ability to get and set the audit container identifier using an
audit netlink message using message types AUDIT_SET_CONTID 1023 and
AUDIT_GET_CONTID 1022 in addition to using the proc filesystem. The
message format includes the data structure:

struct audit_contid_status {
pid_t pid;
u64 id;
};

This switches over the audit_set_containerid() and
audit_get_containerid() to use this method if it exists.

Signed-off-by: Richard Guy Briggs <rgb@xxxxxxxxxx>
---
docs/Makefile.am | 2 +-
docs/audit_get_containerid.3 | 6 +--
docs/audit_set_containerid.3 | 24 +++++++++++
lib/libaudit.c | 96 +++++++++++++++++++++++++++++++++++---------
lib/libaudit.h | 19 ++++++++-
lib/msg_typetab.h | 2 +
lib/netlink.c | 6 +++
7 files changed, 130 insertions(+), 25 deletions(-)
create mode 100644 docs/audit_set_containerid.3

diff --git a/docs/Makefile.am b/docs/Makefile.am
index 209789bb2051..821182315806 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -28,7 +28,7 @@ man_MANS = audit_add_rule_data.3 audit_add_watch.3 auditctl.8 auditd.8 \
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_get_reply.3 audit_get_session.3 audit_get_containerid.3 audit_set_containerid.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/docs/audit_get_containerid.3 b/docs/audit_get_containerid.3
index ef62a25db970..5f485c987993 100644
--- a/docs/audit_get_containerid.3
+++ b/docs/audit_get_containerid.3
@@ -4,10 +4,10 @@ audit_get_containerid \- Get a program's container id value
.SH SYNOPSIS
.B #include <libaudit.h>
.sp
-uin64_t audit_get_containerid(void);
+uin64_t audit_get_containerid(pid_t pid);

.SH DESCRIPTION
-This function returns the task's audit container identifier attribute.
+This function returns the pid task's audit container identifier attribute.

.SH "RETURN VALUE"

@@ -19,7 +19,7 @@ This function returns \-2 on failure. Additionally, in the event of a real error

.SH "SEE ALSO"

-.BR audit_getloginuid (3).
+.BR audit_set_containerid (3).

.SH AUTHOR
Richard Guy Briggs
diff --git a/docs/audit_set_containerid.3 b/docs/audit_set_containerid.3
new file mode 100644
index 000000000000..e4e884eea4a9
--- /dev/null
+++ b/docs/audit_set_containerid.3
@@ -0,0 +1,24 @@
+.TH "AUDIT_SET_CONTAINERID" "4" "Aug 2019" "Red Hat" "Linux Audit API"
+.SH NAME
+audit_set_containerid \- Set a program's container id value
+.SH SYNOPSIS
+.B #include <libaudit.h>
+.sp
+int audit_set_containerid(pid_t pid, uin64_t contid);
+
+.SH "DESCRIPTION"
+
+This function sets the pid task's attribute audit_containerid with the value of contid. The audit_containerid value may only be set by programs with the CAP_AUDIT_CONTROL capability. This normally means the root account.
+.sp
+The audit_containerid value is part of the task structure and is inheritted by child processes. It is used to track in which container a task has been placed. All container orchestrator/engines should set this value right before launching a process after setting up its resources.
+
+.SH "RETURN VALUE"
+
+This function returns 0 on success and non-zero otherwise.
+
+.SH "SEE ALSO"
+
+.BR audit_get_containerid (3).
+
+.SH AUTHOR
+Richard Guy Briggs
diff --git a/lib/libaudit.c b/lib/libaudit.c
index c142a60c52a2..fdba6301e7f0 100644
--- a/lib/libaudit.c
+++ b/lib/libaudit.c
@@ -669,7 +669,7 @@ int audit_request_rules_list_data(int fd)
int audit_request_signal_info(int fd)
{
int rc;
- if (audit_get_containerid() == (long long)-2)
+ if (audit_get_containerid(0) == (long long)-2)
rc = audit_send(fd, AUDIT_SIGNAL_INFO, NULL, 0);
else
rc = audit_send(fd, AUDIT_SIGNAL_INFO2, NULL, 0);
@@ -981,29 +981,85 @@ uint32_t audit_get_session(void)
* This function will retrieve the audit container identifier or -2 if
* there is an error.
*/
-uint64_t audit_get_containerid(void)
+uint64_t audit_get_containerid(pid_t pid)
{
- uint64_t containerid;
- int len, in;
- char buf[32];
-
- errno = 0;
- in = open("/proc/self/audit_containerid", O_NOFOLLOW|O_RDONLY);
- if (in < 0)
+ if ((audit_get_features() & AUDIT_FEATURE_BITMAP_CONTAINERID) == 0) {
return -2;
- do {
- len = read(in, buf, sizeof(buf));
- } while (len < 0 && errno == EINTR);
- close(in);
- if (len < 0 || len >= sizeof(buf))
+ } else {
+ struct audit_reply rep;
+ int i;
+ int timeout = 40; /* tenths of seconds */
+ struct pollfd pfd[1];
+ int fd = audit_open();
+ struct audit_cont_status cs;
+ int rc;
+
+ if (fd < 0) {
+ audit_msg(audit_priority(errno), "Error openning get contid 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 contid 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_CONTID)
+ continue;
+
+ /* Found it... */
+ audit_close(fd);
+ if (rep.cont->pid == pid)
+ return rep.cont->id;
+ else
+ return -2;
+ }
+ }
+ audit_close(fd);
return -2;
- buf[len] = 0;
- errno = 0;
- containerid = strtoull(buf, 0, 10);
- if (errno)
+ }
+}
+
+/*
+ * This function returns 0 on success and 1 on failure
+ */
+int audit_set_containerid(pid_t pid, uint64_t contid)
+{
+ if ((audit_get_features() & AUDIT_FEATURE_BITMAP_CONTAINERID) == 0) {
return -2;
- else
- return containerid;
+ } else {
+ int rc;
+ int seq;
+ int fd = audit_open();
+ struct audit_cont_status cs = { pid, contid };
+
+ if (fd < 0) {
+ audit_msg(audit_priority(errno), "Error openning set audit_containerid req (%s)", strerror(-rc));
+ return 1;
+ }
+ rc = audit_send(fd, AUDIT_SET_CONTID, &cs, sizeof(cs));
+ if (rc < 0) {
+ audit_msg(audit_priority(errno), "Error sending set audit_containerid request (%s)", strerror(-rc));
+ return 1;
+ }
+ return 0;
+ }
}

int audit_rule_syscall_data(struct audit_rule_data *rule, int scall)
diff --git a/lib/libaudit.h b/lib/libaudit.h
index 29e61c876e4c..af58ef563987 100644
--- a/lib/libaudit.h
+++ b/lib/libaudit.h
@@ -255,6 +255,14 @@ extern "C" {
#define AUDIT_SIGNAL_INFO2 1021 /* auditd signal sender info */
#endif

+#ifndef AUDIT_GET_CONTID
+#define AUDIT_GET_CONTID 1022 /* get contid of specified pid */
+#endif
+
+#ifndef AUDIT_SET_CONTID
+#define AUDIT_SET_CONTID 1023 /* set contid of specified pid */
+#endif
+
#ifndef AUDIT_MMAP
#define AUDIT_MMAP 1323 /* Descriptor and flags in mmap */
#endif
@@ -512,6 +520,11 @@ struct audit_message {
// internal - forward declaration
struct daemon_conf;

+struct audit_cont_status {
+ pid_t pid;
+ uint64_t id;
+};
+
struct audit_reply {
int type;
int len;
@@ -532,6 +545,9 @@ struct audit_reply {
#ifdef AUDIT_FEATURE_BITMAP_ALL
struct audit_features *features;
#endif
+#ifdef AUDIT_FEATURE_BITMAP_CONTAINERID
+ struct audit_cont_status *cont;
+#endif
};
};

@@ -602,7 +618,8 @@ extern int audit_get_reply(int fd, struct audit_reply *rep, reply_t block,
extern uid_t audit_getloginuid(void);
extern int audit_setloginuid(uid_t uid);
extern uint32_t audit_get_session(void);
-extern uint64_t audit_get_containerid(void);
+extern uint64_t audit_get_containerid(pid_t pid);
+extern int audit_set_containerid(pid_t pid, uint64_t);
extern int audit_detect_machine(void);
extern int audit_determine_machine(const char *arch);
extern bool audit_signal_info_has_ctx(struct audit_reply *rep);
diff --git a/lib/msg_typetab.h b/lib/msg_typetab.h
index 6c786933b63e..e37070cd82e2 100644
--- a/lib/msg_typetab.h
+++ b/lib/msg_typetab.h
@@ -45,6 +45,8 @@ _S(AUDIT_LOGIN, "LOGIN" )
//_S(AUDIT_SET_FEATURE, "SET_FEATURE" )
//_S(AUDIT_GET_FEATURE, "GET_FEATURE" )
//_S(AUDIT_SIGNAL_INFO2, "SIGNAL_INFO2" )
+//_S(AUDIT_GET_CONTID, "GET_CONTID" )
+//_S(AUDIT_SET_CONTID, "SET_CONTID" )
_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 66a3a3b7e83c..d177b865a79e 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -152,6 +152,9 @@ static int adjust_reply(struct audit_reply *rep, int len)
defined(HAVE_STRUCT_AUDIT_STATUS_FEATURE_BITMAP)
rep->features = NULL;
#endif
+#ifdef AUDIT_FEATURE_BITMAP_CONTAINERID
+ rep->cont = NULL;
+#endif
if (!NLMSG_OK(rep->nlh, (unsigned int)len)) {
if (len == sizeof(rep->msg)) {
audit_msg(LOG_ERR,
@@ -198,6 +201,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_CONTID:
+ rep->cont = NLMSG_DATA(rep->nlh);
+ break;
}
return len;
}
--
1.8.3.1