blob: e13fc7c04ebcd34950c854cede57dce02b6a9cf2 [file] [log] [blame]
Roberto Sassu3ce1217d2013-06-07 12:16:30 +02001/*
2 * Copyright (C) 2013 Politecnico di Torino, Italy
3 * TORSEC group -- http://security.polito.it
4 *
5 * Author: Roberto Sassu <roberto.sassu@polito.it>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2 of the
10 * License.
11 *
12 * File: ima_template_lib.c
13 * Library of supported template fields.
14 */
15#include "ima_template_lib.h"
16
17enum data_formats { DATA_FMT_DIGEST = 0, DATA_FMT_EVENT_NAME, DATA_FMT_STRING };
18static int ima_write_template_field_data(const void *data, const u32 datalen,
19 enum data_formats datafmt,
20 struct ima_field_data *field_data)
21{
22 u8 *buf, *buf_ptr;
23 u32 buflen;
24
25 switch (datafmt) {
26 case DATA_FMT_EVENT_NAME:
27 buflen = IMA_EVENT_NAME_LEN_MAX + 1;
28 break;
29 case DATA_FMT_STRING:
30 buflen = datalen + 1;
31 break;
32 default:
33 buflen = datalen;
34 }
35
36 buf = kzalloc(buflen, GFP_KERNEL);
37 if (!buf)
38 return -ENOMEM;
39
40 memcpy(buf, data, datalen);
41
42 /*
43 * Replace all space characters with underscore for event names and
44 * strings. This avoid that, during the parsing of a measurements list,
45 * filenames with spaces or that end with the suffix ' (deleted)' are
46 * split into multiple template fields (the space is the delimitator
47 * character for measurements lists in ASCII format).
48 */
49 if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) {
50 for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++)
51 if (*buf_ptr == ' ')
52 *buf_ptr = '_';
53 }
54
55 field_data->data = buf;
56 field_data->len = buflen;
57 return 0;
58}
59
60static void ima_show_template_data_ascii(struct seq_file *m,
61 enum ima_show_type show,
62 enum data_formats datafmt,
63 struct ima_field_data *field_data)
64{
65 switch (datafmt) {
66 case DATA_FMT_DIGEST:
67 ima_print_digest(m, field_data->data, field_data->len);
68 break;
69 case DATA_FMT_STRING:
70 seq_printf(m, "%s", field_data->data);
71 break;
72 default:
73 break;
74 }
75}
76
77static void ima_show_template_data_binary(struct seq_file *m,
78 enum ima_show_type show,
79 enum data_formats datafmt,
80 struct ima_field_data *field_data)
81{
82 ima_putc(m, &field_data->len, sizeof(u32));
83 if (!field_data->len)
84 return;
85 ima_putc(m, field_data->data, field_data->len);
86}
87
88static void ima_show_template_field_data(struct seq_file *m,
89 enum ima_show_type show,
90 enum data_formats datafmt,
91 struct ima_field_data *field_data)
92{
93 switch (show) {
94 case IMA_SHOW_ASCII:
95 ima_show_template_data_ascii(m, show, datafmt, field_data);
96 break;
97 case IMA_SHOW_BINARY:
98 ima_show_template_data_binary(m, show, datafmt, field_data);
99 break;
100 default:
101 break;
102 }
103}
104
105void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
106 struct ima_field_data *field_data)
107{
108 ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data);
109}
110
111void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
112 struct ima_field_data *field_data)
113{
114 ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
115}
116
117/*
118 * This function writes the digest of an event.
119 */
120int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
121 const unsigned char *filename,
122 struct ima_field_data *field_data)
123{
124 struct {
125 struct ima_digest_data hdr;
126 char digest[IMA_MAX_DIGEST_SIZE];
127 } hash;
128 u8 *cur_digest = hash.hdr.digest;
129 u32 cur_digestsize = IMA_DIGEST_SIZE;
130 struct inode *inode;
131 int result;
132
133 memset(&hash, 0, sizeof(hash));
134
135 if (!iint) /* recording a violation. */
136 goto out;
137
138 if (iint->ima_hash->algo == ima_hash_algo) {
139 cur_digest = iint->ima_hash->digest;
140 cur_digestsize = iint->ima_hash->length;
141 goto out;
142 }
143
144 if (!file) /* missing info to re-calculate the digest */
145 return -EINVAL;
146
147 inode = file_inode(file);
148 hash.hdr.algo = ima_hash_algo;
149 result = ima_calc_file_hash(file, &hash.hdr);
150 if (result) {
151 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
152 filename, "collect_data",
153 "failed", result, 0);
154 return result;
155 }
156out:
157 return ima_write_template_field_data(cur_digest, cur_digestsize,
158 DATA_FMT_DIGEST, field_data);
159}
160
161/*
162 * This function writes the name of an event.
163 */
164int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
165 const unsigned char *filename,
166 struct ima_field_data *field_data)
167{
168 const char *cur_filename = NULL;
169 u32 cur_filename_len = 0;
170
171 BUG_ON(filename == NULL && file == NULL);
172
173 if (filename) {
174 cur_filename = filename;
175 cur_filename_len = strlen(filename);
176
177 if (cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
178 goto out;
179 }
180
181 if (file) {
182 cur_filename = file->f_dentry->d_name.name;
183 cur_filename_len = strlen(cur_filename);
184 } else
185 /*
186 * Truncate filename if the latter is too long and
187 * the file descriptor is not available.
188 */
189 cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
190out:
191 return ima_write_template_field_data(cur_filename, cur_filename_len,
192 DATA_FMT_EVENT_NAME, field_data);
193}