Commit 10db4ef7 authored by Ingo Molnar's avatar Ingo Molnar

x86, PEBS/DS: fix code flow in ds_request()

this compiler warning:

  arch/x86/kernel/ds.c: In function 'ds_request':
  arch/x86/kernel/ds.c:368: warning: 'context' may be used uninitialized in this function

Shows that the code flow in ds_request() is buggy - it goes into
the unlock+release-context path even when the context is not allocated
yet.

First allocate the context, then do the other checks.

Also, take care with GFP allocations under the ds_lock spinlock.

Cc: <stable@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 93ce99e8
...@@ -236,17 +236,33 @@ static inline struct ds_context *ds_alloc_context(struct task_struct *task) ...@@ -236,17 +236,33 @@ static inline struct ds_context *ds_alloc_context(struct task_struct *task)
struct ds_context *context = *p_context; struct ds_context *context = *p_context;
if (!context) { if (!context) {
spin_unlock(&ds_lock);
context = kzalloc(sizeof(*context), GFP_KERNEL); context = kzalloc(sizeof(*context), GFP_KERNEL);
if (!context) if (!context) {
spin_lock(&ds_lock);
return NULL; return NULL;
}
context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL);
if (!context->ds) { if (!context->ds) {
kfree(context); kfree(context);
spin_lock(&ds_lock);
return NULL; return NULL;
} }
spin_lock(&ds_lock);
/*
* Check for race - another CPU could have allocated
* it meanwhile:
*/
if (*p_context) {
kfree(context->ds);
kfree(context);
return *p_context;
}
*p_context = context; *p_context = context;
context->this = p_context; context->this = p_context;
...@@ -384,15 +400,15 @@ static int ds_request(struct task_struct *task, void *base, size_t size, ...@@ -384,15 +400,15 @@ static int ds_request(struct task_struct *task, void *base, size_t size,
spin_lock(&ds_lock); spin_lock(&ds_lock);
error = -EPERM;
if (!check_tracer(task))
goto out_unlock;
error = -ENOMEM; error = -ENOMEM;
context = ds_alloc_context(task); context = ds_alloc_context(task);
if (!context) if (!context)
goto out_unlock; goto out_unlock;
error = -EPERM;
if (!check_tracer(task))
goto out_unlock;
error = -EALREADY; error = -EALREADY;
if (context->owner[qual] == current) if (context->owner[qual] == current)
goto out_unlock; goto out_unlock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment