aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Zefan <lizefan@huawei.com>2013-07-31 21:51:47 -0400
committerTejun Heo <tj@kernel.org>2013-08-01 09:29:41 -0400
commit876ede8b2b9880615be0de3ec7b8afd0a1786e76 (patch)
treeb2c238a5939a6daf9f43b6eba1b1ceaf3dc2c372
parente14880f7bb7e0dc0933af304998371dd543ceb40 (diff)
cgroup: restructure the failure path in cgroup_write_event_control()
It uses a single label and checks the validity of each pointer. This is err-prone, and actually we had a bug because one of the check was insufficient. Use multi lables as we do in other places. v2: - drop initializations of local variables. Signed-off-by: Li Zefan <lizefan@huawei.com> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--kernel/cgroup.c39
1 files changed, 18 insertions, 21 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 3f6593333525..9f6dab22289e 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -3934,11 +3934,11 @@ static void cgroup_event_ptable_queue_proc(struct file *file,
3934static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, 3934static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
3935 const char *buffer) 3935 const char *buffer)
3936{ 3936{
3937 struct cgroup_event *event = NULL; 3937 struct cgroup_event *event;
3938 struct cgroup *cgrp_cfile; 3938 struct cgroup *cgrp_cfile;
3939 unsigned int efd, cfd; 3939 unsigned int efd, cfd;
3940 struct file *efile = NULL; 3940 struct file *efile;
3941 struct file *cfile = NULL; 3941 struct file *cfile;
3942 char *endp; 3942 char *endp;
3943 int ret; 3943 int ret;
3944 3944
@@ -3964,31 +3964,31 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
3964 efile = eventfd_fget(efd); 3964 efile = eventfd_fget(efd);
3965 if (IS_ERR(efile)) { 3965 if (IS_ERR(efile)) {
3966 ret = PTR_ERR(efile); 3966 ret = PTR_ERR(efile);
3967 goto fail; 3967 goto out_kfree;
3968 } 3968 }
3969 3969
3970 event->eventfd = eventfd_ctx_fileget(efile); 3970 event->eventfd = eventfd_ctx_fileget(efile);
3971 if (IS_ERR(event->eventfd)) { 3971 if (IS_ERR(event->eventfd)) {
3972 ret = PTR_ERR(event->eventfd); 3972 ret = PTR_ERR(event->eventfd);
3973 goto fail; 3973 goto out_put_efile;
3974 } 3974 }
3975 3975
3976 cfile = fget(cfd); 3976 cfile = fget(cfd);
3977 if (!cfile) { 3977 if (!cfile) {
3978 ret = -EBADF; 3978 ret = -EBADF;
3979 goto fail; 3979 goto out_put_eventfd;
3980 } 3980 }
3981 3981
3982 /* the process need read permission on control file */ 3982 /* the process need read permission on control file */
3983 /* AV: shouldn't we check that it's been opened for read instead? */ 3983 /* AV: shouldn't we check that it's been opened for read instead? */
3984 ret = inode_permission(file_inode(cfile), MAY_READ); 3984 ret = inode_permission(file_inode(cfile), MAY_READ);
3985 if (ret < 0) 3985 if (ret < 0)
3986 goto fail; 3986 goto out_put_cfile;
3987 3987
3988 event->cft = __file_cft(cfile); 3988 event->cft = __file_cft(cfile);
3989 if (IS_ERR(event->cft)) { 3989 if (IS_ERR(event->cft)) {
3990 ret = PTR_ERR(event->cft); 3990 ret = PTR_ERR(event->cft);
3991 goto fail; 3991 goto out_put_cfile;
3992 } 3992 }
3993 3993
3994 /* 3994 /*
@@ -3998,18 +3998,18 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
3998 cgrp_cfile = __d_cgrp(cfile->f_dentry->d_parent); 3998 cgrp_cfile = __d_cgrp(cfile->f_dentry->d_parent);
3999 if (cgrp_cfile != cgrp) { 3999 if (cgrp_cfile != cgrp) {
4000 ret = -EINVAL; 4000 ret = -EINVAL;
4001 goto fail; 4001 goto out_put_cfile;
4002 } 4002 }
4003 4003
4004 if (!event->cft->register_event || !event->cft->unregister_event) { 4004 if (!event->cft->register_event || !event->cft->unregister_event) {
4005 ret = -EINVAL; 4005 ret = -EINVAL;
4006 goto fail; 4006 goto out_put_cfile;
4007 } 4007 }
4008 4008
4009 ret = event->cft->register_event(cgrp, event->cft, 4009 ret = event->cft->register_event(cgrp, event->cft,
4010 event->eventfd, buffer); 4010 event->eventfd, buffer);
4011 if (ret) 4011 if (ret)
4012 goto fail; 4012 goto out_put_cfile;
4013 4013
4014 efile->f_op->poll(efile, &event->pt); 4014 efile->f_op->poll(efile, &event->pt);
4015 4015
@@ -4029,16 +4029,13 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
4029 4029
4030 return 0; 4030 return 0;
4031 4031
4032fail: 4032out_put_cfile:
4033 if (cfile) 4033 fput(cfile);
4034 fput(cfile); 4034out_put_eventfd:
4035 4035 eventfd_ctx_put(event->eventfd);
4036 if (event && event->eventfd && !IS_ERR(event->eventfd)) 4036out_put_efile:
4037 eventfd_ctx_put(event->eventfd); 4037 fput(efile);
4038 4038out_kfree:
4039 if (!IS_ERR_OR_NULL(efile))
4040 fput(efile);
4041
4042 kfree(event); 4039 kfree(event);
4043 4040
4044 return ret; 4041 return ret;