Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
3e7c564a5a
|
|||
dc73413114
|
|||
104e70f861
|
|||
365c9d0e95
|
|||
5bad772125
|
|||
f3b0c07af2
|
|||
f3d67cc3c2
|
|||
12b5bd2a99
|
|||
b05c44ab9d
|
|||
19535fc75c
|
|||
5e6a9dec93
|
|||
0f89a868bd
|
|||
14b8010fee
|
|||
7fd8614e3c
|
|||
3d958c1e10
|
32
CHANGELOG.md
32
CHANGELOG.md
@ -4,6 +4,38 @@
|
||||
|
||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.1.1] 2019-08-31
|
||||
|
||||
### Fixed
|
||||
|
||||
- macOS support.
|
||||
|
||||
## [1.1.0] 2019-08-30
|
||||
|
||||
### Added
|
||||
|
||||
- Global configuration file (~/.out-of-tree/out-of-tree.toml) allow to
|
||||
set up default values for settings.
|
||||
|
||||
- rootfs generator for Ubuntu 14.04.
|
||||
|
||||
- Parameter for setting up docker registry server.
|
||||
|
||||
- Support for (distro-specific) custom docker commands that will be
|
||||
executed before the base template.
|
||||
|
||||
- Parameter for setting up a reliability threshold for exit code.
|
||||
|
||||
- Parameter for setting up global timeout, after which no new tasks
|
||||
will be started.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Spelling in output.
|
||||
|
||||
- Now kernel generation will not fail if there are no directory
|
||||
/lib/modules inside the container.
|
||||
|
||||
## [1.0.0] 2019-08-20
|
||||
|
||||
### Added
|
||||
|
@ -1,5 +1,5 @@
|
||||
[](https://app.codacy.com/app/jollheef/out-of-tree?utm_source=github.com&utm_medium=referral&utm_content=jollheef/out-of-tree&utm_campaign=Badge_Grade_Dashboard)
|
||||
[](https://travis-ci.org/jollheef/out-of-tree)
|
||||
[](https://travis-ci.org/jollheef/out-of-tree)
|
||||
[](https://goreportcard.com/report/code.dumpstack.io/tools/out-of-tree)
|
||||
[](https://out-of-tree.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=R8W2UQPZ5X5JE&source=url)
|
||||
@ -9,6 +9,8 @@
|
||||
|
||||
out-of-tree kernel {module, exploit} development tool
|
||||
|
||||
out-of-tree is for automating some routine actions for creating development environments for debugging kernel modules and exploits, generating reliability statistics for exploits, and also provides the ability to easily integrate into CI (Continuous Integration).
|
||||
|
||||

|
||||
|
||||
## Requirements
|
||||
|
77
config/out-of-tree.go
Normal file
77
config/out-of-tree.go
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2019 Mikhail Klementev. All rights reserved.
|
||||
// Use of this source code is governed by a AGPLv3 license
|
||||
// (or later) that can be found in the LICENSE file.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"os/user"
|
||||
|
||||
"github.com/naoina/toml"
|
||||
)
|
||||
|
||||
type DockerCommand struct {
|
||||
DistroType DistroType
|
||||
Command string
|
||||
}
|
||||
|
||||
type OutOfTree struct {
|
||||
Kernels string
|
||||
UserKernels string
|
||||
|
||||
Database string
|
||||
|
||||
Qemu struct {
|
||||
Timeout string
|
||||
}
|
||||
|
||||
Docker struct {
|
||||
Timeout string
|
||||
Registry string
|
||||
|
||||
// Commands that will be executed before
|
||||
// the base layer of Dockerfile
|
||||
Commands []DockerCommand
|
||||
}
|
||||
}
|
||||
|
||||
func ReadOutOfTreeConf(path string) (c OutOfTree, err error) {
|
||||
buf, err := readFileAll(path)
|
||||
if err == nil {
|
||||
err = toml.Unmarshal(buf, &c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// It's ok if there's no configuration
|
||||
// then we'll just set default values
|
||||
err = nil
|
||||
}
|
||||
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.Kernels == "" {
|
||||
c.Kernels = usr.HomeDir + "/.out-of-tree/kernels.toml"
|
||||
}
|
||||
|
||||
if c.UserKernels == "" {
|
||||
c.UserKernels = usr.HomeDir + "/.out-of-tree/kernels.user.toml"
|
||||
}
|
||||
|
||||
if c.Database == "" {
|
||||
c.Database = usr.HomeDir + "/.out-of-tree/db.sqlite"
|
||||
}
|
||||
|
||||
if c.Qemu.Timeout == "" {
|
||||
c.Qemu.Timeout = "1m"
|
||||
}
|
||||
|
||||
if c.Docker.Timeout == "" {
|
||||
c.Docker.Timeout = "1m"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
2
debug.go
2
debug.go
@ -161,7 +161,7 @@ func debugHandler(kcfg config.KernelConfig, workPath, kernRegex, gdb string,
|
||||
|
||||
q.Debug(gdb)
|
||||
coloredGdbAddress := aurora.BgGreen(aurora.Black(gdb))
|
||||
fmt.Printf("[*] gdb runned on %s\n", coloredGdbAddress)
|
||||
fmt.Printf("[*] gdb is listening on %s\n", coloredGdbAddress)
|
||||
|
||||
err = q.Start()
|
||||
if err != nil {
|
||||
|
@ -54,7 +54,7 @@ Overview
|
||||
|
||||
$ out-of-tree debug --kernel 'Ubuntu:4.15.0-58-generic'
|
||||
[*] KASLR SMEP SMAP
|
||||
[*] gdb runned on tcp::1234
|
||||
[*] gdb is listening on tcp::1234
|
||||
[*] build result copied to /tmp/exploit
|
||||
|
||||
ssh -o StrictHostKeyChecking=no -p 29308 root@127.133.45.236
|
||||
|
@ -2,7 +2,7 @@
|
||||
# - KERNEL: kernel headers path
|
||||
# - TARGET: name of exploit binary that MUST be produced by makefile.
|
||||
# - $(TARGET)_test: name of test binary that MUST be produced by makefile
|
||||
# and it's will be runned on a LPE stage. TARGET_TEST MUST accept two argument:
|
||||
# and it's will be executed on a LPE stage. TARGET_TEST MUST accept two argument:
|
||||
# - Path to exploit binary
|
||||
# - File that MUST be created with exploit. It uses for test that exploit works
|
||||
# correctly.
|
||||
|
109
kernel.go
109
kernel.go
@ -19,7 +19,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/naoina/toml"
|
||||
"github.com/zcalusic/sysinfo"
|
||||
|
||||
"code.dumpstack.io/tools/out-of-tree/config"
|
||||
)
|
||||
@ -109,7 +108,9 @@ func vsyscallAvailable() (available bool, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func generateBaseDockerImage(sk config.KernelMask) (err error) {
|
||||
func generateBaseDockerImage(registry string, commands []config.DockerCommand,
|
||||
sk config.KernelMask) (err error) {
|
||||
|
||||
imagePath, err := dockerImagePath(sk)
|
||||
if err != nil {
|
||||
return
|
||||
@ -128,7 +129,12 @@ func generateBaseDockerImage(sk config.KernelMask) (err error) {
|
||||
sk.DistroType.String(), sk.DistroRelease)
|
||||
os.MkdirAll(imagePath, os.ModePerm)
|
||||
|
||||
d += fmt.Sprintf("FROM %s:%s\n",
|
||||
d += "FROM "
|
||||
if registry != "" {
|
||||
d += registry + "/"
|
||||
}
|
||||
|
||||
d += fmt.Sprintf("%s:%s\n",
|
||||
strings.ToLower(sk.DistroType.String()),
|
||||
sk.DistroRelease,
|
||||
)
|
||||
@ -138,6 +144,21 @@ func generateBaseDockerImage(sk config.KernelMask) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, c := range commands {
|
||||
switch c.DistroType {
|
||||
case config.Ubuntu:
|
||||
d += "RUN " + c.Command + "\n"
|
||||
case config.CentOS:
|
||||
d += "RUN " + c.Command + "\n"
|
||||
case config.Debian:
|
||||
d += "RUN " + c.Command + "\n"
|
||||
default:
|
||||
err = fmt.Errorf("%s not yet supported",
|
||||
sk.DistroType.String())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch sk.DistroType {
|
||||
case config.Ubuntu:
|
||||
d += "ENV DEBIAN_FRONTEND=noninteractive\n"
|
||||
@ -147,7 +168,7 @@ func generateBaseDockerImage(sk config.KernelMask) (err error) {
|
||||
if sk.DistroRelease >= "14.04" {
|
||||
d += "RUN apt-get install -y libseccomp-dev\n"
|
||||
}
|
||||
d += "RUN mkdir /lib/modules\n"
|
||||
d += "RUN mkdir -p /lib/modules\n"
|
||||
case config.CentOS:
|
||||
if sk.DistroRelease < "7" && !vsyscall {
|
||||
log.Println("Old CentOS requires `vsyscall=emulate` " +
|
||||
@ -397,66 +418,6 @@ func listDockerImages() (diis []dockerImageInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func genHostKernels(download bool) (kcfg config.KernelConfig, err error) {
|
||||
si := sysinfo.SysInfo{}
|
||||
si.GetSysInfo()
|
||||
|
||||
distroType, err := config.NewDistroType(si.OS.Vendor)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := exec.Command("ls", "/lib/modules")
|
||||
rawOutput, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Println(string(rawOutput), err)
|
||||
return
|
||||
}
|
||||
|
||||
kernelsBase := "/boot/"
|
||||
files, err := ioutil.ReadDir(kernelsBase)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// only for compatibility, docker is not really used
|
||||
dii := dockerImageInfo{
|
||||
ContainerName: config.KernelMask{
|
||||
DistroType: distroType,
|
||||
DistroRelease: si.OS.Version,
|
||||
}.DockerName(),
|
||||
}
|
||||
|
||||
rootfs, err := genRootfsImage(dii, download)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, k := range strings.Fields(string(rawOutput)) {
|
||||
ki := config.KernelInfo{
|
||||
DistroType: distroType,
|
||||
DistroRelease: si.OS.Version,
|
||||
KernelRelease: k,
|
||||
|
||||
KernelSource: "/lib/modules/" + k + "/build",
|
||||
|
||||
KernelPath: kernelsBase + genKernelPath(files, k),
|
||||
InitrdPath: kernelsBase + genInitrdPath(files, k),
|
||||
RootFS: rootfs,
|
||||
}
|
||||
|
||||
vmlinux := "/usr/lib/debug/boot/vmlinux-" + k
|
||||
log.Println("vmlinux", vmlinux)
|
||||
if exists(vmlinux) {
|
||||
ki.VmlinuxPath = vmlinux
|
||||
}
|
||||
|
||||
kcfg.Kernels = append(kcfg.Kernels, ki)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func updateKernelsCfg(host, download bool) (err error) {
|
||||
newkcfg := config.KernelConfig{}
|
||||
|
||||
@ -573,7 +534,10 @@ func shuffle(a []string) []string {
|
||||
return a
|
||||
}
|
||||
|
||||
func generateKernels(km config.KernelMask, max int64, download bool) (err error) {
|
||||
func generateKernels(km config.KernelMask, registry string,
|
||||
commands []config.DockerCommand, max int64,
|
||||
download bool) (err error) {
|
||||
|
||||
log.Println("Generating for kernel mask", km)
|
||||
|
||||
_, err = genRootfsImage(dockerImageInfo{ContainerName: km.DockerName()},
|
||||
@ -582,7 +546,7 @@ func generateKernels(km config.KernelMask, max int64, download bool) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
err = generateBaseDockerImage(km)
|
||||
err = generateBaseDockerImage(registry, commands, km)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -632,7 +596,10 @@ func generateKernels(km config.KernelMask, max int64, download bool) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
func kernelAutogenHandler(workPath string, max int64, host, download bool) (err error) {
|
||||
func kernelAutogenHandler(workPath, registry string,
|
||||
commands []config.DockerCommand,
|
||||
max int64, host, download bool) (err error) {
|
||||
|
||||
ka, err := config.ReadArtifactConfig(workPath + "/.out-of-tree.toml")
|
||||
if err != nil {
|
||||
return
|
||||
@ -644,7 +611,7 @@ func kernelAutogenHandler(workPath string, max int64, host, download bool) (err
|
||||
return
|
||||
}
|
||||
|
||||
err = generateKernels(sk, max, download)
|
||||
err = generateKernels(sk, registry, commands, max, download)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -695,7 +662,9 @@ func kernelDockerRegenHandler(host, download bool) (err error) {
|
||||
return updateKernelsCfg(host, download)
|
||||
}
|
||||
|
||||
func kernelGenallHandler(distro, version string, host, download bool) (err error) {
|
||||
func kernelGenallHandler(distro, version, registry string,
|
||||
commands []config.DockerCommand, host, download bool) (err error) {
|
||||
|
||||
distroType, err := config.NewDistroType(distro)
|
||||
if err != nil {
|
||||
return
|
||||
@ -706,7 +675,7 @@ func kernelGenallHandler(distro, version string, host, download bool) (err error
|
||||
DistroRelease: version,
|
||||
ReleaseMask: ".*",
|
||||
}
|
||||
err = generateKernels(km, kernelsAll, download)
|
||||
err = generateKernels(km, registry, commands, kernelsAll, download)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
77
kernel_linux.go
Normal file
77
kernel_linux.go
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2018 Mikhail Klementev. All rights reserved.
|
||||
// Use of this source code is governed by a AGPLv3 license
|
||||
// (or later) that can be found in the LICENSE file.
|
||||
|
||||
// +build linux
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"code.dumpstack.io/tools/out-of-tree/config"
|
||||
"github.com/zcalusic/sysinfo"
|
||||
)
|
||||
|
||||
func genHostKernels(download bool) (kcfg config.KernelConfig, err error) {
|
||||
si := sysinfo.SysInfo{}
|
||||
si.GetSysInfo()
|
||||
|
||||
distroType, err := config.NewDistroType(si.OS.Vendor)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := exec.Command("ls", "/lib/modules")
|
||||
rawOutput, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Println(string(rawOutput), err)
|
||||
return
|
||||
}
|
||||
|
||||
kernelsBase := "/boot/"
|
||||
files, err := ioutil.ReadDir(kernelsBase)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// only for compatibility, docker is not really used
|
||||
dii := dockerImageInfo{
|
||||
ContainerName: config.KernelMask{
|
||||
DistroType: distroType,
|
||||
DistroRelease: si.OS.Version,
|
||||
}.DockerName(),
|
||||
}
|
||||
|
||||
rootfs, err := genRootfsImage(dii, download)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, k := range strings.Fields(string(rawOutput)) {
|
||||
ki := config.KernelInfo{
|
||||
DistroType: distroType,
|
||||
DistroRelease: si.OS.Version,
|
||||
KernelRelease: k,
|
||||
|
||||
KernelSource: "/lib/modules/" + k + "/build",
|
||||
|
||||
KernelPath: kernelsBase + genKernelPath(files, k),
|
||||
InitrdPath: kernelsBase + genInitrdPath(files, k),
|
||||
RootFS: rootfs,
|
||||
}
|
||||
|
||||
vmlinux := "/usr/lib/debug/boot/vmlinux-" + k
|
||||
log.Println("vmlinux", vmlinux)
|
||||
if exists(vmlinux) {
|
||||
ki.VmlinuxPath = vmlinux
|
||||
}
|
||||
|
||||
kcfg.Kernels = append(kcfg.Kernels, ki)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
18
kernel_macos.go
Normal file
18
kernel_macos.go
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2018 Mikhail Klementev. All rights reserved.
|
||||
// Use of this source code is governed by a AGPLv3 license
|
||||
// (or later) that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"code.dumpstack.io/tools/out-of-tree/config"
|
||||
)
|
||||
|
||||
func genHostKernels(download bool) (kcfg config.KernelConfig, err error) {
|
||||
err = errors.New("generate host kernels for macOS is not supported")
|
||||
return
|
||||
}
|
45
main.go
45
main.go
@ -84,7 +84,7 @@ func main() {
|
||||
)
|
||||
|
||||
app.Author("Mikhail Klementev <root@dumpstack.io>")
|
||||
app.Version("1.0.1")
|
||||
app.Version("1.1.0")
|
||||
|
||||
pathFlag := app.Flag("path", "Path to work directory")
|
||||
path := pathFlag.Default(".").ExistingDir()
|
||||
@ -95,25 +95,36 @@ func main() {
|
||||
}
|
||||
os.MkdirAll(usr.HomeDir+"/.out-of-tree", os.ModePerm)
|
||||
|
||||
defaultKcfgPath := usr.HomeDir + "/.out-of-tree/kernels.toml"
|
||||
confPath := usr.HomeDir + "/.out-of-tree/out-of-tree.toml"
|
||||
conf, err := config.ReadOutOfTreeConf(confPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
kcfgPathFlag := app.Flag("kernels", "Path to main kernels config")
|
||||
kcfgPath := kcfgPathFlag.Default(defaultKcfgPath).String()
|
||||
kcfgPath := kcfgPathFlag.Default(conf.Kernels).String()
|
||||
|
||||
defaultDbPath := usr.HomeDir + "/.out-of-tree/db.sqlite"
|
||||
dbPathFlag := app.Flag("db", "Path to database")
|
||||
dbPath := dbPathFlag.Default(defaultDbPath).String()
|
||||
dbPath := dbPathFlag.Default(conf.Database).String()
|
||||
|
||||
defaultUserKcfgPath := usr.HomeDir + "/.out-of-tree/kernels.user.toml"
|
||||
userKcfgPathFlag := app.Flag("user-kernels", "User kernels config")
|
||||
userKcfgPathEnv := userKcfgPathFlag.Envar("OUT_OF_TREE_KCFG")
|
||||
userKcfgPath := userKcfgPathEnv.Default(defaultUserKcfgPath).String()
|
||||
userKcfgPath := userKcfgPathEnv.Default(conf.UserKernels).String()
|
||||
|
||||
timeoutFlag := app.Flag("timeout", "Timeout after tool will not spawn new tests")
|
||||
timeout := timeoutFlag.Duration()
|
||||
|
||||
qemuTimeoutFlag := app.Flag("qemu-timeout", "Timeout for qemu")
|
||||
qemuTimeout := qemuTimeoutFlag.Default("1m").Duration()
|
||||
qemuTimeout := qemuTimeoutFlag.Default(conf.Qemu.Timeout).Duration()
|
||||
|
||||
dockerTimeoutFlag := app.Flag("docker-timeout", "Timeout for docker")
|
||||
dockerTimeout := dockerTimeoutFlag.Default("1m").Duration()
|
||||
dockerTimeout := dockerTimeoutFlag.Default(conf.Docker.Timeout).Duration()
|
||||
|
||||
dockerRegistryFlag := app.Flag("docker-registry", "Registry for docker")
|
||||
dockerRegistry := dockerRegistryFlag.Default(conf.Docker.Registry).String()
|
||||
|
||||
thresholdFlag := app.Flag("threshold", "Reliablity threshold for exit code")
|
||||
threshold := thresholdFlag.Default("1.00").Float64()
|
||||
|
||||
pewCommand := app.Command("pew", "Build, run and test module/exploit")
|
||||
|
||||
@ -279,20 +290,27 @@ func main() {
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
stop := time.Time{} // never stop
|
||||
if *timeout != 0 {
|
||||
stop = time.Now().Add(*timeout)
|
||||
}
|
||||
|
||||
switch kingpin.MustParse(app.Parse(os.Args[1:])) {
|
||||
case pewCommand.FullCommand():
|
||||
err = pewHandler(kcfg, *path, *pewKernel, *pewBinary,
|
||||
*pewTest, *pewGuess, *qemuTimeout, *dockerTimeout,
|
||||
*pewTest, *pewGuess, stop, *qemuTimeout, *dockerTimeout,
|
||||
*pewMax, *pewRuns, *pewDist, *pewTag, *pewThreads, db)
|
||||
case kernelListCommand.FullCommand():
|
||||
err = kernelListHandler(kcfg)
|
||||
case kernelAutogenCommand.FullCommand():
|
||||
err = kernelAutogenHandler(*path, *kernelAutogenMax,
|
||||
err = kernelAutogenHandler(*path, *dockerRegistry,
|
||||
conf.Docker.Commands, *kernelAutogenMax,
|
||||
*kernelUseHost, !*kernelNoDownload)
|
||||
case kernelDockerRegenCommand.FullCommand():
|
||||
err = kernelDockerRegenHandler(*kernelUseHost, !*kernelNoDownload)
|
||||
case kernelGenallCommand.FullCommand():
|
||||
err = kernelGenallHandler(*distro, *version,
|
||||
*dockerRegistry, conf.Docker.Commands,
|
||||
*kernelUseHost, !*kernelNoDownload)
|
||||
case genModuleCommand.FullCommand():
|
||||
err = genConfig(config.KernelModule)
|
||||
@ -316,7 +334,8 @@ func main() {
|
||||
case logMarkdownCommand.FullCommand():
|
||||
err = logMarkdownHandler(db, *path, *logMarkdownTag)
|
||||
case packCommand.FullCommand():
|
||||
err = packHandler(db, *path, kcfg, *packAutogen,
|
||||
err = packHandler(db, *path, *dockerRegistry, stop,
|
||||
conf.Docker.Commands, kcfg, *packAutogen,
|
||||
!*packNoDownload, *packExploitRuns, *packKernelRuns)
|
||||
}
|
||||
|
||||
@ -324,7 +343,7 @@ func main() {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
if somethingFailed {
|
||||
if successRate(state) < *threshold {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
8
pack.go
8
pack.go
@ -15,7 +15,8 @@ import (
|
||||
"code.dumpstack.io/tools/out-of-tree/config"
|
||||
)
|
||||
|
||||
func packHandler(db *sql.DB, path string, kcfg config.KernelConfig,
|
||||
func packHandler(db *sql.DB, path, registry string, stop time.Time,
|
||||
commands []config.DockerCommand, kcfg config.KernelConfig,
|
||||
autogen, download bool, exploitRuns, kernelRuns int64) (err error) {
|
||||
|
||||
dockerTimeout := time.Minute
|
||||
@ -39,7 +40,8 @@ func packHandler(db *sql.DB, path string, kcfg config.KernelConfig,
|
||||
|
||||
if autogen {
|
||||
var perRegex int64 = 1
|
||||
err = kernelAutogenHandler(workPath, perRegex, false, download)
|
||||
err = kernelAutogenHandler(workPath, registry,
|
||||
commands, perRegex, false, download)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -48,7 +50,7 @@ func packHandler(db *sql.DB, path string, kcfg config.KernelConfig,
|
||||
log.Println(f.Name())
|
||||
|
||||
pewHandler(kcfg, workPath, "", "", "", false,
|
||||
dockerTimeout, qemuTimeout,
|
||||
stop, dockerTimeout, qemuTimeout,
|
||||
kernelRuns, exploitRuns, pathDevNull, tag, threads, db)
|
||||
}
|
||||
|
||||
|
27
pew.go
27
pew.go
@ -26,7 +26,17 @@ import (
|
||||
"code.dumpstack.io/tools/out-of-tree/qemu"
|
||||
)
|
||||
|
||||
var somethingFailed = false
|
||||
type runstate struct {
|
||||
Overall, Success float64
|
||||
}
|
||||
|
||||
var (
|
||||
state runstate
|
||||
)
|
||||
|
||||
func successRate(state runstate) float64 {
|
||||
return state.Success / state.Overall
|
||||
}
|
||||
|
||||
const pathDevNull = "/dev/null"
|
||||
|
||||
@ -134,11 +144,12 @@ func testKernelExploit(q *qemu.System, ka config.Artifact,
|
||||
}
|
||||
|
||||
func genOkFail(name string, ok bool) (aurv aurora.Value) {
|
||||
state.Overall += 1
|
||||
if ok {
|
||||
state.Success += 1
|
||||
s := " " + name + " SUCCESS "
|
||||
aurv = aurora.BgGreen(aurora.Black(s))
|
||||
} else {
|
||||
somethingFailed = true
|
||||
s := " " + name + " FAILURE "
|
||||
aurv = aurora.BgRed(aurora.Gray(aurora.Bold(s)))
|
||||
}
|
||||
@ -380,7 +391,8 @@ func shuffleKernels(a []config.KernelInfo) []config.KernelInfo {
|
||||
}
|
||||
|
||||
func performCI(ka config.Artifact, kcfg config.KernelConfig, binaryPath,
|
||||
testPath string, qemuTimeout, dockerTimeout time.Duration,
|
||||
testPath string, stop time.Time,
|
||||
qemuTimeout, dockerTimeout time.Duration,
|
||||
max, runs int64, dist, tag string, threads int,
|
||||
db *sql.DB) (err error) {
|
||||
|
||||
@ -402,6 +414,9 @@ func performCI(ka config.Artifact, kcfg config.KernelConfig, binaryPath,
|
||||
found = true
|
||||
max--
|
||||
for i := int64(0); i < runs; i++ {
|
||||
if !stop.IsZero() && time.Now().After(stop) {
|
||||
break
|
||||
}
|
||||
swg.Add()
|
||||
go whatever(&swg, ka, kernel, binaryPath,
|
||||
testPath, qemuTimeout, dockerTimeout,
|
||||
@ -457,9 +472,10 @@ func genAllKernels() (sk []config.KernelMask, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Now too many parameters, move all of them to some structure
|
||||
func pewHandler(kcfg config.KernelConfig,
|
||||
workPath, ovrrdKrnl, binary, test string, guess bool,
|
||||
qemuTimeout, dockerTimeout time.Duration,
|
||||
stop time.Time, qemuTimeout, dockerTimeout time.Duration,
|
||||
max, runs int64, dist, tag string, threads int,
|
||||
db *sql.DB) (err error) {
|
||||
|
||||
@ -489,7 +505,8 @@ func pewHandler(kcfg config.KernelConfig,
|
||||
}
|
||||
}
|
||||
|
||||
err = performCI(ka, kcfg, binary, test, qemuTimeout, dockerTimeout,
|
||||
err = performCI(ka, kcfg, binary, test,
|
||||
stop, qemuTimeout, dockerTimeout,
|
||||
max, runs, dist, tag, threads, db)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -60,7 +60,7 @@ type Kernel struct {
|
||||
InitrdPath string
|
||||
}
|
||||
|
||||
// System describe qemu parameters and runned process
|
||||
// System describe qemu parameters and executed process
|
||||
type System struct {
|
||||
arch arch
|
||||
kernel Kernel
|
||||
@ -86,7 +86,7 @@ type System struct {
|
||||
Died bool
|
||||
sshAddrPort string
|
||||
|
||||
// accessible while qemu is runned
|
||||
// accessible while qemu is running
|
||||
cmd *exec.Cmd
|
||||
pipe struct {
|
||||
stdin io.WriteCloser
|
||||
|
@ -47,7 +47,7 @@ ENV IMAGE=/shared/out_of_tree_centos_7.img
|
||||
|
||||
RUN mkdir $IMAGEDIR
|
||||
|
||||
# Must be runned with --privileged because of /dev/loop
|
||||
# Must be executed with --privileged because of /dev/loop
|
||||
CMD qemu-img create $IMAGE 2G && \
|
||||
mkfs.ext4 -F $IMAGE && \
|
||||
mount -o loop $IMAGE $IMAGEDIR && \
|
||||
|
34
tools/qemu-debian-img/14.04/Dockerfile
Normal file
34
tools/qemu-debian-img/14.04/Dockerfile
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright 2018 Mikhail Klementev. All rights reserved.
|
||||
# Use of this source code is governed by a AGPLv3 license
|
||||
# (or later) that can be found in the LICENSE file.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ docker build -t gen-ubuntu1404-image .
|
||||
# $ docker run --privileged -v $(pwd):/shared -t gen-ubuntu1404-image
|
||||
#
|
||||
# ubuntu1404.img will be created in current directory. You can change $(pwd) to
|
||||
# different directory to use different destination for image.
|
||||
#
|
||||
FROM ubuntu:14.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y debootstrap qemu
|
||||
|
||||
ENV TMPDIR=/tmp/ubuntu
|
||||
ENV IMAGEDIR=/tmp/image
|
||||
ENV IMAGE=/shared/out_of_tree_ubuntu_14__04.img
|
||||
ENV REPOSITORY=http://archive.ubuntu.com/ubuntu
|
||||
ENV RELEASE=trusty
|
||||
|
||||
RUN mkdir $IMAGEDIR
|
||||
|
||||
# Must be executed with --privileged because of /dev/loop
|
||||
CMD debootstrap --include=openssh-server $RELEASE $TMPDIR $REPOSITORY && \
|
||||
/shared/setup.sh $TMPDIR && \
|
||||
qemu-img create $IMAGE 2G && \
|
||||
mkfs.ext4 -F $IMAGE && \
|
||||
mount -o loop $IMAGE $IMAGEDIR && \
|
||||
cp -a $TMPDIR/* $IMAGEDIR/ && \
|
||||
umount $IMAGEDIR
|
17
tools/qemu-debian-img/14.04/setup.sh
Executable file
17
tools/qemu-debian-img/14.04/setup.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh -eux
|
||||
# Copyright 2018 Mikhail Klementev. All rights reserved.
|
||||
# Use of this source code is governed by a AGPLv3 license
|
||||
# (or later) that can be found in the LICENSE file.
|
||||
TMPDIR=$1
|
||||
chroot $TMPDIR /bin/sh -c 'useradd -m user'
|
||||
sed -i 's/root:\*:/root::/' $TMPDIR/etc/shadow
|
||||
sed -i 's/user:!!:/user::/' $TMPDIR/etc/shadow
|
||||
echo auth sufficient pam_permit.so > $TMPDIR/etc/pam.d/sshd
|
||||
sed -i '/PermitEmptyPasswords/d' $TMPDIR/etc/ssh/sshd_config
|
||||
echo PermitEmptyPasswords yes >> $TMPDIR/etc/ssh/sshd_config
|
||||
sed -i '/PermitRootLogin/d' $TMPDIR/etc/ssh/sshd_config
|
||||
echo PermitRootLogin yes >> $TMPDIR/etc/ssh/sshd_config
|
||||
|
||||
echo '#!/bin/sh' > $TMPDIR/etc/rc.local
|
||||
echo 'dhclient eth0' >> $TMPDIR/etc/rc.local
|
||||
chmod +x $TMPDIR/etc/rc.local
|
@ -25,7 +25,7 @@ ENV RELEASE=bionic
|
||||
|
||||
RUN mkdir $IMAGEDIR
|
||||
|
||||
# Must be runned with --privileged because of /dev/loop
|
||||
# Must be executed with --privileged because of /dev/loop
|
||||
CMD debootstrap --include=openssh-server $RELEASE $TMPDIR $REPOSITORY && \
|
||||
/shared/setup.sh $TMPDIR && \
|
||||
qemu-img create $IMAGE 2G && \
|
||||
|
Reference in New Issue
Block a user