LoadPin: Require file with verity root digests to have a header

LoadPin expects the file with trusted verity root digests to be
an ASCII file with one digest (hex value) per line. A pinned
root could contain files that meet these format requirements,
even though the hex values don't represent trusted root
digests.

Add a new requirement to the file format which consists in
the first line containing a fixed string. This prevents
attackers from feeding files with an otherwise valid format
to LoadPin.

Suggested-by: Sarthak Kukreti <sarthakkukreti@chromium.org>
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20220906181725.1.I3f51d1bb0014e5a5951be4ad3c5ad7c7ca1dfc32@changeid
This commit is contained in:
Matthias Kaehlcke 2022-09-06 18:18:12 -07:00 committed by Kees Cook
parent 916ef6232c
commit 6e42aec7c7
2 changed files with 21 additions and 2 deletions

View File

@ -33,4 +33,9 @@ config SECURITY_LOADPIN_VERITY
on the LoadPin securityfs entry 'dm-verity'. The ioctl
expects a file descriptor of a file with verity digests as
parameter. The file must be located on the pinned root and
contain one digest per line.
start with the line:
# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS
This is followed by the verity digests, with one digest per
line.

View File

@ -21,6 +21,8 @@
#include <linux/dm-verity-loadpin.h>
#include <uapi/linux/loadpin.h>
#define VERITY_DIGEST_FILE_HEADER "# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS"
static void report_load(const char *origin, struct file *file, char *operation)
{
char *cmdline, *pathname;
@ -292,9 +294,21 @@ static int read_trusted_verity_root_digests(unsigned int fd)
p = strim(data);
while ((d = strsep(&p, "\n")) != NULL) {
int len = strlen(d);
int len;
struct dm_verity_loadpin_trusted_root_digest *trd;
if (d == data) {
/* first line, validate header */
if (strcmp(d, VERITY_DIGEST_FILE_HEADER)) {
rc = -EPROTO;
goto err;
}
continue;
}
len = strlen(d);
if (len % 2) {
rc = -EPROTO;
goto err;