Class: SeccompTools::Explain::Analysis

Inherits:
Object
  • Object
show all
Defined in:
lib/seccomp-tools/explain/analysis.rb

Overview

What a walk of one filter amounts to: the reachable returns, each one's facts read once, and the split into the architectures the filter distinguishes.

Everything that reads a walk needs the same groundwork - Summary to render a per-architecture policy, Audit to assess each architecture's reachable syscalls - so it is derived here once rather than in each of them.

Instance Method Summary collapse

Constructor Details

#initialize(leaves) ⇒ Analysis

Returns a new instance of Analysis.

Parameters:



17
18
19
20
# File 'lib/seccomp-tools/explain/analysis.rb', line 17

def initialize(leaves)
  @leaves = leaves
  @facts = Hash.new { |h, leaf| h[leaf] = PathFacts.new(leaf.path) }
end

Instance Method Details

#arch_valuesArray<Integer>

The distinct architecture values (+AUDIT_ARCH_*+) the filter explicitly branches on.

Returns:

  • (Array<Integer>)


31
32
33
# File 'lib/seccomp-tools/explain/analysis.rb', line 31

def arch_values
  @arch_values ||= @leaves.filter_map { |l| facts(l).arch_eq }.uniq
end

#default_label(leaves) ⇒ String?

The catch-all action of leaves: the verdict of a leaf that matches no syscall, no range and no arguments (or the first leaf, if none is a pure catch-all), or nil when leaves is empty.

Parameters:

Returns:

  • (String?)


61
62
63
64
# File 'lib/seccomp-tools/explain/analysis.rb', line 61

def default_label(leaves)
  catch_all = leaves.find { |l| facts(l).catch_all? }
  (catch_all || leaves.first)&.then { |l| Verdict.label(l.ret) }
end

#facts(leaf) ⇒ PathFacts

The PathFacts of leaf, computed once and shared across all consumers.

Parameters:

Returns:



25
26
27
# File 'lib/seccomp-tools/explain/analysis.rb', line 25

def facts(leaf)
  @facts[leaf]
end

#other_leavesArray<Symbolic::Executor::Leaf>

Leaves reachable when arch is none of the explicitly-checked values.

Returns:



53
54
55
# File 'lib/seccomp-tools/explain/analysis.rb', line 53

def other_leaves
  @leaves.reject { |l| facts(l).arch_eq }
end

#sections(declared_arch) ⇒ Array<Array(Integer?, Symbol?, Object, Array<Symbolic::Executor::Leaf>)>

One entry per architecture section: its AUDIT_ARCH value (+nil+ when the filter never branches on arch), the architecture symbol whose syscall names apply (+nil+ when the checked value is not one seccomp-tools knows), a display title, and the leaves reachable on it.

Parameters:

  • declared_arch (Symbol)

    The architecture assumed when the filter itself does not branch on arch.

Returns:



41
42
43
44
45
46
47
48
49
# File 'lib/seccomp-tools/explain/analysis.rb', line 41

def sections(declared_arch)
  vals = arch_values
  return [[nil, declared_arch, declared_arch, @leaves]] if vals.empty?

  vals.map do |v|
    sym = Const::Audit.arch_symbol(v)
    [v, sym, sym || format('0x%x (unknown)', v), @leaves.select { |l| facts(l).arch_consistent?(v) }]
  end
end