Skip to content

Commit

Permalink
mm: memcg: Correct unregistring of events attached to the same eventfd
Browse files Browse the repository at this point in the history
There is an issue when memcg unregisters events that were attached to
the same eventfd:

- On the first call mem_cgroup_usage_unregister_event() removes all
  events attached to a given eventfd, and if there were no events left,
  thresholds->primary would become NULL;

- Since there were several events registered, cgroups core will call
  mem_cgroup_usage_unregister_event() again, but now kernel will oops,
  as the function doesn't expect that threshold->primary may be NULL.

That's a good question whether mem_cgroup_usage_unregister_event()
should actually remove all events in one go, but nowadays it can't
do any better as cftype->unregister_event callback doesn't pass
any private event-associated cookie. So, let's fix the issue by
simply checking for threshold->primary.

FWIW, w/o the patch the following oops may be observed:

 BUG: unable to handle kernel NULL pointer dereference at 0000000000000004
 IP: [<ffffffff810be32c>] mem_cgroup_usage_unregister_event+0x9c/0x1f0
 Pid: 574, comm: kworker/0:2 Not tainted 3.3.0-rc4+ raspberrypi#9 Bochs Bochs
 RIP: 0010:[<ffffffff810be32c>]  [<ffffffff810be32c>] mem_cgroup_usage_unregister_event+0x9c/0x1f0
 RSP: 0018:ffff88001d0b9d60  EFLAGS: 00010246
 Process kworker/0:2 (pid: 574, threadinfo ffff88001d0b8000, task ffff88001de91cc0)
 Call Trace:
  [<ffffffff8107092b>] cgroup_event_remove+0x2b/0x60
  [<ffffffff8103db94>] process_one_work+0x174/0x450
  [<ffffffff8103e413>] worker_thread+0x123/0x2d0

Cc: stable <[email protected]>
Signed-off-by: Anton Vorontsov <[email protected]>
Acked-by: KAMEZAWA Hiroyuki <[email protected]>
Cc: Kirill A. Shutemov <[email protected]>
Cc: Michal Hocko <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Anton Vorontsov authored and torvalds committed Feb 24, 2012
1 parent 37fbf4b commit 371528c
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion mm/memcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -4414,6 +4414,9 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
*/
BUG_ON(!thresholds);

if (!thresholds->primary)
goto unlock;

usage = mem_cgroup_usage(memcg, type == _MEMSWAP);

/* Check if a threshold crossed before removing */
Expand Down Expand Up @@ -4462,7 +4465,7 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,

/* To be sure that nobody uses thresholds */
synchronize_rcu();

unlock:
mutex_unlock(&memcg->thresholds_lock);
}

Expand Down

0 comments on commit 371528c

Please sign in to comment.