git: 3c7f332f716d - stable/13 - Fix buffer overread in preloaded hostuuid parsing
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 25 Jan 2022 01:40:15 UTC
The branch stable/13 has been updated by jrtc27:
URL: https://cgit.FreeBSD.org/src/commit/?id=3c7f332f716d67f61012bc01a3446c1ca03c5263
commit 3c7f332f716d67f61012bc01a3446c1ca03c5263
Author: Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2021-12-22 16:47:23 +0000
Commit: Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2022-01-24 23:59:49 +0000
Fix buffer overread in preloaded hostuuid parsing
Commit b6be9566d236 stopped prison0_init writing outside of the
preloaded hostuuid's bounds. However, the preloaded data will not
(normally) have a NUL in it, and so validate_uuid will walk off the end
of the buffer in its call to sscanf. Previously if there was any
whitespace in the string we'd at least know there's a NUL one past the
end due to the off-by-one error, but now no such byte is guaranteed.
Fix this by copying to a temporary buffer and explicitly adding a NUL.
Whilst here, change the strlcpy call to use a far less suspicious
argument for dstsize; in practice it's fine, but it's an unusual pattern
and not necessary.
Found by: CHERI
Reviewed by: emaste, kevans, jhb
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D33616
(cherry picked from commit d2ef3774306c54f3999732fd02bdff39c6b4cf2a)
---
sys/kern/kern_jail.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index e9019eda4d6c..a815f423dbad 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -239,6 +239,8 @@ prison0_init(void)
{
uint8_t *file, *data;
size_t size;
+ char buf[sizeof(prison0.pr_hostuuid)];
+ bool valid;
prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset);
prison0.pr_osreldate = osreldate;
@@ -258,10 +260,31 @@ prison0_init(void)
while (size > 0 && data[size - 1] <= 0x20) {
size--;
}
- if (validate_uuid(data, size, NULL, 0) == 0) {
- (void)strlcpy(prison0.pr_hostuuid, data,
- size + 1);
- } else if (bootverbose) {
+
+ valid = false;
+
+ /*
+ * Not NUL-terminated when passed from loader, but
+ * validate_uuid requires that due to using sscanf (as
+ * does the subsequent strlcpy, since it still reads
+ * past the given size to return the true length);
+ * bounce to a temporary buffer to fix.
+ */
+ if (size >= sizeof(buf))
+ goto done;
+
+ memcpy(buf, data, size);
+ buf[size] = '\0';
+
+ if (validate_uuid(buf, size, NULL, 0) != 0)
+ goto done;
+
+ valid = true;
+ (void)strlcpy(prison0.pr_hostuuid, buf,
+ sizeof(prison0.pr_hostuuid));
+
+done:
+ if (bootverbose && !valid) {
printf("hostuuid: preload data malformed: '%.*s'\n",
(int)size, data);
}