diff --git a/README.en.md b/README.en.md index 99bf9a7d2315d49806f34031b744352af14c66f1..37a1dfef150bad61cb26e1d6b1e7fd28e48be2f2 100644 --- a/README.en.md +++ b/README.en.md @@ -52,6 +52,10 @@ Lists extension: Manages digest lists and converts digest lists of arbitrary formats to the format supported by the kernel; +- upload_digest_lists: + Runs parsers of digest lists to upload those that are in a format not + recognized by the kernel; + - verify_digest_lists: Verifies the integrity of digest lists; @@ -91,14 +95,21 @@ the $libdir/digestlist directory. (4) parse digest list (fmt N) | +----------+ +----------+ | | Parser 1 | ... | Parser N | <--------------------------------| - +----------+ +----------+ - +-----------------------------------+ - | Compact list API (generator) | (5) convert to compact list - +-----------------------------------+ - +-----------------------------------+ - | Base library (I/O) | - +-----------------------------------+ - + +----------+ +----------+ | + +-----------------------------------+ | + | Compact list API (generator) | (5) convert to compact list | + +-----------------------------------+ and sign | + +-----------------------------------+ +-------------+ | + | Base library (I/O) | <---- | Signing Key | | + +-----------------------------------+ +-------------+ | + | | + | | + | | + upload_digest_lists: | | + | (6) upload digest list +------------+ + +-------------+ | Parser | + | Kernel | <--------------------------------- | exec | + +-------------+ +------------+ diff --git a/dist/rpm/digest-list-tools.spec b/dist/rpm/digest-list-tools.spec index da570584156d2876ce82549bf032f710238f9198..00ead9d2cfc46f2a1daa546294f5f883288d8238 100644 --- a/dist/rpm/digest-list-tools.spec +++ b/dist/rpm/digest-list-tools.spec @@ -55,6 +55,7 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/setup_ima_digest_lists %{_bindir}/setup_ima_digest_lists_demo %{_bindir}/manage_digest_lists +%{_bindir}/upload_digest_lists %{_bindir}/verify_digest_lists %{_bindir}/write_rpm_pgp_sig %{_libdir}/libdigestlist-base.so @@ -84,6 +85,7 @@ rm -rf $RPM_BUILD_ROOT %{_datarootdir}/digest-list-tools/setup_ima_digest_lists.txt %{_datarootdir}/digest-list-tools/setup_ima_digest_lists_demo.txt %{_datarootdir}/digest-list-tools/manage_digest_lists.txt +%{_datarootdir}/digest-list-tools/upload_digest_lists.txt %{_datarootdir}/digest-list-tools/verify_digest_lists.txt %{_datarootdir}/digest-list-tools/write_rpm_pgp_sig.txt %{_mandir}/man1/gen_digest_lists.1.gz @@ -91,6 +93,7 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man1/setup_ima_digest_lists_demo.1.gz %{_mandir}/man1/verify_digest_lists.1.gz %{_mandir}/man1/manage_digest_lists.1.gz +%{_mandir}/man1/upload_digest_lists.1.gz %{_mandir}/man1/write_rpm_pgp_sig.1.gz %{_mandir}/man1/%{name}.1.gz diff --git a/docs/Makefile.am b/docs/Makefile.am index dd7cd79dc29c134a2359838b6f8f74d3cbb7a343..69d25275a37efbad8285d84bf2f8746572269621 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -2,6 +2,7 @@ dist_pkgdata_DATA = gen_digest_lists.txt \ setup_ima_digest_lists.txt \ setup_ima_digest_lists_demo.txt \ manage_digest_lists.txt \ + upload_digest_lists.txt \ verify_digest_lists.txt \ write_rpm_pgp_sig.txt @@ -9,5 +10,6 @@ man1_MANS = gen_digest_lists.1 \ setup_ima_digest_lists.1 \ setup_ima_digest_lists_demo.1 \ manage_digest_lists.1 \ + upload_digest_lists.1 \ verify_digest_lists.1 \ write_rpm_pgp_sig.1 diff --git a/docs/upload_digest_lists.1 b/docs/upload_digest_lists.1 new file mode 100644 index 0000000000000000000000000000000000000000..463131afc3a169d55a3b40e31f0dfd713bb6dd35 --- /dev/null +++ b/docs/upload_digest_lists.1 @@ -0,0 +1,39 @@ +.\" Text automatically generated by txt2man +.TH untitled "14 July 2020" "" "" +.SH NAME +\fBupload_digest_lists \fP- run digest list parsers +\fB +.RE +\fB +.SH SYNOPSIS +.nf +.fam C +\fBupload_digest_lists\fP add|del + + +.fam T +.fi +.fam T +.fi +.SH DESCRIPTION +\fBupload_digest_lists\fP runs parsers of digest lists to upload those that are +in a format not recognized by the kernel. +.RE +.PP + +.SH EXAMPLES +Run parsers of digest lists in /etc/ima/digest_lists. +.PP +# \fBupload_digest_lists\fP add /etc/ima/digest_lists +.RE +.PP + +.SH AUTHOR +Written by Roberto Sassu, . +.RE +.PP + +.SH COPYING +Copyright (C) 2020 Huawei Technologies Duesseldorf GmbH. Free use of +this software is granted under the terms of the GNU Public License 2.0 +(GPLv2). diff --git a/docs/upload_digest_lists.txt b/docs/upload_digest_lists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2b940adaf4d8ccebdd935bfb1b4a9e7825ed2ee6 --- /dev/null +++ b/docs/upload_digest_lists.txt @@ -0,0 +1,27 @@ +NAME +upload_digest_lists - run digest list parsers + + +SYNOPSIS +upload_digest_lists add|del + + +DESCRIPTION +upload_digest_lists runs parsers of digest lists to upload those that are +in a format not recognized by the kernel. + + +EXAMPLES +Run parsers of digest lists in /etc/ima/digest_lists. + +# upload_digest_lists add /etc/ima/digest_lists + + +AUTHOR +Written by Roberto Sassu, . + + +COPYING +Copyright (C) 2020 Huawei Technologies Duesseldorf GmbH. Free use of +this software is granted under the terms of the GNU Public License 2.0 +(GPLv2). diff --git a/src/Makefile.am b/src/Makefile.am index 84d263169a6b691a67f06e85bc62acc33889b6cd..50586a868e46a78ecb3ace8dd7f66b6315f52248 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ bin_PROGRAMS=manage_digest_lists gen_digest_lists verify_digest_lists \ - write_rpm_pgp_sig + write_rpm_pgp_sig upload_digest_lists manage_digest_lists_CFLAGS=-I$(top_srcdir)/include manage_digest_lists_LDFLAGS=$(top_srcdir)/lib/libdigestlist-base.la @@ -16,3 +16,8 @@ verify_digest_lists_SOURCES=verify_digest_lists.c write_rpm_pgp_sig_CFLAGS=-I$(top_srcdir)/include write_rpm_pgp_sig_LDFLAGS=$(top_srcdir)/lib/libdigestlist-base.la write_rpm_pgp_sig_SOURCES=write_rpm_pgp_sig.c + +upload_digest_lists_CFLAGS=-I$(top_srcdir)/include +upload_digest_lists_LDFLAGS=-all-static +upload_digest_lists_SOURCES=upload_digest_lists.c + diff --git a/src/upload_digest_lists.c b/src/upload_digest_lists.c new file mode 100644 index 0000000000000000000000000000000000000000..37c0c53e5b725a75a571912b028550d638574718 --- /dev/null +++ b/src/upload_digest_lists.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2020 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * File: upload_digest_lists.c + * Run parsers of digest list formats not recognizable by the kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "list.h" + +#define MOUNT_FLAGS MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME + +#define SYSFS_PATH "/sys" +#define SECURITYFS_PATH SYSFS_PATH "/kernel/security" +#define DIGEST_LIST_DATA SECURITYFS_PATH "/ima/digest_list_data" + +struct format_entry { + struct list_head list; + char *format; +}; + +LIST_HEAD(formats); + +int add_format_parser(char *path) +{ + char *format = NULL, *name; + char *type_start, *format_start, *format_end; + struct format_entry *cur, *new; + int ret = 0; + + name = strrchr(path, '/'); + if (!name) + return -EINVAL; + + name++; + + type_start = strchr(name, '-'); + if (!type_start) + return 0; + + format_start = strchr(type_start + 1, '-'); + if (!format_start) + return 0; + + format_end = strchr(format_start + 1, '-'); + if (!format_end) + return 0; + + format = strndup(format_start + 1, format_end - format_start - 1); + if (!format) + return -ENOMEM; + + list_for_each_entry(cur, &formats, list) + if (!strcmp(format, cur->format)) + goto out; + + if (!strcmp(format, "compact")) + goto out; + + new = malloc(sizeof(*new)); + if (!new) { + ret = -ENOMEM; + goto out; + } + + new->format = format; + list_add(&new->list, &formats); +out: + if (ret < 0) + free(format); + + return ret; +} + +static int init_digest_list_upload(int *mount_sysfs, int *mount_securityfs) +{ + struct stat st; + int ret; + + if (!stat(SECURITYFS_PATH, &st)) + goto mount_securityfs; + + ret = mount(SYSFS_PATH, SYSFS_PATH, "sysfs", MOUNT_FLAGS, NULL); + if (ret < 0) { + printf("Cannot mount %s (%s)\n", SYSFS_PATH, + strerror(errno)); + return ret; + } + + *mount_sysfs = 1; +mount_securityfs: + if (!stat(DIGEST_LIST_DATA, &st)) + return 0; + + ret = mount(SECURITYFS_PATH, SECURITYFS_PATH, "securityfs", MOUNT_FLAGS, + NULL); + if (ret < 0) { + printf("Cannot mount %s (%s)\n", SECURITYFS_PATH, + strerror(errno)); + return ret; + } + + *mount_securityfs = 1; + return 0; +} + +static void end_digest_list_upload(int umount_sysfs, int umount_securityfs) +{ + if (umount_securityfs) + umount(SECURITYFS_PATH); + if (umount_sysfs) + umount(SYSFS_PATH); +} + +int main(int argc, char *argv[]) +{ + int mount_sysfs = 0, mount_securityfs = 0; + char *paths[2] = { NULL, NULL }; + struct format_entry *cur, *tmp; + char parser_path[PATH_MAX]; + FTS *fts = NULL; + FTSENT *ftsent; + int fts_flags = (FTS_PHYSICAL | FTS_COMFOLLOW | FTS_NOCHDIR | FTS_XDEV); + int ret; + + if (argc != 3) { + printf("Usage: %s add|del \n", argv[0]); + return -EINVAL; + } + + paths[0] = argv[2]; + + fts = fts_open(paths, fts_flags, NULL); + if (!fts) + return -EACCES; + + while ((ftsent = fts_read(fts)) != NULL) { + switch (ftsent->fts_info) { + case FTS_F: + ret = add_format_parser(ftsent->fts_path); + if (ret < 0) + printf("Cannot upload %s\n", ftsent->fts_path); + + break; + default: + break; + } + } + + fts_close(fts); + fts = NULL; + + ret = init_digest_list_upload(&mount_sysfs, &mount_securityfs); + if (ret < 0) + return -EACCES; + + list_for_each_entry_safe(cur, tmp, &formats, list) { + if (fork() == 0) { + snprintf(parser_path, sizeof(parser_path), + "/usr/libexec/%s_parser", cur->format); + return execlp(parser_path, parser_path, argv[1], + argv[2], NULL); + } + + wait(NULL); + + list_del(&cur->list); + free(cur->format); + free(cur); + } + + end_digest_list_upload(mount_sysfs, mount_securityfs); + return 0; +}