[PATCH 2/2] selftests/cgroup: don't crash on a truncated mount entry in cg_find_root()

From: Shaojie Sun

Date: Mon Sep 21 2026 - 09:33:24 EST


cg_find_root() parses /proc/self/mounts with strtok() and assumes that
every field group it walks over is a complete "device mountpoint type
options freq passno" tuple. That only holds while the buffer is big
enough for the whole file: if the buffer is too small, the last tuple is
cut short, strtok() returns NULL for the missing fields, and the
strcmp(type, ...) and strstr(options, ...) calls that follow dereference
it.

The current buffer is 10 * BUF_SIZE, so reaching this needs a mount table
over 40K, but the crash is easy to hit in a sandbox: with BUF_SIZE
overridden to 6, which leaves a 60-byte buffer, cg_find_unified_root()
segfaults instead of failing.

Stop parsing as soon as a field is missing. Nothing follows a truncated
entry, so there is nothing to parse after it either.

Signed-off-by: Shaojie Sun <sunshaojie@xxxxxxxxxx>
---
tools/testing/selftests/cgroup/lib/cgroup_util.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/tools/testing/selftests/cgroup/lib/cgroup_util.c b/tools/testing/selftests/cgroup/lib/cgroup_util.c
index 65cd85c467bb..cd73471e13d7 100644
--- a/tools/testing/selftests/cgroup/lib/cgroup_util.c
+++ b/tools/testing/selftests/cgroup/lib/cgroup_util.c
@@ -302,6 +302,16 @@ static int cg_find_root(char *root, size_t len, const char *controller,
options = strtok(NULL, delim);
strtok(NULL, delim);
strtok(NULL, delim);
+
+ /*
+ * A mount entry is "device mountpoint type options freq
+ * passno". A field can only be missing if the last entry was
+ * cut short by the buffer being too small for the file, and
+ * there is no complete entry left to look at.
+ */
+ if (!mount || !type || !options)
+ break;
+
if (strcmp(type, "cgroup") == 0) {
if (!controller || !strstr(options, controller))
continue;
--
2.50.1