tree: https://github.com/hnaz/linux-mm master head: f70102acac27ec90e4eeeb7e1a31cff28355dbcc commit: 4e63445547fd4f2de6acf4b85189d6b4d3ea4eb7 [677/696] bpf:bpf_seq_printf(): handle potentially unsafe format string better config: i386-randconfig-s002-20200529 (attached as .config) compiler: gcc-9 (Debian 9.3.0-13) 9.3.0 reproduce: # apt-get install sparse # sparse version: v0.6.1-243-gc100a7ab-dirty git checkout 4e63445547fd4f2de6acf4b85189d6b4d3ea4eb7 # save the attached .config to linux build tree make W=1 C=1 ARCH=i386 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' If you fix the issue, kindly add following tag as appropriate Reported-by: kbuild test robot <lkp@xxxxxxxxx> sparse warnings: (new ones prefixed by >>) >> kernel/trace/bpf_trace.c:602:64: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void const [noderef] <asn:1> *unsafe_addr @@ got void *[assigned] unsafe_ptr @@ >> kernel/trace/bpf_trace.c:602:64: sparse: expected void const [noderef] <asn:1> *unsafe_addr >> kernel/trace/bpf_trace.c:602:64: sparse: got void *[assigned] unsafe_ptr vim +602 kernel/trace/bpf_trace.c 511 512 BPF_CALL_5(bpf_seq_printf, struct seq_file *, m, char *, fmt, u32, fmt_size, 513 const void *, data, u32, data_len) 514 { 515 int err = -EINVAL, fmt_cnt = 0, memcpy_cnt = 0; 516 int i, buf_used, copy_size, num_args; 517 u64 params[MAX_SEQ_PRINTF_VARARGS]; 518 struct bpf_seq_printf_buf *bufs; 519 const u64 *args = data; 520 521 buf_used = this_cpu_inc_return(bpf_seq_printf_buf_used); 522 if (WARN_ON_ONCE(buf_used > 1)) { 523 err = -EBUSY; 524 goto out; 525 } 526 527 bufs = this_cpu_ptr(&bpf_seq_printf_buf); 528 529 /* 530 * bpf_check()->check_func_arg()->check_stack_boundary() 531 * guarantees that fmt points to bpf program stack, 532 * fmt_size bytes of it were initialized and fmt_size > 0 533 */ 534 if (fmt[--fmt_size] != 0) 535 goto out; 536 537 if (data_len & 7) 538 goto out; 539 540 for (i = 0; i < fmt_size; i++) { 541 if (fmt[i] == '%') { 542 if (fmt[i + 1] == '%') 543 i++; 544 else if (!data || !data_len) 545 goto out; 546 } 547 } 548 549 num_args = data_len / 8; 550 551 /* check format string for allowed specifiers */ 552 for (i = 0; i < fmt_size; i++) { 553 /* only printable ascii for now. */ 554 if ((!isprint(fmt[i]) && !isspace(fmt[i])) || !isascii(fmt[i])) { 555 err = -EINVAL; 556 goto out; 557 } 558 559 if (fmt[i] != '%') 560 continue; 561 562 if (fmt[i + 1] == '%') { 563 i++; 564 continue; 565 } 566 567 if (fmt_cnt >= MAX_SEQ_PRINTF_VARARGS) { 568 err = -E2BIG; 569 goto out; 570 } 571 572 if (fmt_cnt >= num_args) { 573 err = -EINVAL; 574 goto out; 575 } 576 577 /* fmt[i] != 0 && fmt[last] == 0, so we can access fmt[i + 1] */ 578 i++; 579 580 /* skip optional "[0 +-][num]" width formating field */ 581 while (fmt[i] == '0' || fmt[i] == '+' || fmt[i] == '-' || 582 fmt[i] == ' ') 583 i++; 584 if (fmt[i] >= '1' && fmt[i] <= '9') { 585 i++; 586 while (fmt[i] >= '0' && fmt[i] <= '9') 587 i++; 588 } 589 590 if (fmt[i] == 's') { 591 void *unsafe_ptr; 592 593 /* try our best to copy */ 594 if (memcpy_cnt >= MAX_SEQ_PRINTF_MAX_MEMCPY) { 595 err = -E2BIG; 596 goto out; 597 } 598 599 unsafe_ptr = (void *)(long)args[fmt_cnt]; 600 if ((unsigned long)unsafe_ptr < TASK_SIZE) { 601 err = strncpy_from_user_nofault( > 602 bufs->buf[memcpy_cnt], unsafe_ptr, 603 MAX_SEQ_PRINTF_STR_LEN); 604 } else { 605 err = -EFAULT; 606 } 607 if (err < 0) 608 bufs->buf[memcpy_cnt][0] = '\0'; 609 params[fmt_cnt] = (u64)(long)bufs->buf[memcpy_cnt]; 610 611 fmt_cnt++; 612 memcpy_cnt++; 613 continue; 614 } 615 616 if (fmt[i] == 'p') { 617 if (fmt[i + 1] == 0 || 618 fmt[i + 1] == 'K' || 619 fmt[i + 1] == 'x') { 620 /* just kernel pointers */ 621 params[fmt_cnt] = args[fmt_cnt]; 622 fmt_cnt++; 623 continue; 624 } 625 626 /* only support "%pI4", "%pi4", "%pI6" and "%pi6". */ 627 if (fmt[i + 1] != 'i' && fmt[i + 1] != 'I') { 628 err = -EINVAL; 629 goto out; 630 } 631 if (fmt[i + 2] != '4' && fmt[i + 2] != '6') { 632 err = -EINVAL; 633 goto out; 634 } 635 636 if (memcpy_cnt >= MAX_SEQ_PRINTF_MAX_MEMCPY) { 637 err = -E2BIG; 638 goto out; 639 } 640 641 642 copy_size = (fmt[i + 2] == '4') ? 4 : 16; 643 644 err = probe_kernel_read(bufs->buf[memcpy_cnt], 645 (void *) (long) args[fmt_cnt], 646 copy_size); 647 if (err < 0) 648 memset(bufs->buf[memcpy_cnt], 0, copy_size); 649 params[fmt_cnt] = (u64)(long)bufs->buf[memcpy_cnt]; 650 651 i += 2; 652 fmt_cnt++; 653 memcpy_cnt++; 654 continue; 655 } 656 657 if (fmt[i] == 'l') { 658 i++; 659 if (fmt[i] == 'l') 660 i++; 661 } 662 663 if (fmt[i] != 'i' && fmt[i] != 'd' && 664 fmt[i] != 'u' && fmt[i] != 'x') { 665 err = -EINVAL; 666 goto out; 667 } 668 669 params[fmt_cnt] = args[fmt_cnt]; 670 fmt_cnt++; 671 } 672 673 /* Maximumly we can have MAX_SEQ_PRINTF_VARARGS parameter, just give 674 * all of them to seq_printf(). 675 */ 676 seq_printf(m, fmt, params[0], params[1], params[2], params[3], 677 params[4], params[5], params[6], params[7], params[8], 678 params[9], params[10], params[11]); 679 680 err = seq_has_overflowed(m) ? -EOVERFLOW : 0; 681 out: 682 this_cpu_dec(bpf_seq_printf_buf_used); 683 return err; 684 } 685 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@xxxxxxxxxxxx
Attachment:
.config.gz
Description: application/gzip