@@ -465,32 +465,32 @@ static void lkdtm_ARRAY_BOUNDS(void)
465465 pr_expected_config (CONFIG_UBSAN_BOUNDS );
466466}
467467
468- struct lkdtm_annotated {
468+ struct lkdtm_cb_fam {
469469 unsigned long flags ;
470470 int count ;
471471 int array [] __counted_by (count );
472472};
473473
474- static volatile int fam_count = 4 ;
474+ static volatile int element_count = 4 ;
475475
476476static void lkdtm_FAM_BOUNDS (void )
477477{
478- struct lkdtm_annotated * inst ;
478+ struct lkdtm_cb_fam * inst ;
479479
480- inst = kzalloc (struct_size (inst , array , fam_count + 1 ), GFP_KERNEL );
480+ inst = kzalloc (struct_size (inst , array , element_count + 1 ), GFP_KERNEL );
481481 if (!inst ) {
482482 pr_err ("FAIL: could not allocate test struct!\n" );
483483 return ;
484484 }
485485
486- inst -> count = fam_count ;
486+ inst -> count = element_count ;
487487 pr_info ("Array access within bounds ...\n" );
488- inst -> array [1 ] = fam_count ;
488+ inst -> array [1 ] = element_count ;
489489 ignored = inst -> array [1 ];
490490
491491 pr_info ("Array access beyond bounds ...\n" );
492- inst -> array [fam_count ] = fam_count ;
493- ignored = inst -> array [fam_count ];
492+ inst -> array [element_count ] = element_count ;
493+ ignored = inst -> array [element_count ];
494494
495495 kfree (inst );
496496
@@ -505,6 +505,79 @@ static void lkdtm_FAM_BOUNDS(void)
505505 pr_expected_config (CONFIG_UBSAN_BOUNDS );
506506}
507507
508+ struct lkdtm_extra {
509+ short a , b ;
510+ u16 sixteen ;
511+ u32 bigger ;
512+ u64 biggest ;
513+ };
514+
515+ struct lkdtm_cb_ptr {
516+ int a , b , c ;
517+ int nr_extra ;
518+ char * buf __counted_by_ptr (len );
519+ size_t len ;
520+ struct lkdtm_extra * extra __counted_by_ptr (nr_extra );
521+ };
522+
523+ static noinline void check_ptr_len (struct lkdtm_cb_ptr * p , size_t len )
524+ {
525+ if (__member_size (p -> buf ) != len )
526+ pr_err ("FAIL: could not determine size of inst->buf: %zu\n" ,
527+ __member_size (p -> buf ));
528+ else
529+ pr_info ("good: inst->buf length is %zu\n" , len );
530+ }
531+
532+ static void lkdtm_PTR_BOUNDS (void )
533+ {
534+ struct lkdtm_cb_ptr * inst ;
535+
536+ inst = kzalloc (sizeof (* inst ), GFP_KERNEL );
537+ if (!inst ) {
538+ pr_err ("FAIL: could not allocate struct lkdtm_cb_ptr!\n" );
539+ return ;
540+ }
541+
542+ inst -> buf = kzalloc (element_count , GFP_KERNEL );
543+ if (!inst -> buf ) {
544+ pr_err ("FAIL: could not allocate inst->buf!\n" );
545+ return ;
546+ }
547+ inst -> len = element_count ;
548+
549+ /* Double element_count */
550+ inst -> extra = kcalloc (element_count * 2 , sizeof (* inst -> extra ), GFP_KERNEL );
551+ inst -> nr_extra = element_count * 2 ;
552+
553+ pr_info ("Pointer access within bounds ...\n" );
554+ check_ptr_len (inst , 4 );
555+ /* All 4 bytes */
556+ inst -> buf [0 ] = 'A' ;
557+ inst -> buf [1 ] = 'B' ;
558+ inst -> buf [2 ] = 'C' ;
559+ inst -> buf [3 ] = 'D' ;
560+ /* Halfway into the array */
561+ inst -> extra [element_count ].biggest = 0x1000 ;
562+
563+ pr_info ("Pointer access beyond bounds ...\n" );
564+ ignored = inst -> extra [inst -> nr_extra ].b ;
565+
566+ kfree (inst -> extra );
567+ kfree (inst -> buf );
568+ kfree (inst );
569+
570+ pr_err ("FAIL: survived access of invalid pointer member offset!\n" );
571+
572+ if (!IS_ENABLED (CONFIG_CC_HAS_COUNTED_BY_PTR ))
573+ pr_warn ("This is expected since this %s was built with a compiler that does not support __counted_by_ptr\n" ,
574+ lkdtm_kernel_info );
575+ else if (IS_ENABLED (CONFIG_UBSAN_BOUNDS ))
576+ pr_expected_config (CONFIG_UBSAN_TRAP );
577+ else
578+ pr_expected_config (CONFIG_UBSAN_BOUNDS );
579+ }
580+
508581static void lkdtm_CORRUPT_LIST_ADD (void )
509582{
510583 /*
@@ -769,6 +842,7 @@ static struct crashtype crashtypes[] = {
769842 CRASHTYPE (OVERFLOW_UNSIGNED ),
770843 CRASHTYPE (ARRAY_BOUNDS ),
771844 CRASHTYPE (FAM_BOUNDS ),
845+ CRASHTYPE (PTR_BOUNDS ),
772846 CRASHTYPE (CORRUPT_LIST_ADD ),
773847 CRASHTYPE (CORRUPT_LIST_DEL ),
774848 CRASHTYPE (STACK_GUARD_PAGE_LEADING ),
0 commit comments