1
0
Fork 0

Do not randomize kernels installation/test order by default

master
dump_stack() 2023-04-05 11:29:31 +00:00
parent f399390c2c
commit fc0c76f114
Signed by: dump_stack
GPG Key ID: BE44DA8C062D87DC
3 changed files with 58 additions and 51 deletions

View File

@ -29,6 +29,7 @@ type KernelCmd struct {
UseHost bool `help:"also use host kernels"` UseHost bool `help:"also use host kernels"`
Force bool `help:"force reinstall kernel"` Force bool `help:"force reinstall kernel"`
NoHeaders bool `help:"do not install kernel headers"` NoHeaders bool `help:"do not install kernel headers"`
Shuffle bool `help:"randomize kernels installation order"`
List KernelListCmd `cmd:"" help:"list kernels"` List KernelListCmd `cmd:"" help:"list kernels"`
Autogen KernelAutogenCmd `cmd:"" help:"generate kernels based on the current config"` Autogen KernelAutogenCmd `cmd:"" help:"generate kernels based on the current config"`
@ -79,6 +80,7 @@ func (cmd KernelAutogenCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
!kernelCmd.NoDownload, !kernelCmd.NoDownload,
kernelCmd.Force, kernelCmd.Force,
!kernelCmd.NoHeaders, !kernelCmd.NoHeaders,
kernelCmd.Shuffle,
) )
if err != nil { if err != nil {
return return
@ -111,6 +113,7 @@ func (cmd *KernelGenallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
!kernelCmd.NoDownload, !kernelCmd.NoDownload,
kernelCmd.Force, kernelCmd.Force,
!kernelCmd.NoHeaders, !kernelCmd.NoHeaders,
kernelCmd.Shuffle,
) )
if err != nil { if err != nil {
return return
@ -143,6 +146,7 @@ func (cmd *KernelInstallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
!kernelCmd.NoDownload, !kernelCmd.NoDownload,
kernelCmd.Force, kernelCmd.Force,
!kernelCmd.NoHeaders, !kernelCmd.NoHeaders,
kernelCmd.Shuffle,
) )
if err != nil { if err != nil {
return return
@ -670,7 +674,7 @@ func hasKernel(ki config.KernelInfo, kcfg config.KernelConfig) bool {
return false return false
} }
func shuffle(a []string) []string { func shuffleStrings(a []string) []string {
// FisherYates shuffle // FisherYates shuffle
for i := len(a) - 1; i > 0; i-- { for i := len(a) - 1; i > 0; i-- {
j := rand.Intn(i + 1) j := rand.Intn(i + 1)
@ -681,7 +685,7 @@ func shuffle(a []string) []string {
func generateKernels(km config.KernelMask, registry string, func generateKernels(km config.KernelMask, registry string,
commands []config.DockerCommand, max int64, commands []config.DockerCommand, max int64,
download, force, headers bool) (err error) { download, force, headers, shuffle bool) (err error) {
log.Info().Msgf("Generating for kernel mask %v", km) log.Info().Msgf("Generating for kernel mask %v", km)
@ -711,7 +715,10 @@ func generateKernels(km config.KernelMask, registry string,
return return
} }
for i, pkg := range shuffle(pkgs) { if shuffle {
pkgs = shuffleStrings(pkgs)
}
for i, pkg := range pkgs {
if max <= 0 { if max <= 0 {
log.Print("Max is reached") log.Print("Max is reached")
break break

View File

@ -63,7 +63,7 @@ func (cmd *PackCmd) Run(g *Globals) (err error) {
log.Print(f.Name()) log.Print(f.Name())
PewCmd{ pew := PewCmd{
Max: cmd.KernelRuns, Max: cmd.KernelRuns,
Runs: cmd.ExploitRuns, Runs: cmd.ExploitRuns,
Threads: cmd.Threads, Threads: cmd.Threads,
@ -72,7 +72,9 @@ func (cmd *PackCmd) Run(g *Globals) (err error) {
QemuTimeout: cmd.QemuTimeout, QemuTimeout: cmd.QemuTimeout,
DockerTimeout: cmd.DockerTimeout, DockerTimeout: cmd.DockerTimeout,
Dist: pathDevNull, Dist: pathDevNull,
}.Run(&Globals{ }
pew.Run(&Globals{
Config: g.Config, Config: g.Config,
WorkDir: workPath, WorkDir: workPath,
}) })

90
pew.go
View File

@ -32,6 +32,7 @@ type PewCmd struct {
Runs int64 `help:"runs per each kernel" default:"1"` Runs int64 `help:"runs per each kernel" default:"1"`
Kernel string `help:"override kernel regex"` Kernel string `help:"override kernel regex"`
Guess bool `help:"try all defined kernels"` Guess bool `help:"try all defined kernels"`
Shuffle bool `help:"randomize kernels test order"`
Binary string `help:"use binary, do not build"` Binary string `help:"use binary, do not build"`
Test string `help:"override path for test"` Test string `help:"override path for test"`
Dist string `help:"build result path" default:"/dev/null"` Dist string `help:"build result path" default:"/dev/null"`
@ -45,26 +46,29 @@ type PewCmd struct {
DockerTimeout time.Duration `help:"timeout for docker"` DockerTimeout time.Duration `help:"timeout for docker"`
Threshold float64 `help:"reliablity threshold for exit code" default:"1.00"` Threshold float64 `help:"reliablity threshold for exit code" default:"1.00"`
db *sql.DB
kcfg config.KernelConfig
timeoutDeadline time.Time
} }
func (cmd PewCmd) Run(g *Globals) (err error) { func (cmd *PewCmd) Run(g *Globals) (err error) {
kcfg, err := config.ReadKernelConfig(g.Config.Kernels) cmd.kcfg, err = config.ReadKernelConfig(g.Config.Kernels)
if err != nil { if err != nil {
log.Debug().Err(err).Msg("read kernels config") log.Fatal().Err(err).Msg("read kernels config")
} }
stop := time.Time{} // never stop
if cmd.Timeout != 0 { if cmd.Timeout != 0 {
log.Info().Msgf("Set global timeout to %s", cmd.Timeout) log.Info().Msgf("Set global timeout to %s", cmd.Timeout)
stop = time.Now().Add(cmd.Timeout) cmd.timeoutDeadline = time.Now().Add(cmd.Timeout)
} }
db, err := openDatabase(g.Config.Database) cmd.db, err = openDatabase(g.Config.Database)
if err != nil { if err != nil {
log.Fatal().Err(err). log.Fatal().Err(err).
Msgf("Cannot open database %s", g.Config.Database) Msgf("Cannot open database %s", g.Config.Database)
} }
defer db.Close() defer cmd.db.Close()
var configPath string var configPath string
if cmd.ArtifactConfig == "" { if cmd.ArtifactConfig == "" {
@ -98,16 +102,16 @@ func (cmd PewCmd) Run(g *Globals) (err error) {
} }
} }
qemuTimeout := g.Config.Qemu.Timeout.Duration
if cmd.QemuTimeout != 0 { if cmd.QemuTimeout != 0 {
log.Info().Msgf("Set qemu timeout to %s", cmd.QemuTimeout) log.Info().Msgf("Set qemu timeout to %s", cmd.QemuTimeout)
qemuTimeout = cmd.QemuTimeout } else {
cmd.QemuTimeout = g.Config.Qemu.Timeout.Duration
} }
dockerTimeout := g.Config.Docker.Timeout.Duration
if cmd.DockerTimeout != 0 { if cmd.DockerTimeout != 0 {
log.Info().Msgf("Set docker timeout to %s", cmd.DockerTimeout) log.Info().Msgf("Set docker timeout to %s", cmd.DockerTimeout)
dockerTimeout = cmd.DockerTimeout } else {
cmd.DockerTimeout = g.Config.Docker.Timeout.Duration
} }
if cmd.Tag == "" { if cmd.Tag == "" {
@ -115,10 +119,7 @@ func (cmd PewCmd) Run(g *Globals) (err error) {
} }
log.Info().Str("tag", cmd.Tag).Msg("log") log.Info().Str("tag", cmd.Tag).Msg("log")
err = performCI(ka, kcfg, cmd.Binary, cmd.Test, stop, err = cmd.performCI(ka)
qemuTimeout, dockerTimeout,
cmd.Max, cmd.Runs, cmd.Dist, cmd.Tag,
cmd.Threads, db)
if err != nil { if err != nil {
return return
} }
@ -518,10 +519,8 @@ func copyStandardModules(q *qemu.System, ki config.KernelInfo) (err error) {
return return
} }
func testArtifact(swg *sizedwaitgroup.SizedWaitGroup, ka config.Artifact, func (cmd PewCmd) testArtifact(swg *sizedwaitgroup.SizedWaitGroup,
ki config.KernelInfo, binaryPath, testPath string, ka config.Artifact, ki config.KernelInfo) {
qemuTimeout, dockerTimeout time.Duration, dist, tag string,
db *sql.DB) {
defer swg.Done() defer swg.Done()
@ -539,7 +538,7 @@ func testArtifact(swg *sizedwaitgroup.SizedWaitGroup, ka config.Artifact,
slog.Error().Err(err).Msg("qemu init") slog.Error().Err(err).Msg("qemu init")
return return
} }
q.Timeout = qemuTimeout q.Timeout = cmd.QemuTimeout
if ka.Qemu.Timeout.Duration != 0 { if ka.Qemu.Timeout.Duration != 0 {
q.Timeout = ka.Qemu.Timeout.Duration q.Timeout = ka.Qemu.Timeout.Duration
@ -552,7 +551,7 @@ func testArtifact(swg *sizedwaitgroup.SizedWaitGroup, ka config.Artifact,
} }
if ka.Docker.Timeout.Duration != 0 { if ka.Docker.Timeout.Duration != 0 {
dockerTimeout = ka.Docker.Timeout.Duration cmd.DockerTimeout = ka.Docker.Timeout.Duration
} }
q.SetKASLR(!ka.Mitigations.DisableKaslr) q.SetKASLR(!ka.Mitigations.DisableKaslr)
@ -589,16 +588,16 @@ func testArtifact(swg *sizedwaitgroup.SizedWaitGroup, ka config.Artifact,
defer os.RemoveAll(tmp) defer os.RemoveAll(tmp)
result := phasesResult{} result := phasesResult{}
defer dumpResult(q, ka, ki, &result, dist, tag, binaryPath, db) defer dumpResult(q, ka, ki, &result, cmd.Dist, cmd.Tag, cmd.Binary, cmd.db)
if ka.Type == config.Script { if ka.Type == config.Script {
result.Build.Ok = true result.Build.Ok = true
testPath = ka.Script cmd.Test = ka.Script
} else if binaryPath == "" { } else if cmd.Binary == "" {
// TODO: build should return structure // TODO: build should return structure
start := time.Now() start := time.Now()
result.BuildDir, result.BuildArtifact, result.Build.Output, err = result.BuildDir, result.BuildArtifact, result.Build.Output, err =
build(tmp, ka, ki, dockerTimeout) build(tmp, ka, ki, cmd.DockerTimeout)
slog.Debug().Str("duration", time.Now().Sub(start).String()). slog.Debug().Str("duration", time.Now().Sub(start).String()).
Msg("build done") Msg("build done")
if err != nil { if err != nil {
@ -607,23 +606,23 @@ func testArtifact(swg *sizedwaitgroup.SizedWaitGroup, ka config.Artifact,
} }
result.Build.Ok = true result.Build.Ok = true
} else { } else {
result.BuildArtifact = binaryPath result.BuildArtifact = cmd.Binary
result.Build.Ok = true result.Build.Ok = true
} }
if testPath == "" { if cmd.Test == "" {
testPath = result.BuildArtifact + "_test" cmd.Test = result.BuildArtifact + "_test"
if !exists(testPath) { if !exists(cmd.Test) {
testPath = tmp + "/source/" + "test.sh" cmd.Test = tmp + "/source/" + "test.sh"
} }
} }
err = q.WaitForSSH(qemuTimeout) err = q.WaitForSSH(cmd.QemuTimeout)
if err != nil { if err != nil {
return return
} }
remoteTest, err := copyTest(q, testPath, ka) remoteTest, err := copyTest(q, cmd.Test, ka)
if err != nil { if err != nil {
return return
} }
@ -640,7 +639,7 @@ func testArtifact(swg *sizedwaitgroup.SizedWaitGroup, ka config.Artifact,
Msg("copy standard modules") Msg("copy standard modules")
} }
err = preloadModules(q, ka, ki, dockerTimeout) err = preloadModules(q, ka, ki, cmd.DockerTimeout)
if err != nil { if err != nil {
slog.Error().Err(err).Msg("preload modules") slog.Error().Err(err).Msg("preload modules")
return return
@ -661,16 +660,15 @@ func shuffleKernels(a []config.KernelInfo) []config.KernelInfo {
return a return a
} }
func performCI(ka config.Artifact, kcfg config.KernelConfig, binaryPath, func (cmd PewCmd) performCI(ka config.Artifact) (err error) {
testPath string, stop time.Time,
qemuTimeout, dockerTimeout time.Duration,
max, runs int64, dist, tag string, threads int,
db *sql.DB) (err error) {
found := false found := false
max := cmd.Max
swg := sizedwaitgroup.New(threads) swg := sizedwaitgroup.New(cmd.Threads)
for _, kernel := range shuffleKernels(kcfg.Kernels) { if cmd.Shuffle {
cmd.kcfg.Kernels = shuffleKernels(cmd.kcfg.Kernels)
}
for _, kernel := range cmd.kcfg.Kernels {
if max <= 0 { if max <= 0 {
break break
} }
@ -684,14 +682,14 @@ func performCI(ka config.Artifact, kcfg config.KernelConfig, binaryPath,
if supported { if supported {
found = true found = true
max-- max--
for i := int64(0); i < runs; i++ { for i := int64(0); i < cmd.Runs; i++ {
if !stop.IsZero() && time.Now().After(stop) { if !cmd.timeoutDeadline.IsZero() &&
time.Now().After(cmd.timeoutDeadline) {
break break
} }
swg.Add() swg.Add()
go testArtifact(&swg, ka, kernel, binaryPath, go cmd.testArtifact(&swg, ka, kernel)
testPath, qemuTimeout, dockerTimeout,
dist, tag, db)
} }
} }
} }