diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 61 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.h | 6 |
2 files changed, 67 insertions, 0 deletions
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index f9ba37b3928d..28af43f63572 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -159,6 +159,67 @@ void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data); } +/** + * ima_parse_buf() - Parses lengths and data from an input buffer + * @bufstartp: Buffer start address. + * @bufendp: Buffer end address. + * @bufcurp: Pointer to remaining (non-parsed) data. + * @maxfields: Length of fields array. + * @fields: Array containing lengths and pointers of parsed data. + * @curfields: Number of array items containing parsed data. + * @len_mask: Bitmap (if bit is set, data length should not be parsed). + * @enforce_mask: Check if curfields == maxfields and/or bufcurp == bufendp. + * @bufname: String identifier of the input buffer. + * + * Return: 0 on success, -EINVAL on error. + */ +int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp, + int maxfields, struct ima_field_data *fields, int *curfields, + unsigned long *len_mask, int enforce_mask, char *bufname) +{ + void *bufp = bufstartp; + int i; + + for (i = 0; i < maxfields; i++) { + if (len_mask == NULL || !test_bit(i, len_mask)) { + if (bufp > (bufendp - sizeof(u32))) + break; + + fields[i].len = *(u32 *)bufp; + if (ima_canonical_fmt) + fields[i].len = le32_to_cpu(fields[i].len); + + bufp += sizeof(u32); + } + + if (bufp > (bufendp - fields[i].len)) + break; + + fields[i].data = bufp; + bufp += fields[i].len; + } + + if ((enforce_mask & ENFORCE_FIELDS) && i != maxfields) { + pr_err("%s: nr of fields mismatch: expected: %d, current: %d\n", + bufname, maxfields, i); + return -EINVAL; + } + + if ((enforce_mask & ENFORCE_BUFEND) && bufp != bufendp) { + pr_err("%s: buf end mismatch: expected: %p, current: %p\n", + bufname, bufendp, bufp); + return -EINVAL; + } + + if (curfields) + *curfields = i; + + if (bufcurp) + *bufcurp = bufp; + + return 0; +} + static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, struct ima_field_data *field_data) { diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h index c344530c1d69..6a3d8b831deb 100644 --- a/security/integrity/ima/ima_template_lib.h +++ b/security/integrity/ima/ima_template_lib.h @@ -18,6 +18,9 @@ #include <linux/seq_file.h> #include "ima.h" +#define ENFORCE_FIELDS 0x00000001 +#define ENFORCE_BUFEND 0x00000002 + void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, struct ima_field_data *field_data); void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, @@ -26,6 +29,9 @@ 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); +int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp, + int maxfields, struct ima_field_data *fields, int *curfields, + unsigned long *len_mask, int enforce_mask, char *bufname); 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, |