Re: [PATCH 5/7] proc/kcore: clean up ELF header generation

From: kbuild test robot
Date: Sat Jul 07 2018 - 06:05:54 EST


Hi Omar,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v4.18-rc3 next-20180706]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Omar-Sandoval/proc-kcore-improvements/20180707-052548
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

include/linux/nodemask.h:265:16: sparse: expression using sizeof(void)
include/linux/nodemask.h:271:16: sparse: expression using sizeof(void)
>> fs//proc/kcore.c:328:23: sparse: expression using sizeof(void)
>> fs//proc/kcore.c:328:23: sparse: expression using sizeof(void)
fs//proc/kcore.c:368:23: sparse: expression using sizeof(void)
fs//proc/kcore.c:368:23: sparse: expression using sizeof(void)
>> fs//proc/kcore.c:384:49: sparse: missing braces around initializer
fs//proc/kcore.c:408:23: sparse: expression using sizeof(void)
fs//proc/kcore.c:408:23: sparse: expression using sizeof(void)

vim +328 fs//proc/kcore.c

285
286 static ssize_t
287 read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
288 {
289 char *buf = file->private_data;
290 size_t phdrs_offset, notes_offset, data_offset;
291 size_t phdrs_len, notes_len;
292 struct kcore_list *m;
293 size_t tsz;
294 int nphdr;
295 unsigned long start;
296 size_t orig_buflen = buflen;
297 int ret = 0;
298
299 down_read(&kclist_lock);
300
301 get_kcore_size(&nphdr, &phdrs_len, &notes_len, &data_offset);
302 phdrs_offset = sizeof(struct elfhdr);
303 notes_offset = phdrs_offset + phdrs_len;
304
305 /* ELF file header. */
306 if (buflen && *fpos < sizeof(struct elfhdr)) {
307 struct elfhdr ehdr = {
308 .e_ident = {
309 [EI_MAG0] = ELFMAG0,
310 [EI_MAG1] = ELFMAG1,
311 [EI_MAG2] = ELFMAG2,
312 [EI_MAG3] = ELFMAG3,
313 [EI_CLASS] = ELF_CLASS,
314 [EI_DATA] = ELF_DATA,
315 [EI_VERSION] = EV_CURRENT,
316 [EI_OSABI] = ELF_OSABI,
317 },
318 .e_type = ET_CORE,
319 .e_machine = ELF_ARCH,
320 .e_version = EV_CURRENT,
321 .e_phoff = sizeof(struct elfhdr),
322 .e_flags = ELF_CORE_EFLAGS,
323 .e_ehsize = sizeof(struct elfhdr),
324 .e_phentsize = sizeof(struct elf_phdr),
325 .e_phnum = nphdr,
326 };
327
> 328 tsz = min_t(size_t, buflen, sizeof(struct elfhdr) - *fpos);
329 if (copy_to_user(buffer, (char *)&ehdr + *fpos, tsz)) {
330 ret = -EFAULT;
331 goto out;
332 }
333
334 buffer += tsz;
335 buflen -= tsz;
336 *fpos += tsz;
337 }
338
339 /* ELF program headers. */
340 if (buflen && *fpos < phdrs_offset + phdrs_len) {
341 struct elf_phdr *phdrs, *phdr;
342
343 phdrs = kzalloc(phdrs_len, GFP_KERNEL);
344 if (!phdrs) {
345 ret = -ENOMEM;
346 goto out;
347 }
348
349 phdrs[0].p_type = PT_NOTE;
350 phdrs[0].p_offset = notes_offset;
351 phdrs[0].p_filesz = notes_len;
352
353 phdr = &phdrs[1];
354 list_for_each_entry(m, &kclist_head, list) {
355 phdr->p_type = PT_LOAD;
356 phdr->p_flags = PF_R | PF_W | PF_X;
357 phdr->p_offset = kc_vaddr_to_offset(m->addr) + data_offset;
358 phdr->p_vaddr = (size_t)m->addr;
359 if (m->type == KCORE_RAM || m->type == KCORE_TEXT)
360 phdr->p_paddr = __pa(m->addr);
361 else
362 phdr->p_paddr = (elf_addr_t)-1;
363 phdr->p_filesz = phdr->p_memsz = m->size;
364 phdr->p_align = PAGE_SIZE;
365 phdr++;
366 }
367
368 tsz = min_t(size_t, buflen, phdrs_offset + phdrs_len - *fpos);
369 if (copy_to_user(buffer, (char *)phdrs + *fpos - phdrs_offset,
370 tsz)) {
371 kfree(phdrs);
372 ret = -EFAULT;
373 goto out;
374 }
375 kfree(phdrs);
376
377 buffer += tsz;
378 buflen -= tsz;
379 *fpos += tsz;
380 }
381
382 /* ELF note segment. */
383 if (buflen && *fpos < notes_offset + notes_len) {
> 384 struct elf_prstatus prstatus = {0};
385 struct elf_prpsinfo prpsinfo = {
386 .pr_sname = 'R',
387 .pr_fname = "vmlinux",
388 };
389 char *notes;
390 size_t i = 0;
391
392 strlcpy(prpsinfo.pr_psargs, saved_command_line,
393 sizeof(prpsinfo.pr_psargs));
394
395 notes = kzalloc(notes_len, GFP_KERNEL);
396 if (!notes) {
397 ret = -ENOMEM;
398 goto out;
399 }
400
401 append_kcore_note(notes, &i, CORE_STR, NT_PRSTATUS, &prstatus,
402 sizeof(prstatus));
403 append_kcore_note(notes, &i, CORE_STR, NT_PRPSINFO, &prpsinfo,
404 sizeof(prpsinfo));
405 append_kcore_note(notes, &i, CORE_STR, NT_TASKSTRUCT, current,
406 arch_task_struct_size);
407
408 tsz = min_t(size_t, buflen, notes_offset + notes_len - *fpos);
409 if (copy_to_user(buffer, notes + *fpos - notes_offset, tsz)) {
410 kfree(notes);
411 ret = -EFAULT;
412 goto out;
413 }
414 kfree(notes);
415
416 buffer += tsz;
417 buflen -= tsz;
418 *fpos += tsz;
419 }
420
421 /*
422 * Check to see if our file offset matches with any of
423 * the addresses in the elf_phdr on our list.
424 */
425 start = kc_offset_to_vaddr(*fpos - data_offset);
426 if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
427 tsz = buflen;
428
429 while (buflen) {
430 list_for_each_entry(m, &kclist_head, list) {
431 if (start >= m->addr && start < (m->addr+m->size))
432 break;
433 }
434
435 if (&m->list == &kclist_head) {
436 if (clear_user(buffer, tsz)) {
437 ret = -EFAULT;
438 goto out;
439 }
440 } else if (m->type == KCORE_VMALLOC) {
441 vread(buf, (char *)start, tsz);
442 /* we have to zero-fill user buffer even if no read */
443 if (copy_to_user(buffer, buf, tsz)) {
444 ret = -EFAULT;
445 goto out;
446 }
447 } else if (m->type == KCORE_USER) {
448 /* User page is handled prior to normal kernel page: */
449 if (copy_to_user(buffer, (char *)start, tsz)) {
450 ret = -EFAULT;
451 goto out;
452 }
453 } else {
454 if (kern_addr_valid(start)) {
455 /*
456 * Using bounce buffer to bypass the
457 * hardened user copy kernel text checks.
458 */
459 if (probe_kernel_read(buf, (void *) start, tsz)) {
460 if (clear_user(buffer, tsz)) {
461 ret = -EFAULT;
462 goto out;
463 }
464 } else {
465 if (copy_to_user(buffer, buf, tsz)) {
466 ret = -EFAULT;
467 goto out;
468 }
469 }
470 } else {
471 if (clear_user(buffer, tsz)) {
472 ret = -EFAULT;
473 goto out;
474 }
475 }
476 }
477 buflen -= tsz;
478 *fpos += tsz;
479 buffer += tsz;
480 start += tsz;
481 tsz = (buflen > PAGE_SIZE ? PAGE_SIZE : buflen);
482 }
483
484 out:
485 up_write(&kclist_lock);
486 if (ret)
487 return ret;
488 return orig_buflen - buflen;
489 }
490

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation