github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/subsystem/linux/parents.go (about) 1 // Copyright 2023 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package linux 5 6 import "github.com/google/syzkaller/pkg/subsystem" 7 8 // parentTransformations applies all subsystem list transformations that have been implemented. 9 func parentTransformations(matrix *CoincidenceMatrix, 10 list []*subsystem.Subsystem) ([]*subsystem.Subsystem, error) { 11 list = dropSmallSubsystems(matrix, list) 12 list = dropDuplicateSubsystems(matrix, list) 13 err := setParents(matrix, list) 14 if err != nil { 15 return nil, err 16 } 17 return list, nil 18 } 19 20 // setParents attempts to determine the parent-child relations among the extracted subsystems. 21 // We assume A is a child of B if: 22 // 1) B covers more paths than A. 23 // 2) Most of the paths that relate to A also relate to B. 24 func setParents(matrix *CoincidenceMatrix, list []*subsystem.Subsystem) error { 25 // Some subsystems might have already been dropeed. 26 inInput := map[*subsystem.Subsystem]bool{} 27 for _, item := range list { 28 inInput[item] = true 29 } 30 matrix.NonEmptyPairs(func(a, b *subsystem.Subsystem, count int) { 31 if !inInput[a] || !inInput[b] { 32 return 33 } 34 // Demand that >= 50% paths are related. 35 if 2*count/matrix.Count(a) >= 1 && matrix.Count(a) < matrix.Count(b) { 36 a.Parents = append(a.Parents, b) 37 a.ReachableParents() // make sure we haven't created a loop 38 } 39 }) 40 transitiveReduction(list) 41 return nil 42 } 43 44 // dropSmallSubsystems removes subsystems for which we have found only a few matches in the filesystem tree. 45 func dropSmallSubsystems(matrix *CoincidenceMatrix, list []*subsystem.Subsystem) []*subsystem.Subsystem { 46 const cutOffCount = 2 47 48 newList := []*subsystem.Subsystem{} 49 for _, item := range list { 50 if matrix.Count(item) > cutOffCount || len(item.Syscalls) > 0 { 51 newList = append(newList, item) 52 } 53 } 54 return newList 55 } 56 57 // dropDuplicateSubsystems makes sure there are no duplicate subsystems. 58 // First, if subsystems A and B 100% overlap, we prefer the one that's alphabetically first. 59 // Second, if subsystem A is fully enclosed in subsystem B and constitutes more than 75% of B, 60 // we drop A, since it brings little value. 61 func dropDuplicateSubsystems(matrix *CoincidenceMatrix, list []*subsystem.Subsystem) []*subsystem.Subsystem { 62 drop := map[*subsystem.Subsystem]struct{}{} 63 firstIsBetter := func(first, second *subsystem.Subsystem) bool { 64 firstEmail, secondEmail := "", "" 65 if len(first.Lists) > 0 { 66 firstEmail = first.Lists[0] 67 } 68 if len(second.Lists) > 0 { 69 secondEmail = second.Lists[0] 70 } 71 return firstEmail < secondEmail 72 } 73 matrix.NonEmptyPairs(func(a, b *subsystem.Subsystem, count int) { 74 // Only consider cases when A is fully enclosed in B, i.e. M[A][B] == M[A][A]. 75 if count != matrix.Count(a) { 76 return 77 } 78 // If A and B 100% coincide, eliminate A and keep B if A > B. 79 if count == matrix.Count(b) { 80 if firstIsBetter(a, b) { 81 return 82 } 83 drop[a] = struct{}{} 84 return 85 } 86 // If A constitutes > 75% of B, drop A. 87 if 4*matrix.Count(a)/matrix.Count(b) >= 3 { 88 drop[a] = struct{}{} 89 } 90 }) 91 newList := []*subsystem.Subsystem{} 92 for _, item := range list { 93 if _, exists := drop[item]; !exists { 94 newList = append(newList, item) 95 } 96 } 97 return newList 98 } 99 100 // The algorithm runs in O(E * (E + V)). 101 // We expect that E is quite low here, so it should be fine. 102 func transitiveReduction(list []*subsystem.Subsystem) { 103 for _, s := range list { 104 removeParents := map[*subsystem.Subsystem]bool{} 105 for _, p := range s.Parents { 106 for otherP := range p.ReachableParents() { 107 removeParents[otherP] = true 108 } 109 } 110 newParents := []*subsystem.Subsystem{} 111 for _, p := range s.Parents { 112 if !removeParents[p] { 113 newParents = append(newParents, p) 114 } 115 } 116 s.Parents = newParents 117 } 118 }