1414 * The following locks and mutexes are used by kmemleak:
1515 *
1616 * - kmemleak_lock (raw_spinlock_t): protects the object_list modifications and
17- * accesses to the object_tree_root. The object_list is the main list
18- * holding the metadata (struct kmemleak_object) for the allocated memory
19- * blocks. The object_tree_root is a red black tree used to look-up
20- * metadata based on a pointer to the corresponding memory block. The
21- * kmemleak_object structures are added to the object_list and
22- * object_tree_root in the create_object() function called from the
23- * kmemleak_alloc() callback and removed in delete_object() called from the
24- * kmemleak_free() callback
17+ * accesses to the object_tree_root (or object_phys_tree_root). The
18+ * object_list is the main list holding the metadata (struct kmemleak_object)
19+ * for the allocated memory blocks. The object_tree_root and object_phys_tree_root
20+ * are red black trees used to look-up metadata based on a pointer to the
21+ * corresponding memory block. The object_phys_tree_root is for objects
22+ * allocated with physical address. The kmemleak_object structures are
23+ * added to the object_list and object_tree_root (or object_phys_tree_root)
24+ * in the create_object() function called from the kmemleak_alloc() (or
25+ * kmemleak_alloc_phys()) callback and removed in delete_object() called from
26+ * the kmemleak_free() callback
2527 * - kmemleak_object.lock (raw_spinlock_t): protects a kmemleak_object.
2628 * Accesses to the metadata (e.g. count) are protected by this lock. Note
2729 * that some members of this structure may be protected by other means
@@ -195,7 +197,9 @@ static int mem_pool_free_count = ARRAY_SIZE(mem_pool);
195197static LIST_HEAD (mem_pool_free_list );
196198/* search tree for object boundaries */
197199static struct rb_root object_tree_root = RB_ROOT ;
198- /* protecting the access to object_list and object_tree_root */
200+ /* search tree for object (with OBJECT_PHYS flag) boundaries */
201+ static struct rb_root object_phys_tree_root = RB_ROOT ;
202+ /* protecting the access to object_list, object_tree_root (or object_phys_tree_root) */
199203static DEFINE_RAW_SPINLOCK (kmemleak_lock );
200204
201205/* allocation caches for kmemleak internal data */
@@ -287,6 +291,9 @@ static void hex_dump_object(struct seq_file *seq,
287291 const u8 * ptr = (const u8 * )object -> pointer ;
288292 size_t len ;
289293
294+ if (WARN_ON_ONCE (object -> flags & OBJECT_PHYS ))
295+ return ;
296+
290297 /* limit the number of lines to HEX_MAX_LINES */
291298 len = min_t (size_t , object -> size , HEX_MAX_LINES * HEX_ROW_SIZE );
292299
@@ -380,9 +387,11 @@ static void dump_object_info(struct kmemleak_object *object)
380387 * beginning of the memory block are allowed. The kmemleak_lock must be held
381388 * when calling this function.
382389 */
383- static struct kmemleak_object * lookup_object (unsigned long ptr , int alias )
390+ static struct kmemleak_object * __lookup_object (unsigned long ptr , int alias ,
391+ bool is_phys )
384392{
385- struct rb_node * rb = object_tree_root .rb_node ;
393+ struct rb_node * rb = is_phys ? object_phys_tree_root .rb_node :
394+ object_tree_root .rb_node ;
386395 unsigned long untagged_ptr = (unsigned long )kasan_reset_tag ((void * )ptr );
387396
388397 while (rb ) {
@@ -408,6 +417,12 @@ static struct kmemleak_object *lookup_object(unsigned long ptr, int alias)
408417 return NULL ;
409418}
410419
420+ /* Look-up a kmemleak object which allocated with virtual address. */
421+ static struct kmemleak_object * lookup_object (unsigned long ptr , int alias )
422+ {
423+ return __lookup_object (ptr , alias , false);
424+ }
425+
411426/*
412427 * Increment the object use_count. Return 1 if successful or 0 otherwise. Note
413428 * that once an object's use_count reached 0, the RCU freeing was already
@@ -517,14 +532,15 @@ static void put_object(struct kmemleak_object *object)
517532/*
518533 * Look up an object in the object search tree and increase its use_count.
519534 */
520- static struct kmemleak_object * find_and_get_object (unsigned long ptr , int alias )
535+ static struct kmemleak_object * __find_and_get_object (unsigned long ptr , int alias ,
536+ bool is_phys )
521537{
522538 unsigned long flags ;
523539 struct kmemleak_object * object ;
524540
525541 rcu_read_lock ();
526542 raw_spin_lock_irqsave (& kmemleak_lock , flags );
527- object = lookup_object (ptr , alias );
543+ object = __lookup_object (ptr , alias , is_phys );
528544 raw_spin_unlock_irqrestore (& kmemleak_lock , flags );
529545
530546 /* check whether the object is still available */
@@ -535,28 +551,39 @@ static struct kmemleak_object *find_and_get_object(unsigned long ptr, int alias)
535551 return object ;
536552}
537553
554+ /* Look up and get an object which allocated with virtual address. */
555+ static struct kmemleak_object * find_and_get_object (unsigned long ptr , int alias )
556+ {
557+ return __find_and_get_object (ptr , alias , false);
558+ }
559+
538560/*
539- * Remove an object from the object_tree_root and object_list. Must be called
540- * with the kmemleak_lock held _if_ kmemleak is still enabled.
561+ * Remove an object from the object_tree_root (or object_phys_tree_root)
562+ * and object_list. Must be called with the kmemleak_lock held _if_ kmemleak
563+ * is still enabled.
541564 */
542565static void __remove_object (struct kmemleak_object * object )
543566{
544- rb_erase (& object -> rb_node , & object_tree_root );
567+ rb_erase (& object -> rb_node , object -> flags & OBJECT_PHYS ?
568+ & object_phys_tree_root :
569+ & object_tree_root );
545570 list_del_rcu (& object -> object_list );
546571}
547572
548573/*
549574 * Look up an object in the object search tree and remove it from both
550- * object_tree_root and object_list. The returned object's use_count should be
551- * at least 1, as initially set by create_object().
575+ * object_tree_root (or object_phys_tree_root) and object_list. The
576+ * returned object's use_count should be at least 1, as initially set
577+ * by create_object().
552578 */
553- static struct kmemleak_object * find_and_remove_object (unsigned long ptr , int alias )
579+ static struct kmemleak_object * find_and_remove_object (unsigned long ptr , int alias ,
580+ bool is_phys )
554581{
555582 unsigned long flags ;
556583 struct kmemleak_object * object ;
557584
558585 raw_spin_lock_irqsave (& kmemleak_lock , flags );
559- object = lookup_object (ptr , alias );
586+ object = __lookup_object (ptr , alias , is_phys );
560587 if (object )
561588 __remove_object (object );
562589 raw_spin_unlock_irqrestore (& kmemleak_lock , flags );
@@ -574,7 +601,8 @@ static int __save_stack_trace(unsigned long *trace)
574601
575602/*
576603 * Create the metadata (struct kmemleak_object) corresponding to an allocated
577- * memory block and add it to the object_list and object_tree_root.
604+ * memory block and add it to the object_list and object_tree_root (or
605+ * object_phys_tree_root).
578606 */
579607static struct kmemleak_object * __create_object (unsigned long ptr , size_t size ,
580608 int min_count , gfp_t gfp ,
@@ -631,9 +659,16 @@ static struct kmemleak_object *__create_object(unsigned long ptr, size_t size,
631659 raw_spin_lock_irqsave (& kmemleak_lock , flags );
632660
633661 untagged_ptr = (unsigned long )kasan_reset_tag ((void * )ptr );
634- min_addr = min (min_addr , untagged_ptr );
635- max_addr = max (max_addr , untagged_ptr + size );
636- link = & object_tree_root .rb_node ;
662+ /*
663+ * Only update min_addr and max_addr with object
664+ * storing virtual address.
665+ */
666+ if (!is_phys ) {
667+ min_addr = min (min_addr , untagged_ptr );
668+ max_addr = max (max_addr , untagged_ptr + size );
669+ }
670+ link = is_phys ? & object_phys_tree_root .rb_node :
671+ & object_tree_root .rb_node ;
637672 rb_parent = NULL ;
638673 while (* link ) {
639674 rb_parent = * link ;
@@ -657,7 +692,8 @@ static struct kmemleak_object *__create_object(unsigned long ptr, size_t size,
657692 }
658693 }
659694 rb_link_node (& object -> rb_node , rb_parent , link );
660- rb_insert_color (& object -> rb_node , & object_tree_root );
695+ rb_insert_color (& object -> rb_node , is_phys ? & object_phys_tree_root :
696+ & object_tree_root );
661697
662698 list_add_tail_rcu (& object -> object_list , & object_list );
663699out :
@@ -707,7 +743,7 @@ static void delete_object_full(unsigned long ptr)
707743{
708744 struct kmemleak_object * object ;
709745
710- object = find_and_remove_object (ptr , 0 );
746+ object = find_and_remove_object (ptr , 0 , false );
711747 if (!object ) {
712748#ifdef DEBUG
713749 kmemleak_warn ("Freeing unknown object at 0x%08lx\n" ,
@@ -723,12 +759,12 @@ static void delete_object_full(unsigned long ptr)
723759 * delete it. If the memory block is partially freed, the function may create
724760 * additional metadata for the remaining parts of the block.
725761 */
726- static void delete_object_part (unsigned long ptr , size_t size )
762+ static void delete_object_part (unsigned long ptr , size_t size , bool is_phys )
727763{
728764 struct kmemleak_object * object ;
729765 unsigned long start , end ;
730766
731- object = find_and_remove_object (ptr , 1 );
767+ object = find_and_remove_object (ptr , 1 , is_phys );
732768 if (!object ) {
733769#ifdef DEBUG
734770 kmemleak_warn ("Partially freeing unknown object at 0x%08lx (size %zu)\n" ,
@@ -746,10 +782,10 @@ static void delete_object_part(unsigned long ptr, size_t size)
746782 end = object -> pointer + object -> size ;
747783 if (ptr > start )
748784 __create_object (start , ptr - start , object -> min_count ,
749- GFP_KERNEL , object -> flags & OBJECT_PHYS );
785+ GFP_KERNEL , is_phys );
750786 if (ptr + size < end )
751787 __create_object (ptr + size , end - ptr - size , object -> min_count ,
752- GFP_KERNEL , object -> flags & OBJECT_PHYS );
788+ GFP_KERNEL , is_phys );
753789
754790 __delete_object (object );
755791}
@@ -770,11 +806,11 @@ static void paint_it(struct kmemleak_object *object, int color)
770806 raw_spin_unlock_irqrestore (& object -> lock , flags );
771807}
772808
773- static void paint_ptr (unsigned long ptr , int color )
809+ static void paint_ptr (unsigned long ptr , int color , bool is_phys )
774810{
775811 struct kmemleak_object * object ;
776812
777- object = find_and_get_object (ptr , 0 );
813+ object = __find_and_get_object (ptr , 0 , is_phys );
778814 if (!object ) {
779815 kmemleak_warn ("Trying to color unknown object at 0x%08lx as %s\n" ,
780816 ptr ,
@@ -792,16 +828,16 @@ static void paint_ptr(unsigned long ptr, int color)
792828 */
793829static void make_gray_object (unsigned long ptr )
794830{
795- paint_ptr (ptr , KMEMLEAK_GREY );
831+ paint_ptr (ptr , KMEMLEAK_GREY , false );
796832}
797833
798834/*
799835 * Mark the object as black-colored so that it is ignored from scans and
800836 * reporting.
801837 */
802- static void make_black_object (unsigned long ptr )
838+ static void make_black_object (unsigned long ptr , bool is_phys )
803839{
804- paint_ptr (ptr , KMEMLEAK_BLACK );
840+ paint_ptr (ptr , KMEMLEAK_BLACK , is_phys );
805841}
806842
807843/*
@@ -1007,7 +1043,7 @@ void __ref kmemleak_free_part(const void *ptr, size_t size)
10071043 pr_debug ("%s(0x%p)\n" , __func__ , ptr );
10081044
10091045 if (kmemleak_enabled && ptr && !IS_ERR (ptr ))
1010- delete_object_part ((unsigned long )ptr , size );
1046+ delete_object_part ((unsigned long )ptr , size , false );
10111047}
10121048EXPORT_SYMBOL_GPL (kmemleak_free_part );
10131049
@@ -1095,7 +1131,7 @@ void __ref kmemleak_ignore(const void *ptr)
10951131 pr_debug ("%s(0x%p)\n" , __func__ , ptr );
10961132
10971133 if (kmemleak_enabled && ptr && !IS_ERR (ptr ))
1098- make_black_object ((unsigned long )ptr );
1134+ make_black_object ((unsigned long )ptr , false );
10991135}
11001136EXPORT_SYMBOL (kmemleak_ignore );
11011137
@@ -1153,7 +1189,7 @@ void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, gfp_t gfp)
11531189 * Create object with OBJECT_PHYS flag and
11541190 * assume min_count 0.
11551191 */
1156- create_object_phys ((unsigned long )__va ( phys ) , size , 0 , gfp );
1192+ create_object_phys ((unsigned long )phys , size , 0 , gfp );
11571193}
11581194EXPORT_SYMBOL (kmemleak_alloc_phys );
11591195
@@ -1166,8 +1202,10 @@ EXPORT_SYMBOL(kmemleak_alloc_phys);
11661202 */
11671203void __ref kmemleak_free_part_phys (phys_addr_t phys , size_t size )
11681204{
1205+ pr_debug ("%s(0x%pa)\n" , __func__ , & phys );
1206+
11691207 if (PHYS_PFN (phys ) >= min_low_pfn && PHYS_PFN (phys ) < max_low_pfn )
1170- kmemleak_free_part ( __va ( phys ) , size );
1208+ delete_object_part (( unsigned long ) phys , size , true );
11711209}
11721210EXPORT_SYMBOL (kmemleak_free_part_phys );
11731211
@@ -1178,8 +1216,10 @@ EXPORT_SYMBOL(kmemleak_free_part_phys);
11781216 */
11791217void __ref kmemleak_ignore_phys (phys_addr_t phys )
11801218{
1219+ pr_debug ("%s(0x%pa)\n" , __func__ , & phys );
1220+
11811221 if (PHYS_PFN (phys ) >= min_low_pfn && PHYS_PFN (phys ) < max_low_pfn )
1182- kmemleak_ignore ( __va ( phys ) );
1222+ make_black_object (( unsigned long ) phys , true );
11831223}
11841224EXPORT_SYMBOL (kmemleak_ignore_phys );
11851225
@@ -1190,6 +1230,9 @@ static bool update_checksum(struct kmemleak_object *object)
11901230{
11911231 u32 old_csum = object -> checksum ;
11921232
1233+ if (WARN_ON_ONCE (object -> flags & OBJECT_PHYS ))
1234+ return false;
1235+
11931236 kasan_disable_current ();
11941237 kcsan_disable_current ();
11951238 object -> checksum = crc32 (0 , kasan_reset_tag ((void * )object -> pointer ), object -> size );
@@ -1343,6 +1386,7 @@ static void scan_object(struct kmemleak_object *object)
13431386{
13441387 struct kmemleak_scan_area * area ;
13451388 unsigned long flags ;
1389+ void * obj_ptr ;
13461390
13471391 /*
13481392 * Once the object->lock is acquired, the corresponding memory block
@@ -1354,10 +1398,15 @@ static void scan_object(struct kmemleak_object *object)
13541398 if (!(object -> flags & OBJECT_ALLOCATED ))
13551399 /* already freed object */
13561400 goto out ;
1401+
1402+ obj_ptr = object -> flags & OBJECT_PHYS ?
1403+ __va ((phys_addr_t )object -> pointer ) :
1404+ (void * )object -> pointer ;
1405+
13571406 if (hlist_empty (& object -> area_list ) ||
13581407 object -> flags & OBJECT_FULL_SCAN ) {
1359- void * start = ( void * ) object -> pointer ;
1360- void * end = ( void * )( object -> pointer + object -> size ) ;
1408+ void * start = obj_ptr ;
1409+ void * end = obj_ptr + object -> size ;
13611410 void * next ;
13621411
13631412 do {
0 commit comments