diff options
author | Tejun Heo <tj@kernel.org> | 2013-08-15 11:43:15 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-08-19 09:56:34 -0400 |
commit | 6e6eab0efdf48fb2d8d7aee904d7740acb4661c6 (patch) | |
tree | 7805e157bdbe18844f650fa0a691cd8d1a6e1baf | |
parent | 0bfb4aa67cef4982adc70590a31624d7b35a0bda (diff) |
cgroup: fix cgroup_write_event_control()
81eeaf0411 ("cgroup: make cftype->[un]register_event() deal with
cgroup_subsys_state inst ead of cgroup") updated the cftype event
methods to take @css (cgroup_subsys_state) instead of @cgroup;
however, it incorrectly used @css passed to
cgroup_write_event_control(), which the dummy_css for the cgroup as
the file is a cgroup core file. This leads to oops on event
registration.
Fix it by using the css matching the event target file. Note that
cgroup_write_event_control() now disallows cgroup core files from
being event sources. This is for simplicity and doesn't matter as
cgroup_event will be moved and made specific to memcg.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r-- | kernel/cgroup.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 896e035eb6e4..ef43e3f453ef 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4040,10 +4040,10 @@ static void cgroup_event_ptable_queue_proc(struct file *file, | |||
4040 | * Input must be in format '<event_fd> <control_fd> <args>'. | 4040 | * Input must be in format '<event_fd> <control_fd> <args>'. |
4041 | * Interpretation of args is defined by control file implementation. | 4041 | * Interpretation of args is defined by control file implementation. |
4042 | */ | 4042 | */ |
4043 | static int cgroup_write_event_control(struct cgroup_subsys_state *css, | 4043 | static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css, |
4044 | struct cftype *cft, const char *buffer) | 4044 | struct cftype *cft, const char *buffer) |
4045 | { | 4045 | { |
4046 | struct cgroup *cgrp = css->cgroup; | 4046 | struct cgroup *cgrp = dummy_css->cgroup; |
4047 | struct cgroup_event *event; | 4047 | struct cgroup_event *event; |
4048 | struct cgroup *cgrp_cfile; | 4048 | struct cgroup *cgrp_cfile; |
4049 | unsigned int efd, cfd; | 4049 | unsigned int efd, cfd; |
@@ -4065,7 +4065,7 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css, | |||
4065 | event = kzalloc(sizeof(*event), GFP_KERNEL); | 4065 | event = kzalloc(sizeof(*event), GFP_KERNEL); |
4066 | if (!event) | 4066 | if (!event) |
4067 | return -ENOMEM; | 4067 | return -ENOMEM; |
4068 | event->css = css; | 4068 | |
4069 | INIT_LIST_HEAD(&event->list); | 4069 | INIT_LIST_HEAD(&event->list); |
4070 | init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc); | 4070 | init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc); |
4071 | init_waitqueue_func_entry(&event->wait, cgroup_event_wake); | 4071 | init_waitqueue_func_entry(&event->wait, cgroup_event_wake); |
@@ -4101,6 +4101,23 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css, | |||
4101 | goto out_put_cfile; | 4101 | goto out_put_cfile; |
4102 | } | 4102 | } |
4103 | 4103 | ||
4104 | if (!event->cft->ss) { | ||
4105 | ret = -EBADF; | ||
4106 | goto out_put_cfile; | ||
4107 | } | ||
4108 | |||
4109 | /* determine the css of @cfile and associate @event with it */ | ||
4110 | rcu_read_lock(); | ||
4111 | |||
4112 | ret = -EINVAL; | ||
4113 | event->css = cgroup_css(cgrp, event->cft->ss->subsys_id); | ||
4114 | if (event->css) | ||
4115 | ret = 0; | ||
4116 | |||
4117 | rcu_read_unlock(); | ||
4118 | if (ret) | ||
4119 | goto out_put_cfile; | ||
4120 | |||
4104 | /* | 4121 | /* |
4105 | * The file to be monitored must be in the same cgroup as | 4122 | * The file to be monitored must be in the same cgroup as |
4106 | * cgroup.event_control is. | 4123 | * cgroup.event_control is. |
@@ -4116,7 +4133,7 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css, | |||
4116 | goto out_put_cfile; | 4133 | goto out_put_cfile; |
4117 | } | 4134 | } |
4118 | 4135 | ||
4119 | ret = event->cft->register_event(css, event->cft, | 4136 | ret = event->cft->register_event(event->css, event->cft, |
4120 | event->eventfd, buffer); | 4137 | event->eventfd, buffer); |
4121 | if (ret) | 4138 | if (ret) |
4122 | goto out_put_cfile; | 4139 | goto out_put_cfile; |