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>

+21 -5
+21 -5
arch/x86/kernel/ds.c
··· 236 236 struct ds_context *context = *p_context; 237 237 238 238 if (!context) { 239 + spin_unlock(&ds_lock); 240 + 239 241 context = kzalloc(sizeof(*context), GFP_KERNEL); 240 242 241 - if (!context) 243 + if (!context) { 244 + spin_lock(&ds_lock); 242 245 return NULL; 246 + } 243 247 244 248 context->ds = kzalloc(ds_cfg.sizeof_ds, GFP_KERNEL); 245 249 if (!context->ds) { 246 250 kfree(context); 251 + spin_lock(&ds_lock); 247 252 return NULL; 253 + } 254 + 255 + spin_lock(&ds_lock); 256 + /* 257 + * Check for race - another CPU could have allocated 258 + * it meanwhile: 259 + */ 260 + if (*p_context) { 261 + kfree(context->ds); 262 + kfree(context); 263 + return *p_context; 248 264 } 249 265 250 266 *p_context = context; ··· 400 384 401 385 spin_lock(&ds_lock); 402 386 403 - error = -EPERM; 404 - if (!check_tracer(task)) 405 - goto out_unlock; 406 - 407 387 error = -ENOMEM; 408 388 context = ds_alloc_context(task); 409 389 if (!context) 390 + goto out_unlock; 391 + 392 + error = -EPERM; 393 + if (!check_tracer(task)) 410 394 goto out_unlock; 411 395 412 396 error = -EALREADY;