[Rpm-maint] [PATCH 3/4] Label ima xattr when signed files are installed

fin at linux.vnet.ibm.com fin at linux.vnet.ibm.com
Tue Oct 7 20:19:17 UTC 2014


From: Fionnuala Gunter <fin at linux.vnet.ibm.com>

This patch creates a new rpm-plugin for IMA and extends the rpm installer.
When a package with signed files is installed, the file signatures are 
extracted from the package header, and passed to the IMA plugin. The IMA 
plugin labels the security.ima xattr with the file signature.

Signed-off-by: Fionnuala Gunter <fin at linux.vnet.ibm.com>
---
 lib/fsm.c           | 23 ++++++++++++++-
 macros.in           |  1 +
 plugins/Makefile.am |  4 +++
 plugins/ima.c       | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 plugins/ima.c

diff --git a/lib/fsm.c b/lib/fsm.c
index e7c2a3b..dbeeaab 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -20,6 +20,7 @@
 #include "lib/rpmte_internal.h"	/* XXX rpmfs */
 #include "lib/rpmplugins.h"	/* rpm plugins hooks */
 #include "lib/rpmug.h"
+#include "lib/rpmlib.h"
 
 #include "debug.h"
 
@@ -823,12 +824,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
     char *tid = NULL;
     const char *suffix;
     char *fpath = NULL;
+    Header h = rpmteHeader(te);
+    struct rpmtd_s sigs;
+    char *sig = NULL;
 
     if (fi == NULL) {
 	rc = RPMERR_BAD_MAGIC;
 	goto exit;
     }
 
+    if (h == NULL) {
+	rc = RPMRC_FAIL;
+	goto exit;
+    }
+
+    headerGet(h, RPMTAG_FILESIGNATURES, &sigs, HEADERGET_MINMEM);
+
     /* transaction id used for temporary path suffix while installing */
     rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
 
@@ -953,9 +964,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
 	if (rc)
 	    *failedFile = xstrdup(fpath);
 
+	/* get file signatures from header */
+	if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
+	    sig = rpmtdNextString(&sigs);
+	} else {
+	    sig = NULL;
+	    rpmtdNextString(&sigs);
+	}
+
 	/* Run fsm file post hook for all plugins */
 	rpmpluginsCallFsmFilePost(plugins, fi, fpath,
-				  sb.st_mode, action, NULL, rc);
+				  sb.st_mode, action, sig, rc);
 	fpath = _free(fpath);
     }
 
@@ -965,6 +984,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
 exit:
 
     /* No need to bother with close errors on read */
+    rpmtdFreeData(&sigs);
+    headerFree(h);
     rpmfiArchiveClose(fi);
     rpmfiFree(fi);
     Fclose(payload);
diff --git a/macros.in b/macros.in
index 1647104..0b62991 100644
--- a/macros.in
+++ b/macros.in
@@ -1043,6 +1043,7 @@ done \
 %__transaction_systemd_inhibit	%{__plugindir}/systemd_inhibit.so
 %__transaction_selinux		%{__plugindir}/selinux.so
 %__transaction_syslog		%{__plugindir}/syslog.so
+%__transaction_ima		%{__plugindir}/ima.so
 
 #------------------------------------------------------------------------------
 # Macros for further automated spec %setup and patch application
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 53b2450..18f6170 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -31,3 +31,7 @@ endif
 syslog_la_SOURCES = syslog.c
 syslog_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
 plugins_LTLIBRARIES += syslog.la
+
+ima_la_sources = ima.c
+ima_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
+plugins_LTLIBRARIES +=  ima.la
diff --git a/plugins/ima.c b/plugins/ima.c
new file mode 100644
index 0000000..6b739db
--- /dev/null
+++ b/plugins/ima.c
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2014 IBM Corporation
+ *
+ * Author: Fionnuala Gunter <fin at linux.vnet.ibm.com>
+ */
+#include <syslog.h>
+
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmlog.h>
+#include <lib/rpmplugin.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "debug.h"
+
+#define XATTR_NAME_IMA "security.ima"
+
+static int hex_to_bin(char ch)
+{
+	if ((ch >= '0') && (ch <= '9'))
+		return ch - '0';
+	ch = tolower(ch);
+	if ((ch >= 'a') && (ch <= 'f'))
+		return ch - 'a' + 10;
+	return -1;
+}
+
+static int hex2bin(char *dst, const char *src, size_t count)
+{
+	int hi, lo;
+
+	while (count--) {
+		if (*src == ' ')
+			src++;
+
+		hi = hex_to_bin(*src++);
+		lo = hex_to_bin(*src++);
+
+		if ((hi < 0) || (lo < 0))
+			return -1;
+
+		*dst++ = (hi << 4) | lo;
+        }
+	return 0;
+}
+
+static rpmRC ima_init(rpmPlugin plugin, rpmts ts)
+{
+	return RPMRC_OK;
+}
+
+static void ima_cleanup(rpmPlugin plugin)
+{
+}
+
+static rpmRC ima_fsm_file_post(rpmPlugin plugin, rpmfi fi, const char *path,
+                               mode_t file_mode, rpmFsmOp op, const char *sig,
+                               int res)
+{
+	rpmRC rc = RPMRC_OK;
+	if (sig == NULL) {
+		return rc;
+	}
+
+	int siglen = strlen(sig) + 1;
+	char bin[siglen/2];
+	hex2bin(bin, sig, siglen);
+	rc = lsetxattr(path, XATTR_NAME_IMA, bin, siglen/2, 0);
+
+	if (rpmIsDebug())
+		rpmlog(RPMLOG_DEBUG, "lsetxattr: (%s) %s\n",
+			path, (rc < 0 ? strerror(errno) : ""));
+
+	return rc;
+}
+
+struct rpmPluginHooks_s ima_hooks = {
+	.init = ima_init,
+	.cleanup = ima_cleanup,
+	.fsm_file_post = ima_fsm_file_post,
+};
-- 
1.9.3



More information about the Rpm-maint mailing list