[RFC 03/11] ima: qualify pathname in measurement file

From: Guilherme Magalhaes
Date: Thu May 11 2017 - 12:28:56 EST


Adding new fields (mount namespace id, file inode and device name) to
uniquely identify a pathname in the measurement file considering
multiple mount namespaces. The file inode on a given device is unique
and these fields are required to identify a namespace id since this
id can be released and later reused by a different namespace.
These new fields are added to all measurement templates if
CONFIG_IMA_PER_NAMESPACE is defined.
There will still be one single measurement file even with multiple
namespaces, since for the remote attestion a single and complete list
is required.

Signed-off-by: Guilherme Magalhaes <guilherme.magalhaes@xxxxxxx>
---
security/integrity/ima/Kconfig | 8 ++++
security/integrity/ima/ima.h | 12 ++++++
security/integrity/ima/ima_template.c | 10 ++++-
security/integrity/ima/ima_template_lib.c | 70 +++++++++++++++++++++++++++++++
security/integrity/ima/ima_template_lib.h | 13 ++++++
5 files changed, 111 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 370eb2f..7331ff6 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -219,3 +219,11 @@ config IMA_APPRAISE_SIGNED_INIT
default n
help
This option requires user-space init to be signed.
+
+config IMA_PER_NAMESPACE
+ bool "Enable per mount-namespace handling of IMA policy."
+ depends on IMA
+ default n
+ help
+ This option enables another API in securityfs allowing IMA policies to
+ be defined per mount namespace.
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index b563fbd..42fb91ba 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -47,7 +47,19 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
#define IMA_TEMPLATE_NUM_FIELDS_MAX 15

#define IMA_TEMPLATE_IMA_NAME "ima"
+#define IMA_TEMPLATE_IMA_NG_NAME "ima-ng"
+#define IMA_TEMPLATE_IMA_SIG_NAME "ima-sig"
+
+#ifndef CONFIG_IMA_PER_NAMESPACE
#define IMA_TEMPLATE_IMA_FMT "d|n"
+#define IMA_TEMPLATE_IMA_NG_FMT "d-ng|n-ng"
+#define IMA_TEMPLATE_IMA_SIG_FMT "d-ng|n-ng|sig"
+#else
+#define IMA_TEMPLATE_IMA_FMT "nid|fi|dev|d|n"
+#define IMA_TEMPLATE_IMA_NG_FMT "nid|fi|dev|d-ng|n-ng"
+#define IMA_TEMPLATE_IMA_SIG_FMT "nid|fi|dev|d-ng|n-ng|sig"
+#endif
+

/* current content of the policy */
extern int ima_policy_flag;
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index cebb37c..db65c09 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -21,8 +21,8 @@

static struct ima_template_desc builtin_templates[] = {
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
- {.name = "ima-ng", .fmt = "d-ng|n-ng"},
- {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
+ {.name = IMA_TEMPLATE_IMA_NG_NAME, .fmt = IMA_TEMPLATE_IMA_NG_FMT},
+ {.name = IMA_TEMPLATE_IMA_SIG_NAME, .fmt = IMA_TEMPLATE_IMA_SIG_FMT},
{.name = "", .fmt = ""}, /* placeholder for a custom format */
};

@@ -40,6 +40,12 @@ static struct ima_template_field supported_fields[] = {
.field_show = ima_show_template_string},
{.field_id = "sig", .field_init = ima_eventsig_init,
.field_show = ima_show_template_sig},
+ {.field_id = "nid", .field_init = ima_namespaceid_init,
+ .field_show = ima_show_namespaceid},
+ {.field_id = "fi", .field_init = ima_filei_init,
+ .field_show = ima_show_filei},
+ {.field_id = "dev", .field_init = ima_dev_init,
+ .field_show = ima_show_dev},
};
#define MAX_TEMPLATE_NAME_LEN 15

diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index f9ba37b..50cde10 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -14,6 +14,8 @@
*/

#include "ima_template_lib.h"
+#include <linux/proc_ns.h>
+#include <linux/types.h>

static bool ima_template_hash_algo_allowed(u8 algo)
{
@@ -330,3 +332,71 @@ int ima_eventsig_init(struct ima_event_data *event_data,
out:
return rc;
}
+
+int ima_namespaceid_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data)
+{
+ u8 tmpbuf[64];
+ struct ns_common *ns;
+
+ ns = mntns_operations.get(current);
+ snprintf(tmpbuf, sizeof(tmpbuf), "mnt-ns=%u", ns->inum);
+ mntns_operations.put(ns);
+
+ return ima_write_template_field_data(tmpbuf, strlen(tmpbuf), DATA_FMT_STRING, field_data);
+}
+
+void ima_show_namespaceid(struct seq_file *m, enum ima_show_type show,
+ struct ima_field_data *field_data)
+{
+ ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
+}
+
+int ima_filei_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data)
+{
+ u8 tmpbuf[64];
+ struct inode *inode;
+ int rc = 0;
+
+ if (event_data->file) {
+ inode = file_inode(event_data->file);
+ snprintf(tmpbuf, sizeof(tmpbuf), "inode=%lu", inode->i_ino);
+ rc = ima_write_template_field_data(tmpbuf, strlen(tmpbuf), DATA_FMT_STRING, field_data);
+ } else {
+ pr_info("IMA: event file is NULL\n");
+ }
+
+ return rc;
+}
+
+void ima_show_filei(struct seq_file *m, enum ima_show_type show,
+ struct ima_field_data *field_data)
+{
+ ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
+}
+
+int ima_dev_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data)
+{
+ u8 tmpbuf[64];
+ struct inode *inode;
+ int rc = 0;
+
+ if (event_data->file) {
+ inode = file_inode(event_data->file);
+ snprintf(tmpbuf, sizeof(tmpbuf), "dev=%s", inode->i_sb->s_id); //TODO: check untrusted string? see audit_log_n_untrustedstring()
+ tmpbuf[sizeof(tmpbuf) - 1] = 0;
+ rc = ima_write_template_field_data(tmpbuf, strlen(tmpbuf), DATA_FMT_STRING, field_data);
+ } else {
+ pr_info("IMA: event file is NULL\n");
+ }
+
+ return rc;
+}
+
+void ima_show_dev(struct seq_file *m, enum ima_show_type show,
+ struct ima_field_data *field_data)
+{
+ ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
+}
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
index c344530..cf6a6c7 100644
--- a/security/integrity/ima/ima_template_lib.h
+++ b/security/integrity/ima/ima_template_lib.h
@@ -26,6 +26,12 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data);
void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data);
+void ima_show_namespaceid(struct seq_file *m, enum ima_show_type show,
+ struct ima_field_data *field_data);
+void ima_show_filei(struct seq_file *m, enum ima_show_type show,
+ struct ima_field_data *field_data);
+void ima_show_dev(struct seq_file *m, enum ima_show_type show,
+ struct ima_field_data *field_data);
int ima_eventdigest_init(struct ima_event_data *event_data,
struct ima_field_data *field_data);
int ima_eventname_init(struct ima_event_data *event_data,
@@ -36,4 +42,11 @@ int ima_eventname_ng_init(struct ima_event_data *event_data,
struct ima_field_data *field_data);
int ima_eventsig_init(struct ima_event_data *event_data,
struct ima_field_data *field_data);
+int ima_namespaceid_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data);
+int ima_filei_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data);
+int ima_dev_init(struct ima_event_data *event_data,
+ struct ima_field_data *field_data);
+
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */
--
2.7.4