diff --git a/main.go b/main.go index 83ba180..b28af7c 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ import ( "github.com/develar/app-builder/pkg/blockmap" "github.com/develar/app-builder/pkg/dmg" "github.com/develar/app-builder/pkg/download" + "github.com/develar/app-builder/pkg/elfExecStack" "github.com/develar/app-builder/pkg/fs" "github.com/develar/app-builder/pkg/icons" "github.com/develar/app-builder/pkg/log-cli" @@ -53,6 +54,7 @@ func main() { snap.ConfigureCommand(app) icons.ConfigureCommand(app) dmg.ConfigureCommand(app) + elfExecStack.ConfigureCommand(app) command, err := app.Parse(os.Args[1:]) if err != nil { diff --git a/pkg/elfExecStack/elfExecStack.go b/pkg/elfExecStack/elfExecStack.go new file mode 100644 index 0000000..ab2e9c8 --- /dev/null +++ b/pkg/elfExecStack/elfExecStack.go @@ -0,0 +1,68 @@ +package elfExecStack + +import ( + "bytes" + "io" + "io/ioutil" + "os" + + "github.com/alecthomas/kingpin" + "github.com/apex/log" + "github.com/develar/errors" +) + +func ConfigureCommand(app *kingpin.Application) { + command := app.Command("clear-exec-stack", "") + + file := command.Flag("input", "").Short('i').Required().String() + + command.Action(func(context *kingpin.ParseContext) error { + err := ClearExecStack(*file) + if err != nil { + return errors.WithStack(err) + } + + return nil + }) +} + +func ClearExecStack(fileName string) error { + file, err := os.OpenFile(fileName, os.O_RDWR, 0) + if err != nil { + return errors.WithStack(err) + } + + defer file.Close() + + data, err := ioutil.ReadAll(io.LimitReader(file, 2048)) + if err != nil { + return errors.WithStack(err) + } + + // GNU_STACK 1685382481 + gnuStack := []byte{0x51, 0xE5, 0x74, 0x64} + index := bytes.Index(data, gnuStack) + if index < 0 { + return errors.Errorf("cannot find GNU_STACK header in a first 2048 bytes") + } + + flagIndex := index + len(gnuStack) + + if index >= len(data) { + return errors.Errorf("GNU_STACK header flags outside of first 2048 bytes") + } + + flagValue := data[flagIndex] + if flagValue == 6 { + // already cleared + log.WithField("flags", flagValue).Debug("stack is already cleared") + return nil + } + + _, err = file.WriteAt([]byte{0x06}, int64(flagIndex)) + if err != nil { + return errors.WithStack(err) + } + + return nil +} diff --git a/pkg/snap/snap.go b/pkg/snap/snap.go index 6408b1b..f750327 100644 --- a/pkg/snap/snap.go +++ b/pkg/snap/snap.go @@ -61,12 +61,12 @@ func ConfigureCommand(app *kingpin.Application) { } options := SnapOptions{ - appDir: command.Flag("app", "The app dir.").Short('a').Required().String(), - stageDir: command.Flag("stage", "The stage dir.").Short('s').Required().String(), - icon: command.Flag("icon", "The path to the icon.").String(), - hooksDir: command.Flag("hooks", "The hooks dir.").String(), + appDir: command.Flag("app", "The app dir.").Short('a').Required().String(), + stageDir: command.Flag("stage", "The stage dir.").Short('s').Required().String(), + icon: command.Flag("icon", "The path to the icon.").String(), + hooksDir: command.Flag("hooks", "The hooks dir.").String(), - arch: command.Flag("arch", "The arch.").Default("amd64").Enum("amd64", "i386", "armv7l", "arm64"), + arch: command.Flag("arch", "The arch.").Default("amd64").Enum("amd64", "i386", "armv7l", "arm64"), output: command.Flag("output", "The output file.").Short('o').Required().String(), @@ -86,7 +86,7 @@ func ConfigureCommand(app *kingpin.Application) { } } - isUseDocker, err := DetectIsUseDocker(*isUseDockerCommandArg, len( resolvedTemplateDir) != 0) + isUseDocker, err := DetectIsUseDocker(*isUseDockerCommandArg, len(resolvedTemplateDir) != 0) err = Snap(resolvedTemplateDir, isUseDocker, options) if err != nil { return errors.WithStack(err) @@ -153,7 +153,7 @@ func Snap(templateDir string, isUseDocker bool, options SnapOptions) error { iconPath := *options.icon if len(iconPath) != 0 { - err := fs.CopyUsingHardlink(iconPath, filepath.Join(snapMetaDir, "gui", "icon" + filepath.Ext(iconPath))) + err := fs.CopyUsingHardlink(iconPath, filepath.Join(snapMetaDir, "gui", "icon"+filepath.Ext(iconPath))) if err != nil { return errors.WithStack(err) } @@ -231,7 +231,7 @@ func buildUsingDocker(isUseTemplateApp bool, options SnapOptions) error { err := util.ExecuteWithInheritedStdOutAndStdErr(exec.Command("docker", "run", "--rm", "-v", filepath.Dir(*options.output)+":/out:delegated", - "--mount", "type=bind,source=" + stageDir+",destination=/stage,readonly", + "--mount", "type=bind,source="+stageDir+",destination=/stage,readonly", "--mount", "type=bind,source=" + *options.appDir+",destination=/tmp/final-stage/app,readonly", *options.dockerImage, "/bin/bash", "-c", strings.Join(commands, " && "), @@ -254,4 +254,4 @@ func cleanUpSnap(dir string) (error) { return nil }, nil }) -} \ No newline at end of file +}