2023-01-31 07:13:33 +00:00
|
|
|
// Copyright 2023 Mikhail Klementev. All rights reserved.
|
2018-10-08 20:51:32 +00:00
|
|
|
// Use of this source code is governed by a AGPLv3 license
|
2018-10-06 19:25:03 +00:00
|
|
|
// (or later) that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-12-10 02:51:15 +00:00
|
|
|
"fmt"
|
2023-03-18 21:30:07 +00:00
|
|
|
"os"
|
2023-04-07 18:57:18 +00:00
|
|
|
"os/exec"
|
2024-02-20 12:08:45 +00:00
|
|
|
"runtime"
|
2023-04-06 12:50:44 +00:00
|
|
|
"runtime/debug"
|
2024-02-20 12:08:45 +00:00
|
|
|
"strings"
|
2018-10-06 19:25:03 +00:00
|
|
|
|
2023-04-06 17:32:42 +00:00
|
|
|
"github.com/natefinch/lumberjack"
|
2023-03-18 21:30:07 +00:00
|
|
|
"github.com/rs/zerolog"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
|
2023-01-31 07:13:33 +00:00
|
|
|
"github.com/alecthomas/kong"
|
2018-11-17 20:18:50 +00:00
|
|
|
|
2023-05-18 21:37:07 +00:00
|
|
|
_ "code.dumpstack.io/tools/out-of-tree/distro/centos"
|
|
|
|
_ "code.dumpstack.io/tools/out-of-tree/distro/debian"
|
2023-06-15 15:24:29 +00:00
|
|
|
_ "code.dumpstack.io/tools/out-of-tree/distro/opensuse"
|
2023-05-18 21:37:07 +00:00
|
|
|
_ "code.dumpstack.io/tools/out-of-tree/distro/oraclelinux"
|
|
|
|
_ "code.dumpstack.io/tools/out-of-tree/distro/ubuntu"
|
|
|
|
|
2023-05-13 10:46:43 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/cache"
|
2024-02-17 22:38:43 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/cmd"
|
2024-02-20 13:25:31 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/config/dotfiles"
|
2023-05-13 10:14:45 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/container"
|
2023-05-13 09:17:57 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/fs"
|
2018-10-06 19:25:03 +00:00
|
|
|
)
|
|
|
|
|
2023-01-31 07:13:33 +00:00
|
|
|
type CLI struct {
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.Globals
|
|
|
|
|
|
|
|
Pew cmd.PewCmd `cmd:"" help:"build, run, and test module/exploit"`
|
|
|
|
Kernel cmd.KernelCmd `cmd:"" help:"manipulate kernels"`
|
|
|
|
Debug cmd.DebugCmd `cmd:"" help:"debug environment"`
|
|
|
|
Log cmd.LogCmd `cmd:"" help:"query logs"`
|
|
|
|
Pack cmd.PackCmd `cmd:"" help:"exploit pack test"`
|
|
|
|
Gen cmd.GenCmd `cmd:"" help:"generate .out-of-tree.toml skeleton"`
|
|
|
|
Image cmd.ImageCmd `cmd:"" help:"manage images"`
|
|
|
|
Container cmd.ContainerCmd `cmd:"" help:"manage containers"`
|
|
|
|
Distro cmd.DistroCmd `cmd:"" help:"distro-related helpers"`
|
2018-12-01 20:18:43 +00:00
|
|
|
|
2024-02-20 13:25:31 +00:00
|
|
|
Daemon cmd.DaemonCmd `cmd:"" help:"run daemon"`
|
|
|
|
|
2023-01-31 07:13:33 +00:00
|
|
|
Version VersionFlag `name:"version" help:"print version information and quit"`
|
2023-03-18 21:53:53 +00:00
|
|
|
|
2023-04-06 18:00:46 +00:00
|
|
|
LogLevel LogLevelFlag `enum:"trace,debug,info,warn,error" default:"info"`
|
2023-04-07 18:57:18 +00:00
|
|
|
|
|
|
|
ContainerRuntime string `enum:"podman,docker" default:"podman"`
|
2023-03-18 21:53:53 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 12:08:45 +00:00
|
|
|
func last(s []string) string {
|
|
|
|
return s[len(s)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
func debugLevel(pc uintptr, file string, line int) string {
|
|
|
|
function := runtime.FuncForPC(pc).Name()
|
|
|
|
if strings.Contains(function, ".") {
|
|
|
|
function = last(strings.Split(function, "."))
|
|
|
|
}
|
|
|
|
return function
|
|
|
|
}
|
|
|
|
|
|
|
|
func traceLevel(pc uintptr, file string, line int) string {
|
|
|
|
function := runtime.FuncForPC(pc).Name()
|
|
|
|
if strings.Contains(function, "/") {
|
|
|
|
function = last(strings.Split(function, "/"))
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("%s:%s:%d", file, function, line)
|
|
|
|
}
|
|
|
|
|
2023-03-18 21:53:53 +00:00
|
|
|
type LogLevelFlag string
|
|
|
|
|
|
|
|
func (loglevel LogLevelFlag) AfterApply() error {
|
|
|
|
switch loglevel {
|
2024-02-20 12:08:45 +00:00
|
|
|
case "debug":
|
|
|
|
zerolog.CallerMarshalFunc = debugLevel
|
|
|
|
log.Logger = log.With().Caller().Logger()
|
|
|
|
|
|
|
|
case "trace":
|
|
|
|
zerolog.CallerMarshalFunc = traceLevel
|
2023-03-22 17:36:04 +00:00
|
|
|
log.Logger = log.With().Caller().Logger()
|
2023-03-18 21:53:53 +00:00
|
|
|
}
|
|
|
|
return nil
|
2018-12-01 20:18:43 +00:00
|
|
|
}
|
|
|
|
|
2023-01-31 07:13:33 +00:00
|
|
|
type VersionFlag string
|
2018-12-10 02:51:15 +00:00
|
|
|
|
2023-01-31 07:13:33 +00:00
|
|
|
func (v VersionFlag) Decode(ctx *kong.DecodeContext) error { return nil }
|
|
|
|
func (v VersionFlag) IsBool() bool { return true }
|
|
|
|
func (v VersionFlag) BeforeApply(app *kong.Kong, vars kong.Vars) error {
|
|
|
|
fmt.Println(vars["version"])
|
|
|
|
app.Exit(0)
|
|
|
|
return nil
|
2019-07-10 22:08:04 +00:00
|
|
|
}
|
|
|
|
|
2023-04-06 17:32:42 +00:00
|
|
|
func main() {
|
2023-01-31 07:13:33 +00:00
|
|
|
cli := CLI{}
|
|
|
|
ctx := kong.Parse(&cli,
|
|
|
|
kong.Name("out-of-tree"),
|
|
|
|
kong.Description("kernel {module, exploit} development tool"),
|
|
|
|
kong.UsageOnError(),
|
|
|
|
kong.ConfigureHelp(kong.HelpOptions{
|
|
|
|
Compact: true,
|
|
|
|
}),
|
|
|
|
kong.Vars{
|
2023-04-26 14:36:25 +00:00
|
|
|
"version": "2.1.2",
|
2023-01-31 07:13:33 +00:00
|
|
|
},
|
2018-10-27 08:14:10 +00:00
|
|
|
)
|
|
|
|
|
2023-04-06 17:32:42 +00:00
|
|
|
switch cli.LogLevel {
|
2023-04-06 18:00:46 +00:00
|
|
|
case "trace":
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.LogLevel = zerolog.TraceLevel
|
2023-04-06 17:32:42 +00:00
|
|
|
case "debug":
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.LogLevel = zerolog.DebugLevel
|
2023-04-06 17:32:42 +00:00
|
|
|
case "info":
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.LogLevel = zerolog.InfoLevel
|
2023-04-06 17:32:42 +00:00
|
|
|
case "warn":
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.LogLevel = zerolog.WarnLevel
|
2023-04-06 17:32:42 +00:00
|
|
|
case "error":
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.LogLevel = zerolog.ErrorLevel
|
2023-04-06 17:32:42 +00:00
|
|
|
}
|
|
|
|
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.ConsoleWriter = cmd.LevelWriter{Writer: zerolog.NewConsoleWriter(
|
2023-05-02 11:10:57 +00:00
|
|
|
func(w *zerolog.ConsoleWriter) {
|
|
|
|
w.Out = os.Stderr
|
2023-04-06 17:32:42 +00:00
|
|
|
},
|
2023-05-02 11:10:57 +00:00
|
|
|
),
|
2024-02-17 22:38:43 +00:00
|
|
|
Level: cmd.LogLevel,
|
2023-05-02 11:10:57 +00:00
|
|
|
}
|
|
|
|
|
2024-02-17 22:38:43 +00:00
|
|
|
cmd.FileWriter = cmd.LevelWriter{Writer: &lumberjack.Logger{
|
2024-02-20 13:25:31 +00:00
|
|
|
Filename: dotfiles.File("logs/out-of-tree.log"),
|
2023-05-02 11:10:57 +00:00
|
|
|
},
|
|
|
|
Level: zerolog.TraceLevel,
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Logger = log.Output(zerolog.MultiLevelWriter(
|
2024-02-17 22:38:43 +00:00
|
|
|
&cmd.ConsoleWriter,
|
|
|
|
&cmd.FileWriter,
|
2023-04-06 17:32:42 +00:00
|
|
|
))
|
|
|
|
|
2023-04-06 18:13:56 +00:00
|
|
|
log.Trace().Msg("start out-of-tree")
|
2023-04-06 17:32:42 +00:00
|
|
|
log.Debug().Msgf("%v", os.Args)
|
|
|
|
log.Debug().Msgf("%v", cli)
|
|
|
|
|
2023-04-06 12:50:44 +00:00
|
|
|
if buildInfo, ok := debug.ReadBuildInfo(); ok {
|
|
|
|
log.Debug().Msgf("%v", buildInfo.GoVersion)
|
|
|
|
log.Debug().Msgf("%v", buildInfo.Settings)
|
|
|
|
}
|
|
|
|
|
2024-02-20 13:25:31 +00:00
|
|
|
path := dotfiles.Dir()
|
2023-05-13 09:17:57 +00:00
|
|
|
yes, err := fs.CaseInsensitive(path)
|
2023-05-11 02:42:34 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal().Err(err).Msg(path)
|
|
|
|
}
|
|
|
|
if yes {
|
|
|
|
log.Warn().Msg("case-insensitive file system not supported")
|
|
|
|
}
|
|
|
|
|
2023-04-07 18:57:18 +00:00
|
|
|
_, err = exec.LookPath(cli.ContainerRuntime)
|
|
|
|
if err != nil {
|
|
|
|
if cli.ContainerRuntime == "podman" { // default value
|
|
|
|
log.Debug().Msgf("podman is not found in $PATH, " +
|
|
|
|
"fall back to docker")
|
|
|
|
cli.ContainerRuntime = "docker"
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = exec.LookPath(cli.ContainerRuntime)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal().Msgf("%v is not found in $PATH",
|
|
|
|
cli.ContainerRuntime)
|
|
|
|
}
|
|
|
|
}
|
2023-05-13 10:14:45 +00:00
|
|
|
container.Runtime = cli.ContainerRuntime
|
2023-04-07 18:57:18 +00:00
|
|
|
|
2023-05-13 12:08:55 +00:00
|
|
|
if cli.Globals.CacheURL.String() != "" {
|
|
|
|
cache.URL = cli.Globals.CacheURL.String()
|
|
|
|
}
|
|
|
|
log.Debug().Msgf("set cache url to %s", cache.URL)
|
2023-05-13 10:46:43 +00:00
|
|
|
|
2023-04-06 17:32:42 +00:00
|
|
|
err = ctx.Run(&cli.Globals)
|
2023-01-31 07:13:33 +00:00
|
|
|
ctx.FatalIfErrorf(err)
|
2018-10-06 19:25:03 +00:00
|
|
|
}
|