diff options
| -rw-r--r-- | pkg/manager/http.go | 12 | ||||
| -rw-r--r-- | prog/prio.go | 124 | ||||
| -rw-r--r-- | prog/prio_test.go | 2 | ||||
| -rw-r--r-- | tools/syz-showprio/showprio.go | 3 |
4 files changed, 92 insertions, 49 deletions
diff --git a/pkg/manager/http.go b/pkg/manager/http.go index 50f672207..eaf2459f5 100644 --- a/pkg/manager/http.go +++ b/pkg/manager/http.go @@ -667,14 +667,22 @@ func (serv *HTTPServer) httpPrio(w http.ResponseWriter, r *http.Request) { progs = append(progs, inp.Prog) } - prios := serv.Cfg.Target.CalculatePriorities(progs) + var enabled map[*prog.Syscall]bool + if obj := serv.EnabledSyscalls.Load(); obj != nil { + enabled = obj.(map[*prog.Syscall]bool) + } + prios, generatable := serv.Cfg.Target.CalculatePriorities(progs, enabled) data := &UIPrioData{ UIPageHeader: serv.pageHeader(r, "syscall priorities"), Call: callName, } for i, p := range prios[call.ID] { - data.Prios = append(data.Prios, UIPrio{serv.Cfg.Target.Syscalls[i].Name, p}) + syscall := serv.Cfg.Target.Syscalls[i] + if !generatable[syscall] { + continue + } + data.Prios = append(data.Prios, UIPrio{syscall.Name, p}) } sort.Slice(data.Prios, func(i, j int) bool { return data.Prios[i].Prio > data.Prios[j].Prio diff --git a/prog/prio.go b/prog/prio.go index a18008271..b64a8a9e2 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -26,11 +26,14 @@ import ( // Note: the current implementation is very basic, there is no theory behind any // constants. -func (target *Target) CalculatePriorities(corpus []*Prog) [][]int32 { - static := target.calcStaticPriorities() +// CalculatePriorities returns the priority matrix as well as the map of generatable syscalls. +// The rows/columns corresponding to the non-generatable syscalls are left to be 0. +func (target *Target) CalculatePriorities(corpus []*Prog, enabled map[*Syscall]bool) ([][]int32, map[*Syscall]bool) { + enabled = target.prepareEnabledSyscalls(corpus, enabled) + static := target.calcStaticPriorities(enabled) if len(corpus) != 0 { // Let's just sum the static and dynamic distributions. - dynamic := target.calcDynamicPrio(corpus) + dynamic := target.calcDynamicPrio(corpus, enabled) for i, prios := range dynamic { dst := static[i] for j, p := range prios { @@ -38,11 +41,58 @@ func (target *Target) CalculatePriorities(corpus []*Prog) [][]int32 { } } } - return static + if debug { + for _, syscall := range target.Syscalls { + if enabled[syscall] { + continue + } + for i := range static { + if static[i][syscall.ID] != 0 || static[syscall.ID][i] != 0 { + panic(fmt.Sprintf("prio matrix has non-zero value for a disabled syscall %d", + syscall.ID)) + } + } + } + } + return static, enabled +} + +func (target *Target) prepareEnabledSyscalls(corpus []*Prog, enabled map[*Syscall]bool) map[*Syscall]bool { + if enabled == nil { + enabled = make(map[*Syscall]bool) + for _, c := range target.Syscalls { + enabled[c] = true + } + } + noGenerateCalls := make(map[int]bool) + enabledCalls := make(map[*Syscall]bool) + for call := range enabled { + if call.Attrs.NoGenerate { + noGenerateCalls[call.ID] = true + } else if !call.Attrs.Disabled { + enabledCalls[call] = true + } + } + // Some validation checks. + if len(enabledCalls) == 0 { + panic("no syscalls enabled and generatable") + } + for _, p := range corpus { + for _, call := range p.Calls { + if !enabledCalls[call.Meta] && !noGenerateCalls[call.Meta.ID] { + fmt.Printf("corpus contains disabled syscall %v\n", call.Meta.Name) + for call := range enabled { + fmt.Printf("%s: enabled\n", call.Name) + } + panic("disabled syscall") + } + } + } + return enabledCalls } -func (target *Target) calcStaticPriorities() [][]int32 { - uses := target.calcResourceUsage() +func (target *Target) calcStaticPriorities(enabled map[*Syscall]bool) [][]int32 { + uses := target.calcResourceUsage(enabled) prios := make([][]int32, len(target.Syscalls)) for i := range prios { prios[i] = make([]int32, len(target.Syscalls)) @@ -61,22 +111,27 @@ func (target *Target) calcStaticPriorities() [][]int32 { } } // The value assigned for self-priority (call wrt itself) have to be high, but not too high. - for c0, pp := range prios { + for c := range enabled { + id, pp := c.ID, prios[c.ID] max := slices.Max(pp) if max == 0 { - pp[c0] = 1 + pp[id] = 1 } else { - pp[c0] = max * 3 / 4 + pp[id] = max * 3 / 4 } } - normalizePrios(prios) + normalizePrios(prios, len(enabled)) return prios } -func (target *Target) calcResourceUsage() map[string]map[int]weights { +func (target *Target) calcResourceUsage(enabled map[*Syscall]bool) map[string]map[int]weights { uses := make(map[string]map[int]weights) ForeachType(target.Syscalls, func(t Type, ctx *TypeCtx) { c := ctx.Meta + if !enabled[c] { + ctx.Stop = true + return + } switch a := t.(type) { case *ResourceType: if target.AuxResources[a.Desc.Name] { @@ -155,14 +210,20 @@ func noteUsagef(uses map[string]map[int]weights, c *Syscall, weight int32, dir D uses[id][c.ID] = callWeight } -func (target *Target) calcDynamicPrio(corpus []*Prog) [][]int32 { +func (target *Target) calcDynamicPrio(corpus []*Prog, enabled map[*Syscall]bool) [][]int32 { prios := make([][]int32, len(target.Syscalls)) for i := range prios { prios[i] = make([]int32, len(target.Syscalls)) } for _, p := range corpus { for idx0, c0 := range p.Calls { + if !enabled[c0.Meta] { + continue + } for _, c1 := range p.Calls[idx0+1:] { + if !enabled[c1.Meta] { + continue + } prios[c0.Meta.ID][c1.Meta.ID]++ } } @@ -175,13 +236,14 @@ func (target *Target) calcDynamicPrio(corpus []*Prog) [][]int32 { prios[i][j] = int32(2.0 * math.Sqrt(float64(val))) } } - normalizePrios(prios) + normalizePrios(prios, len(enabled)) return prios } // normalizePrio distributes |N| * 10 points proportional to the values in the matrix. -func normalizePrios(prios [][]int32) { - total := 10 * int32(len(prios)) +// |N| is the number of the generatable syscalls. +func normalizePrios(prios [][]int32, n int) { + total := 10 * int32(n) for _, prio := range prios { sum := int32(0) for _, p := range prio { @@ -205,43 +267,15 @@ type ChoiceTable struct { } func (target *Target) BuildChoiceTable(corpus []*Prog, enabled map[*Syscall]bool) *ChoiceTable { - if enabled == nil { - enabled = make(map[*Syscall]bool) - for _, c := range target.Syscalls { - enabled[c] = true - } - } - noGenerateCalls := make(map[int]bool) - enabledCalls := make(map[*Syscall]bool) - for call := range enabled { - if call.Attrs.NoGenerate { - noGenerateCalls[call.ID] = true - } else if !call.Attrs.Disabled { - enabledCalls[call] = true - } - } + prios, enabledCalls := target.CalculatePriorities(corpus, enabled) var generatableCalls []*Syscall for c := range enabledCalls { generatableCalls = append(generatableCalls, c) } - if len(generatableCalls) == 0 { - panic("no syscalls enabled and generatable") - } sort.Slice(generatableCalls, func(i, j int) bool { return generatableCalls[i].ID < generatableCalls[j].ID }) - for _, p := range corpus { - for _, call := range p.Calls { - if !enabledCalls[call.Meta] && !noGenerateCalls[call.Meta.ID] { - fmt.Printf("corpus contains disabled syscall %v\n", call.Meta.Name) - for call := range enabled { - fmt.Printf("%s: enabled\n", call.Name) - } - panic("disabled syscall") - } - } - } - prios := target.CalculatePriorities(corpus) + run := make([][]int32, len(target.Syscalls)) // ChoiceTable.runs[][] contains cumulated sum of weighted priority numbers. // This helps in quick binary search with biases when generating programs. diff --git a/prog/prio_test.go b/prog/prio_test.go index 93555818e..2e1208822 100644 --- a/prog/prio_test.go +++ b/prog/prio_test.go @@ -23,7 +23,7 @@ func TestNormalizePrios(t *testing.T) { {10, 20, 0}, } t.Logf("had: %+v", prios) - normalizePrios(prios) + normalizePrios(prios, len(prios)) if !reflect.DeepEqual(prios, want) { t.Logf("got: %+v", prios) t.Errorf("want: %+v", want) diff --git a/tools/syz-showprio/showprio.go b/tools/syz-showprio/showprio.go index f9ec2ff69..a4b15bca3 100644 --- a/tools/syz-showprio/showprio.go +++ b/tools/syz-showprio/showprio.go @@ -45,7 +45,8 @@ func main() { fmt.Fprintf(os.Stderr, "failed to read corpus: %v\n", err) os.Exit(1) } - showPriorities(enabled, target.CalculatePriorities(corpus), target) + matrix, _ := target.CalculatePriorities(corpus, nil) + showPriorities(enabled, matrix, target) } func showPriorities(calls []string, prios [][]int32, target *prog.Target) { |
