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: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -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,
|
|||||||
|
|
||||||
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;
|
||||||
|
Reference in New Issue
Block a user