Skip to content

Commit 4d6593c

Browse files
author
Harold Seigel
committed
8272124: Cgroup v1 initialization causes NullPointerException when cgroup path contains colon
Reviewed-by: mseledtsov, sgehwolf
1 parent 30b0f82 commit 4d6593c

2 files changed

Lines changed: 57 additions & 3 deletions

File tree

src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,10 @@ public static Optional<CgroupTypeResult> determineType(String mountInfo,
196196
if (isCgroupsV2) {
197197
action = (tokens -> setCgroupV2Path(infos, tokens));
198198
}
199-
selfCgroupLines.map(line -> line.split(":"))
200-
.filter(tokens -> (tokens.length >= 3))
201-
.forEach(action);
199+
// The limit value of 3 is because /proc/self/cgroup contains three
200+
// colon-separated tokens per line. The last token, cgroup path, might
201+
// contain a ':'.
202+
selfCgroupLines.map(line -> line.split(":", 3)).forEach(action);
202203
}
203204

204205
CgroupTypeResult result = new CgroupTypeResult(isCgroupsV2,

test/jdk/jdk/internal/platform/cgroup/TestCgroupSubsystemFactory.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ public class TestCgroupSubsystemFactory {
7171
private Path cgroupv1MntInfoSystemdOnly;
7272
private Path cgroupv1MntInfoDoubleCpusets;
7373
private Path cgroupv1MntInfoDoubleCpusets2;
74+
private Path cgroupv1MntInfoColonsHierarchy;
7475
private Path cgroupv1SelfCgroup;
76+
private Path cgroupv1SelfColons;
7577
private Path cgroupv2SelfCgroup;
7678
private Path cgroupv1SelfCgroupJoinCtrl;
7779
private Path cgroupv1CgroupsOnlyCPUCtrl;
@@ -150,6 +152,20 @@ public class TestCgroupSubsystemFactory {
150152
"41 31 0:36 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,blkio\n" +
151153
"42 31 0:37 / /sys/fs/cgroup/rdma rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,rdma\n" +
152154
"43 31 0:38 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,freezer\n";
155+
private String mntInfoColons =
156+
"30 23 0:26 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,seclabel,mode=755\n" +
157+
"31 30 0:27 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 none rw,seclabel,nsdelegate\n" +
158+
"32 30 0:28 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:6 - cgroup none rw,seclabel,xattr,name=systemd\n" +
159+
"4624 4583 0:31 /system.slice/containerd.service/kubepods-burstable-podf65e797d_d5f9_4604_9773_94f4bb9946a0.slice:cri-containerd:86ac6260f9f8a9c1276748250f330ae9c2fcefe5ae809364ad1e45f3edf7e08a /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime master:12 - cgroup cgroup rw,memory\n" +
160+
"36 30 0:32 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:8 - cgroup none rw,seclabel,pids\n" +
161+
"37 30 0:33 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:9 - cgroup none rw,seclabel,perf_event\n" +
162+
"38 30 0:34 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:10 - cgroup none rw,seclabel,net_cls,net_prio\n" +
163+
"39 30 0:35 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:11 - cgroup none rw,seclabel,hugetlb\n" +
164+
"40 30 0:36 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup none rw,seclabel,cpu,cpuacct\n" +
165+
"41 30 0:37 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:13 - cgroup none rw,seclabel,devices\n" +
166+
"42 30 0:38 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:14 - cgroup none rw,seclabel,cpuset\n" +
167+
"43 30 0:39 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup none rw,seclabel,blkio\n" +
168+
"44 30 0:40 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:16 - cgroup none rw,seclabel,freezer\n";
153169
private String cgroupsNonZeroHierarchy =
154170
"#subsys_name hierarchy num_cgroups enabled\n" +
155171
"cpuset 9 1 1\n" +
@@ -184,6 +200,23 @@ public class TestCgroupSubsystemFactory {
184200
"2:cpu,cpuacct:/\n" +
185201
"1:name=systemd:/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n" +
186202
"0::/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n";
203+
204+
// `/proc/self/cgroup` should contain **three** colon-separated fields,
205+
// `hierarchy-ID:controller-list:cgroup-path`. This cgroup-path intentionally
206+
// contains a colon to ensure that the correct path is being extracted by the
207+
// logic in CgroupSubsystemFactory.
208+
private String cgroupv1SelfColonsContent = "11:memory:/system.slice/containerd.service/kubepods-burstable-podf65e797d_d5f9_4604_9773_94f4bb9946a0.slice:cri-containerd:86ac6260f9f8a9c1276748250f330ae9c2fcefe5ae809364ad1e45f3edf7e08a\n" +
209+
"10:hugetlb:/\n" +
210+
"9:cpuset:/\n" +
211+
"8:pids:/user.slice/user-1000.slice/user@1000.service\n" +
212+
"7:freezer:/\n" +
213+
"6:blkio:/\n" +
214+
"5:net_cls,net_prio:/\n" +
215+
"4:devices:/user.slice\n" +
216+
"3:perf_event:/\n" +
217+
"2:cpu,cpuacct:/\n" +
218+
"1:name=systemd:/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n" +
219+
"0::/user.slice/user-1000.slice/user@1000.service/apps.slice/apps-org.gnome.Terminal.slice/vte-spawn-3c00b338-5b65-439f-8e97-135e183d135d.scope\n";
187220
private String cgroupv2SelfCgroupContent = "0::/user.slice/user-1000.slice/session-2.scope";
188221

189222
@Before
@@ -221,9 +254,15 @@ public void setup() {
221254
cgroupv1MountInfoJoinControllers = Paths.get(existingDirectory.toString(), "mntinfo_cgv1_join_controllers");
222255
Files.writeString(cgroupv1MountInfoJoinControllers, mntInfoCgroupv1JoinControllers);
223256

257+
cgroupv1MntInfoColonsHierarchy = Paths.get(existingDirectory.toString(), "mountinfo_colons");
258+
Files.writeString(cgroupv1MntInfoColonsHierarchy, mntInfoColons);
259+
224260
cgroupv1SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv1");
225261
Files.writeString(cgroupv1SelfCgroup, cgroupv1SelfCgroupContent);
226262

263+
cgroupv1SelfColons = Paths.get(existingDirectory.toString(), "self_colons_cgv1");
264+
Files.writeString(cgroupv1SelfColons, cgroupv1SelfColonsContent);
265+
227266
cgroupv2SelfCgroup = Paths.get(existingDirectory.toString(), "self_cgroup_cgv2");
228267
Files.writeString(cgroupv2SelfCgroup, cgroupv2SelfCgroupContent);
229268

@@ -340,6 +379,20 @@ public void testHybridCgroupsV1() throws IOException {
340379
assertEquals("/sys/fs/cgroup/memory", memoryInfo.getMountPoint());
341380
}
342381

382+
@Test
383+
public void testColonsCgroupsV1() throws IOException {
384+
String cgroups = cgroupv1CgInfoNonZeroHierarchy.toString();
385+
String mountInfo = cgroupv1MntInfoColonsHierarchy.toString();
386+
String selfCgroup = cgroupv1SelfColons.toString();
387+
Optional<CgroupTypeResult> result = CgroupSubsystemFactory.determineType(mountInfo, cgroups, selfCgroup);
388+
389+
assertTrue("Expected non-empty cgroup result", result.isPresent());
390+
CgroupTypeResult res = result.get();
391+
CgroupInfo memoryInfo = res.getInfos().get("memory");
392+
assertEquals(memoryInfo.getCgroupPath(), "/system.slice/containerd.service/kubepods-burstable-podf65e797d_d5f9_4604_9773_94f4bb9946a0.slice:cri-containerd:86ac6260f9f8a9c1276748250f330ae9c2fcefe5ae809364ad1e45f3edf7e08a");
393+
assertEquals(memoryInfo.getMountRoot(), memoryInfo.getCgroupPath());
394+
}
395+
343396
@Test
344397
public void testZeroHierarchyCgroupsV1() throws IOException {
345398
String cgroups = cgroupv1CgInfoZeroHierarchy.toString();

0 commit comments

Comments
 (0)