[PATCH -next] cgroup/pids: Avoid spurious event notification

From: Xiu Jianfeng
Date: Mon Jul 29 2024 - 07:07:45 EST


From: Xiu Jianfeng <xiujianfeng@xxxxxxxxxx>

Currently when a process in a group forks and fails due to it's
parent's max restriction, all the cgroups from 'pids_forking' to root
will generate event notifications but only the cgroups from
'pids_over_limit' to root will increase the counter of PIDCG_MAX.

Consider this scenario: there are 4 groups A, B, C,and D, the
relationships are as follows, and user is watching on C.pids.events.

root->A->B->C->D

When a process in D forks and fails due to B.max restriction, the
user will get a spurious event notification because when he wakes up
and reads C.pids.events, he will find that the content has not changed.

To address this issue, only the cgroups from 'pids_over_limit' to root
will have their PIDCG_MAX counter increased and event notifications
generated.

Signed-off-by: Xiu Jianfeng <xiujianfeng@xxxxxxxxxx>
---
kernel/cgroup/pids.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/kernel/cgroup/pids.c b/kernel/cgroup/pids.c
index f5cb0ec45b9d..1c8c9f76ff0e 100644
--- a/kernel/cgroup/pids.c
+++ b/kernel/cgroup/pids.c
@@ -244,7 +244,6 @@ static void pids_event(struct pids_cgroup *pids_forking,
struct pids_cgroup *pids_over_limit)
{
struct pids_cgroup *p = pids_forking;
- bool limit = false;

/* Only log the first time limit is hit. */
if (atomic64_inc_return(&p->events_local[PIDCG_FORKFAIL]) == 1) {
@@ -257,15 +256,11 @@ static void pids_event(struct pids_cgroup *pids_forking,
cgrp_dfl_root.flags & CGRP_ROOT_PIDS_LOCAL_EVENTS)
return;

- for (; parent_pids(p); p = parent_pids(p)) {
- if (p == pids_over_limit) {
- limit = true;
- atomic64_inc(&p->events_local[PIDCG_MAX]);
- cgroup_file_notify(&p->events_local_file);
- }
- if (limit)
- atomic64_inc(&p->events[PIDCG_MAX]);
+ atomic64_inc(&pids_over_limit->events_local[PIDCG_MAX]);
+ cgroup_file_notify(&pids_over_limit->events_local_file);

+ for (p = pids_over_limit; parent_pids(p); p = parent_pids(p)) {
+ atomic64_inc(&p->events[PIDCG_MAX]);
cgroup_file_notify(&p->events_file);
}
}
--
2.34.1