LoadPin: Require file with verity root digests to have a header
authorMatthias Kaehlcke <mka@chromium.org>
Wed, 7 Sep 2022 01:18:12 +0000 (18:18 -0700)
committerKees Cook <keescook@chromium.org>
Wed, 7 Sep 2022 23:37:27 +0000 (16:37 -0700)
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
security/loadpin/Kconfig
security/loadpin/loadpin.c

index 994c1d9376e6b2bff820d9f5956e14f6ef031e0f..6724eaba3d36471239e814bfafccad48fa0c045b 100644 (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.
index 44521582dcba2464de36fa4119293df724dd1c51..de41621f4998e37fcdce46c1fba88e458e8fd9c8 100644 (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;