diff --git a/.buildah.metadata b/.buildah.metadata index 524f7f1..ca2a784 100644 --- a/.buildah.metadata +++ b/.buildah.metadata @@ -1 +1 @@ -d8c4ecf4ff637f6341209f8ae685caae51c77fc7 SOURCES/buildah-00eb895.tar.gz +da35ceecbee25d37313869956f602161fc282153 SOURCES/buildah-9513cb8.tar.gz diff --git a/.gitignore b/.gitignore index 446fb64..dc35543 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/buildah-00eb895.tar.gz +SOURCES/buildah-9513cb8.tar.gz diff --git a/SOURCES/buildah-1756986.patch b/SOURCES/buildah-1756986.patch new file mode 100644 index 0000000..e70ea76 --- /dev/null +++ b/SOURCES/buildah-1756986.patch @@ -0,0 +1,98 @@ +From 6d7ab38f33edb9ab87a290a0c68cfd27b55b061f Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Wed, 8 Jan 2020 11:02:05 -0500 +Subject: [PATCH 1/2] Check for .dockerignore specifically + +When generating the list of exclusions to process .dockerignore +contents, don't include .dockerignore if we don't have a .dockerignore +file in the context directory. That way, if the file doesn't exist, and +the caller didn't pass in any patterns, we get no patterns instead of +just one ".dockerignore" pattern, and we can hit the faster copy path. + +Signed-off-by: Nalin Dahyabhai + +Closes: #2072 +Approved by: giuseppe +--- + add.go | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/add.go b/add.go +index b5119e369..e82a5ef9a 100644 +--- a/add.go ++++ b/add.go +@@ -215,7 +215,12 @@ func dockerIgnoreMatcher(lines []string, contextDir string) (*fileutils.PatternM + if contextDir == "" { + return nil, nil + } +- patterns := []string{".dockerignore"} ++ // If there's no .dockerignore file, then we don't have to add a ++ // pattern to tell copy logic to ignore it later. ++ var patterns []string ++ if _, err := os.Stat(filepath.Join(contextDir, ".dockerignore")); err == nil || !os.IsNotExist(err) { ++ patterns = []string{".dockerignore"} ++ } + for _, ignoreSpec := range lines { + ignoreSpec = strings.TrimSpace(ignoreSpec) + // ignore comments passed back from .dockerignore +@@ -224,7 +229,8 @@ func dockerIgnoreMatcher(lines []string, contextDir string) (*fileutils.PatternM + } + // if the spec starts with '!' it means the pattern + // should be included. make a note so that we can move +- // it to the front of the updated pattern ++ // it to the front of the updated pattern, and insert ++ // the context dir's path in between + includeFlag := "" + if strings.HasPrefix(ignoreSpec, "!") { + includeFlag = "!" + +From f999964084ce75c833b0cffd17fb09b947dad506 Mon Sep 17 00:00:00 2001 +From: Nalin Dahyabhai +Date: Wed, 8 Jan 2020 11:04:57 -0500 +Subject: [PATCH 2/2] copyFileWithTar: close source files at the right time + +Close source files after we've finished reading from them, rather than +leaving it for later. + +Signed-off-by: Nalin Dahyabhai + +Closes: #2072 +Approved by: giuseppe +--- + util.go | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/util.go b/util.go +index b4670e41c..2f923357c 100644 +--- a/util.go ++++ b/util.go +@@ -165,11 +165,6 @@ func (b *Builder) copyFileWithTar(tarIDMappingOptions *IDMappingOptions, chownOp + if err != nil { + return errors.Wrapf(err, "error opening %q to copy its contents", src) + } +- defer func() { +- if err := f.Close(); err != nil { +- logrus.Debugf("error closing %s: %v", fi.Name(), err) +- } +- }() + } + } + +@@ -200,6 +195,9 @@ func (b *Builder) copyFileWithTar(tarIDMappingOptions *IDMappingOptions, chownOp + logrus.Debugf("error copying contents of %s: %v", fi.Name(), err) + copyErr = err + } ++ if err = srcFile.Close(); err != nil { ++ logrus.Debugf("error closing %s: %v", fi.Name(), err) ++ } + } + if err = writer.Close(); err != nil { + logrus.Debugf("error closing write pipe for %s: %v", hdr.Name, err) +@@ -213,7 +211,6 @@ func (b *Builder) copyFileWithTar(tarIDMappingOptions *IDMappingOptions, chownOp + if err == nil { + err = copyErr + } +- f = nil + if pipeWriter != nil { + pipeWriter.Close() + } diff --git a/SOURCES/buildah-1784950.patch b/SOURCES/buildah-1784950.patch new file mode 100644 index 0000000..5c88c11 --- /dev/null +++ b/SOURCES/buildah-1784950.patch @@ -0,0 +1,145 @@ +From fb7d2b6bd6a16ffdbe4a69428e3ba5b487719e78 Mon Sep 17 00:00:00 2001 +From: Daniel J Walsh +Date: Tue, 17 Dec 2019 15:24:29 -0500 +Subject: [PATCH] Add support for FIPS-Mode backends + +If host is running in fips mode, then RHEL8.2 and beyond container images +will come with a directory /usr/share/crypto-policies/back-ends/FIPS. +This directory needs to be bind mounted over /etc/crypto-policies/back-ends in +order to make all tools in the container follow the FIPS Mode rules. + +Signed-off-by: Daniel J Walsh +--- + pkg/secrets/secrets.go | 48 +++++++++++++++++++++++++++++++++--------- + run_linux.go | 2 +- + 2 files changed, 39 insertions(+), 11 deletions(-) + +diff -up ./buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/pkg/secrets/secrets.go.1784950 ./buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/pkg/secrets/secrets.go +--- buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/pkg/secrets/secrets.go.1784950 2020-02-19 16:09:40.446764064 +0100 ++++ buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/pkg/secrets/secrets.go 2020-02-19 16:09:40.448764092 +0100 +@@ -148,12 +148,21 @@ func getMountsMap(path string) (string, + } + + // SecretMounts copies, adds, and mounts the secrets to the container root filesystem ++// Deprecated, Please use SecretMountWithUIDGID + func SecretMounts(mountLabel, containerWorkingDir, mountFile string, rootless, disableFips bool) []rspec.Mount { + return SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, containerWorkingDir, 0, 0, rootless, disableFips) + } + +-// SecretMountsWithUIDGID specifies the uid/gid of the owner +-func SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPrefix string, uid, gid int, rootless, disableFips bool) []rspec.Mount { ++// SecretMountsWithUIDGID copies, adds, and mounts the secrets to the container root filesystem ++// mountLabel: MAC/SELinux label for container content ++// containerWorkingDir: Private data for storing secrets on the host mounted in container. ++// mountFile: Additional mount points required for the container. ++// mountPoint: Container image mountpoint ++// uid: to assign to content created for secrets ++// gid: to assign to content created for secrets ++// rootless: indicates whether container is running in rootless mode ++// disableFips: indicates whether system should ignore fips mode ++func SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint string, uid, gid int, rootless, disableFips bool) []rspec.Mount { + var ( + secretMounts []rspec.Mount + mountFiles []string +@@ -171,7 +180,7 @@ func SecretMountsWithUIDGID(mountLabel, + } + for _, file := range mountFiles { + if _, err := os.Stat(file); err == nil { +- mounts, err := addSecretsFromMountsFile(file, mountLabel, containerWorkingDir, mountPrefix, uid, gid) ++ mounts, err := addSecretsFromMountsFile(file, mountLabel, containerWorkingDir, uid, gid) + if err != nil { + logrus.Warnf("error mounting secrets, skipping entry in %s: %v", file, err) + } +@@ -187,7 +196,7 @@ func SecretMountsWithUIDGID(mountLabel, + // Add FIPS mode secret if /etc/system-fips exists on the host + _, err := os.Stat("/etc/system-fips") + if err == nil { +- if err := addFIPSModeSecret(&secretMounts, containerWorkingDir, mountPrefix, mountLabel, uid, gid); err != nil { ++ if err := addFIPSModeSecret(&secretMounts, containerWorkingDir, mountPoint, mountLabel, uid, gid); err != nil { + logrus.Errorf("error adding FIPS mode secret to container: %v", err) + } + } else if os.IsNotExist(err) { +@@ -206,7 +215,7 @@ func rchown(chowndir string, uid, gid in + + // addSecretsFromMountsFile copies the contents of host directory to container directory + // and returns a list of mounts +-func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir, mountPrefix string, uid, gid int) ([]rspec.Mount, error) { ++func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir string, uid, gid int) ([]rspec.Mount, error) { + var mounts []rspec.Mount + defaultMountsPaths := getMounts(filePath) + for _, path := range defaultMountsPaths { +@@ -285,7 +294,7 @@ func addSecretsFromMountsFile(filePath, + } + + m := rspec.Mount{ +- Source: filepath.Join(mountPrefix, ctrDirOrFile), ++ Source: ctrDirOrFileOnHost, + Destination: ctrDirOrFile, + Type: "bind", + Options: []string{"bind", "rprivate"}, +@@ -300,15 +309,15 @@ func addSecretsFromMountsFile(filePath, + // root filesystem if /etc/system-fips exists on hosts. + // This enables the container to be FIPS compliant and run openssl in + // FIPS mode as the host is also in FIPS mode. +-func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir, mountPrefix, mountLabel string, uid, gid int) error { ++func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir, mountPoint, mountLabel string, uid, gid int) error { + secretsDir := "/run/secrets" + ctrDirOnHost := filepath.Join(containerWorkingDir, secretsDir) + if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) { + if err = idtools.MkdirAllAs(ctrDirOnHost, 0755, uid, gid); err != nil { +- return errors.Wrapf(err, "making container directory on host failed") ++ return errors.Wrapf(err, "making container directory %q on host failed", ctrDirOnHost) + } + if err = label.Relabel(ctrDirOnHost, mountLabel, false); err != nil { +- return errors.Wrap(err, "error applying correct labels") ++ return errors.Wrapf(err, "error applying correct labels on %q", ctrDirOnHost) + } + } + fipsFile := filepath.Join(ctrDirOnHost, "system-fips") +@@ -323,7 +332,7 @@ func addFIPSModeSecret(mounts *[]rspec.M + + if !mountExists(*mounts, secretsDir) { + m := rspec.Mount{ +- Source: filepath.Join(mountPrefix, secretsDir), ++ Source: ctrDirOnHost, + Destination: secretsDir, + Type: "bind", + Options: []string{"bind", "rprivate"}, +@@ -331,6 +340,25 @@ func addFIPSModeSecret(mounts *[]rspec.M + *mounts = append(*mounts, m) + } + ++ srcBackendDir := "/usr/share/crypto-policies/back-ends/FIPS" ++ destDir := "/etc/crypto-policies/back-ends" ++ srcOnHost := filepath.Join(mountPoint, srcBackendDir) ++ if _, err := os.Stat(srcOnHost); err != nil { ++ if os.IsNotExist(err) { ++ return nil ++ } ++ return errors.Wrapf(err, "failed to stat FIPS Backend directory %q", ctrDirOnHost) ++ } ++ ++ if !mountExists(*mounts, destDir) { ++ m := rspec.Mount{ ++ Source: srcOnHost, ++ Destination: destDir, ++ Type: "bind", ++ Options: []string{"bind", "rprivate"}, ++ } ++ *mounts = append(*mounts, m) ++ } + return nil + } + +diff -up ./buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/run_linux.go.1784950 ./buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/run_linux.go +--- buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/run_linux.go.1784950 2020-02-19 16:09:40.416763645 +0100 ++++ buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/run_linux.go 2020-02-19 16:09:40.419763687 +0100 +@@ -460,7 +460,7 @@ func (b *Builder) setupMounts(mountPoint + } + + // Get the list of secrets mounts. +- secretMounts := secrets.SecretMountsWithUIDGID(b.MountLabel, cdir, b.DefaultMountsFilePath, cdir, int(rootUID), int(rootGID), unshare.IsRootless(), false) ++ secretMounts := secrets.SecretMountsWithUIDGID(b.MountLabel, cdir, b.DefaultMountsFilePath, mountPoint, int(rootUID), int(rootGID), unshare.IsRootless(), false) + + // Add temporary copies of the contents of volume locations at the + // volume locations, unless we already have something there. diff --git a/SOURCES/buildah-1792243.patch b/SOURCES/buildah-1792243.patch new file mode 100644 index 0000000..bc53b49 --- /dev/null +++ b/SOURCES/buildah-1792243.patch @@ -0,0 +1,12 @@ +diff -up ./buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/vendor/github.com/mtrmac/gpgme/gpgme.go.1792243 ./buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/vendor/github.com/mtrmac/gpgme/gpgme.go +--- buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/vendor/github.com/mtrmac/gpgme/gpgme.go.1792243 2020-01-20 14:17:06.032949209 +0100 ++++ buildah-9513cb8c7bec0f7789c696aee4d252ebf85194cc/vendor/github.com/mtrmac/gpgme/gpgme.go 2020-01-20 14:17:06.034949229 +0100 +@@ -1,7 +1,7 @@ + // Package gpgme provides a Go wrapper for the GPGME library + package gpgme + +-// #cgo LDFLAGS: -lgpgme -lassuan -lgpg-error ++// #cgo LDFLAGS: -lgpgme-pthread -lassuan -lgpg-error + // #cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64 + // #include + // #include diff --git a/SOURCES/buildah-CVE-2020-8945.patch b/SOURCES/buildah-CVE-2020-8945.patch new file mode 100644 index 0000000..abb9597 --- /dev/null +++ b/SOURCES/buildah-CVE-2020-8945.patch @@ -0,0 +1,961 @@ +From c48714e522ea147e49b0d0dfddf58a9b47137055 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= +Date: Thu, 20 Feb 2020 19:51:27 +0100 +Subject: [PATCH 1/3] Update to github.com/mtrmac/gpgme v0.1.2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes CVE-2020-8945 by incorporating proglottis/gpgme#23 . + +Other changes included by the rebase: +- Support for gpgme_off_t (~no-op on Linux) +- Wrapping a few more GPGME functions (irrelevant if we don't call them) + +Given how invasive the CVE fix is (affecting basically all binding +code), it seems safer to just update the package (and be verifiably +equivalent with upstream) than to backport and try to back out the few +other changes. + +Performed by +$ go get github.com/mtrmac/gpgme@v0.1.2 +$ make vendor +and manually backing out unrelated deletions of files (which Go 1.13 does +but Go 1.11, used for testing the old version, does not). + +Signed-off-by: Miloslav Trmač +--- + go.mod | 1 + + go.sum | 2 + + vendor/github.com/mtrmac/gpgme/.appveyor.yml | 40 ++ + vendor/github.com/mtrmac/gpgme/.travis.yml | 32 ++ + vendor/github.com/mtrmac/gpgme/data.go | 18 +- + vendor/github.com/mtrmac/gpgme/go.mod | 3 + + vendor/github.com/mtrmac/gpgme/go_gpgme.c | 22 ++ + vendor/github.com/mtrmac/gpgme/go_gpgme.h | 12 + + vendor/github.com/mtrmac/gpgme/gpgme.go | 346 ++++++++++++++---- + .../mtrmac/gpgme/unset_agent_info.go | 18 + + .../mtrmac/gpgme/unset_agent_info_windows.go | 14 + + vendor/modules.txt | 2 +- + 12 files changed, 432 insertions(+), 78 deletions(-) + create mode 100644 vendor/github.com/mtrmac/gpgme/.appveyor.yml + create mode 100644 vendor/github.com/mtrmac/gpgme/.travis.yml + create mode 100644 vendor/github.com/mtrmac/gpgme/go.mod + create mode 100644 vendor/github.com/mtrmac/gpgme/unset_agent_info.go + create mode 100644 vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go + +diff --git a/vendor/github.com/mtrmac/gpgme/.appveyor.yml b/vendor/github.com/mtrmac/gpgme/.appveyor.yml +new file mode 100644 +index 000000000..2fdc09ab5 +--- /dev/null ++++ b/vendor/github.com/mtrmac/gpgme/.appveyor.yml +@@ -0,0 +1,40 @@ ++--- ++version: 0.{build} ++platform: x86 ++branches: ++ only: ++ - master ++ ++clone_folder: c:\gopath\src\github.com\proglottis\gpgme ++ ++environment: ++ GOPATH: c:\gopath ++ GOROOT: C:\go-x86 ++ CGO_LDFLAGS: -LC:\gpg\lib ++ CGO_CFLAGS: -IC:\gpg\include ++ GPG_DIR: C:\gpg ++ ++install: ++ - nuget install 7ZipCLI -ExcludeVersion ++ - set PATH=%appveyor_build_folder%\7ZipCLI\tools;%PATH% ++ - appveyor DownloadFile https://www.gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.1.20_20170403.exe -FileName gnupg-w32-2.1.20_20170403.exe ++ - 7z x -o%GPG_DIR% gnupg-w32-2.1.20_20170403.exe ++ - copy "%GPG_DIR%\lib\libgpg-error.imp" "%GPG_DIR%\lib\libgpg-error.a" ++ - copy "%GPG_DIR%\lib\libassuan.imp" "%GPG_DIR%\lib\libassuan.a" ++ - copy "%GPG_DIR%\lib\libgpgme.imp" "%GPG_DIR%\lib\libgpgme.a" ++ - set PATH=%GOPATH%\bin;%GOROOT%\bin;%GPG_DIR%\bin;C:\MinGW\bin;%PATH% ++ - C:\cygwin\bin\sed -i 's/"GPG_AGENT_INFO"/"GPG_AGENT_INFO="/;s/C.unsetenv(v)/C.putenv(v)/' %APPVEYOR_BUILD_FOLDER%\gpgme.go ++ ++test_script: ++ - go test -v github.com/proglottis/gpgme ++ ++ ++build_script: ++ - go build -o example_decrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\decrypt.go ++ - go build -o example_encrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\encrypt.go ++ ++artifacts: ++ - path: example_decrypt.exe ++ name: decrypt example binary ++ - path: example_encrypt.exe ++ name: encrypt example binary +\ No newline at end of file +diff --git a/vendor/github.com/mtrmac/gpgme/.travis.yml b/vendor/github.com/mtrmac/gpgme/.travis.yml +new file mode 100644 +index 000000000..619e33721 +--- /dev/null ++++ b/vendor/github.com/mtrmac/gpgme/.travis.yml +@@ -0,0 +1,32 @@ ++--- ++language: go ++os: ++ - linux ++ - osx ++ - windows ++dist: xenial ++sudo: false ++ ++go: ++ - 1.11 ++ - 1.12 ++ - 1.13 ++ ++addons: ++ apt: ++ packages: ++ - libgpgme11-dev ++ homebrew: ++ packages: ++ - gnupg ++ - gnupg@1.4 ++ - gpgme ++ update: true ++ ++matrix: ++ allow_failures: ++ - os: windows ++ ++before_install: ++ - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install msys2; fi ++ - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install gpg4win; fi +diff --git a/vendor/github.com/mtrmac/gpgme/data.go b/vendor/github.com/mtrmac/gpgme/data.go +index eebc97263..eee32c032 100644 +--- a/vendor/github.com/mtrmac/gpgme/data.go ++++ b/vendor/github.com/mtrmac/gpgme/data.go +@@ -50,25 +50,25 @@ func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t { + } + + //export gogpgme_seekfunc +-func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t { ++func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t { + d := callbackLookup(uintptr(handle)).(*Data) + n, err := d.s.Seek(int64(offset), int(whence)) + if err != nil { + C.gpgme_err_set_errno(C.EIO) + return -1 + } +- return C.off_t(n) ++ return C.gpgme_off_t(n) + } + + // The Data buffer used to communicate with GPGME + type Data struct { +- dh C.gpgme_data_t ++ dh C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C + buf []byte + cbs C.struct_gpgme_data_cbs + r io.Reader + w io.Writer + s io.Seeker +- cbc uintptr ++ cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh) + } + + func newData() *Data { +@@ -154,12 +154,14 @@ func (d *Data) Close() error { + callbackDelete(d.cbc) + } + _, err := C.gpgme_data_release(d.dh) ++ runtime.KeepAlive(d) + d.dh = nil + return err + } + + func (d *Data) Write(p []byte) (int, error) { + n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p))) ++ runtime.KeepAlive(d) + if err != nil { + return 0, err + } +@@ -171,6 +173,7 @@ func (d *Data) Write(p []byte) (int, error) { + + func (d *Data) Read(p []byte) (int, error) { + n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p))) ++ runtime.KeepAlive(d) + if err != nil { + return 0, err + } +@@ -181,11 +184,14 @@ func (d *Data) Read(p []byte) (int, error) { + } + + func (d *Data) Seek(offset int64, whence int) (int64, error) { +- n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence)) ++ n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence)) ++ runtime.KeepAlive(d) + return int64(n), err + } + + // Name returns the associated filename if any + func (d *Data) Name() string { +- return C.GoString(C.gpgme_data_get_file_name(d.dh)) ++ res := C.GoString(C.gpgme_data_get_file_name(d.dh)) ++ runtime.KeepAlive(d) ++ return res + } +diff --git a/vendor/github.com/mtrmac/gpgme/go.mod b/vendor/github.com/mtrmac/gpgme/go.mod +new file mode 100644 +index 000000000..3dd09c9fb +--- /dev/null ++++ b/vendor/github.com/mtrmac/gpgme/go.mod +@@ -0,0 +1,3 @@ ++module github.com/mtrmac/gpgme ++ ++go 1.11 +diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/github.com/mtrmac/gpgme/go_gpgme.c +index b887574e0..00da3ab30 100644 +--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.c ++++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.c +@@ -8,6 +8,28 @@ void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintpt + gpgme_set_passphrase_cb(ctx, cb, (void *)handle); + } + ++gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence) { ++ return gpgme_data_seek(dh, offset, whence); ++} ++ ++gpgme_error_t gogpgme_op_assuan_transact_ext( ++ gpgme_ctx_t ctx, ++ char* cmd, ++ uintptr_t data_h, ++ uintptr_t inquiry_h, ++ uintptr_t status_h, ++ gpgme_error_t *operr ++ ){ ++ return gpgme_op_assuan_transact_ext( ++ ctx, ++ cmd, ++ (gpgme_assuan_data_cb_t) gogpgme_assuan_data_callback, (void *)data_h, ++ (gpgme_assuan_inquire_cb_t) gogpgme_assuan_inquiry_callback, (void *)inquiry_h, ++ (gpgme_assuan_status_cb_t) gogpgme_assuan_status_callback, (void *)status_h, ++ operr ++ ); ++} ++ + unsigned int key_revoked(gpgme_key_t k) { + return k->revoked; + } +diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/github.com/mtrmac/gpgme/go_gpgme.h +index a3678b127..d4826ab36 100644 +--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.h ++++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.h +@@ -6,12 +6,24 @@ + + #include + ++/* GPGME_VERSION_NUMBER was introduced in 1.4.0 */ ++#if !defined(GPGME_VERSION_NUMBER) || GPGME_VERSION_NUMBER < 0x010402 ++typedef off_t gpgme_off_t; /* Introduced in 1.4.2 */ ++#endif ++ + extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size); + extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size); + extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence); + extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd); + extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle); + extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle); ++extern gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence); ++ ++extern gpgme_error_t gogpgme_op_assuan_transact_ext(gpgme_ctx_t ctx, char *cmd, uintptr_t data_h, uintptr_t inquiry_h , uintptr_t status_h, gpgme_error_t *operr); ++ ++extern gpgme_error_t gogpgme_assuan_data_callback(void *opaque, void* data, size_t datalen ); ++extern gpgme_error_t gogpgme_assuan_inquiry_callback(void *opaque, char* name, char* args); ++extern gpgme_error_t gogpgme_assuan_status_callback(void *opaque, char* status, char* args); + + extern unsigned int key_revoked(gpgme_key_t k); + extern unsigned int key_expired(gpgme_key_t k); +diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/mtrmac/gpgme/gpgme.go +index 20aad737c..c19b9aebc 100644 +--- a/vendor/github.com/mtrmac/gpgme/gpgme.go ++++ b/vendor/github.com/mtrmac/gpgme/gpgme.go +@@ -7,7 +7,6 @@ package gpgme + // #include + // #include "go_gpgme.h" + import "C" +- + import ( + "fmt" + "io" +@@ -48,9 +47,8 @@ const ( + ProtocolAssuan Protocol = C.GPGME_PROTOCOL_ASSUAN + ProtocolG13 Protocol = C.GPGME_PROTOCOL_G13 + ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER +- // ProtocolSpawn Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3 +- ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT +- ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN ++ ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT ++ ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN + ) + + type PinEntryMode int +@@ -70,7 +68,6 @@ const ( + EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO + EncryptPrepare EncryptFlag = C.GPGME_ENCRYPT_PREPARE + EncryptExceptSign EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN +- // EncryptNoCompress EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3 + ) + + type HashAlgo int +@@ -84,7 +81,6 @@ const ( + KeyListModeExtern KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN + KeyListModeSigs KeyListMode = C.GPGME_KEYLIST_MODE_SIGS + KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS +- // KeyListModeWithSecret KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3 + KeyListModeEphemeral KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL + KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE + ) +@@ -168,39 +164,60 @@ func EngineCheckVersion(p Protocol) error { + } + + type EngineInfo struct { +- info C.gpgme_engine_info_t ++ next *EngineInfo ++ protocol Protocol ++ fileName string ++ homeDir string ++ version string ++ requiredVersion string + } + +-func (e *EngineInfo) Next() *EngineInfo { +- if e.info.next == nil { +- return nil ++func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo { ++ res := &EngineInfo{ ++ next: nil, ++ protocol: Protocol(info.protocol), ++ fileName: C.GoString(info.file_name), ++ homeDir: C.GoString(info.home_dir), ++ version: C.GoString(info.version), ++ requiredVersion: C.GoString(info.req_version), ++ } ++ if info.next != nil { ++ res.next = copyEngineInfo(info.next) + } +- return &EngineInfo{info: e.info.next} ++ return res ++} ++ ++func (e *EngineInfo) Next() *EngineInfo { ++ return e.next + } + + func (e *EngineInfo) Protocol() Protocol { +- return Protocol(e.info.protocol) ++ return e.protocol + } + + func (e *EngineInfo) FileName() string { +- return C.GoString(e.info.file_name) ++ return e.fileName + } + + func (e *EngineInfo) Version() string { +- return C.GoString(e.info.version) ++ return e.version + } + + func (e *EngineInfo) RequiredVersion() string { +- return C.GoString(e.info.req_version) ++ return e.requiredVersion + } + + func (e *EngineInfo) HomeDir() string { +- return C.GoString(e.info.home_dir) ++ return e.homeDir + } + + func GetEngineInfo() (*EngineInfo, error) { +- info := &EngineInfo{} +- return info, handleError(C.gpgme_get_engine_info(&info.info)) ++ var cInfo C.gpgme_engine_info_t ++ err := handleError(C.gpgme_get_engine_info(&cInfo)) ++ if err != nil { ++ return nil, err ++ } ++ return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done. + } + + func SetEngineInfo(proto Protocol, fileName, homeDir string) error { +@@ -261,9 +278,9 @@ type Context struct { + KeyError error + + callback Callback +- cbc uintptr ++ cbc uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx) + +- ctx C.gpgme_ctx_t ++ ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C + } + + func New() (*Context, error) { +@@ -281,49 +298,68 @@ func (c *Context) Release() { + callbackDelete(c.cbc) + } + C.gpgme_release(c.ctx) ++ runtime.KeepAlive(c) + c.ctx = nil + } + + func (c *Context) SetArmor(yes bool) { + C.gpgme_set_armor(c.ctx, cbool(yes)) ++ runtime.KeepAlive(c) + } + + func (c *Context) Armor() bool { +- return C.gpgme_get_armor(c.ctx) != 0 ++ res := C.gpgme_get_armor(c.ctx) != 0 ++ runtime.KeepAlive(c) ++ return res + } + + func (c *Context) SetTextMode(yes bool) { + C.gpgme_set_textmode(c.ctx, cbool(yes)) ++ runtime.KeepAlive(c) + } + + func (c *Context) TextMode() bool { +- return C.gpgme_get_textmode(c.ctx) != 0 ++ res := C.gpgme_get_textmode(c.ctx) != 0 ++ runtime.KeepAlive(c) ++ return res + } + + func (c *Context) SetProtocol(p Protocol) error { +- return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p))) ++ err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p))) ++ runtime.KeepAlive(c) ++ return err + } + + func (c *Context) Protocol() Protocol { +- return Protocol(C.gpgme_get_protocol(c.ctx)) ++ res := Protocol(C.gpgme_get_protocol(c.ctx)) ++ runtime.KeepAlive(c) ++ return res + } + + func (c *Context) SetKeyListMode(m KeyListMode) error { +- return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m))) ++ err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m))) ++ runtime.KeepAlive(c) ++ return err + } + + func (c *Context) KeyListMode() KeyListMode { +- return KeyListMode(C.gpgme_get_keylist_mode(c.ctx)) ++ res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx)) ++ runtime.KeepAlive(c) ++ return res + } + + // Unavailable in 1.3.2: + // func (c *Context) SetPinEntryMode(m PinEntryMode) error { +-// return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m))) ++// err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m))) ++// runtime.KeepAlive(c) ++// return err + // } + + // Unavailable in 1.3.2: + // func (c *Context) PinEntryMode() PinEntryMode { +-// return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx)) ++// res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx)) ++// runtime.KeepAlive(c) ++// return res + // } + + func (c *Context) SetCallback(callback Callback) error { +@@ -340,11 +376,17 @@ func (c *Context) SetCallback(callback Callback) error { + c.cbc = 0 + _, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0) + } ++ runtime.KeepAlive(c) + return err + } + + func (c *Context) EngineInfo() *EngineInfo { +- return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)} ++ cInfo := C.gpgme_ctx_get_engine_info(c.ctx) ++ runtime.KeepAlive(c) ++ // NOTE: c must be live as long as we are accessing cInfo. ++ res := copyEngineInfo(cInfo) ++ runtime.KeepAlive(c) // for accesses to cInfo ++ return res + } + + func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error { +@@ -357,19 +399,23 @@ func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error + chome = C.CString(homeDir) + defer C.free(unsafe.Pointer(chome)) + } +- return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome)) ++ err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome)) ++ runtime.KeepAlive(c) ++ return err + } + + func (c *Context) KeyListStart(pattern string, secretOnly bool) error { + cpattern := C.CString(pattern) + defer C.free(unsafe.Pointer(cpattern)) +- err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)) +- return handleError(err) ++ err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))) ++ runtime.KeepAlive(c) ++ return err + } + + func (c *Context) KeyListNext() bool { + c.Key = newKey() + err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k)) ++ runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key) + if err != nil { + if e, ok := err.(Error); ok && e.Code() == ErrorEOF { + c.KeyError = nil +@@ -383,7 +429,9 @@ func (c *Context) KeyListNext() bool { + } + + func (c *Context) KeyListEnd() error { +- return handleError(C.gpgme_op_keylist_end(c.ctx)) ++ err := handleError(C.gpgme_op_keylist_end(c.ctx)) ++ runtime.KeepAlive(c) ++ return err + } + + func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) { +@@ -391,7 +439,11 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) { + cfpr := C.CString(fingerprint) + defer C.free(unsafe.Pointer(cfpr)) + err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret))) +- if e, ok := err.(Error); key.k == nil && ok && e.Code() == ErrorEOF { ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(key) ++ keyKIsNil := key.k == nil ++ runtime.KeepAlive(key) ++ if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF { + return nil, fmt.Errorf("key %q not found", fingerprint) + } + if err != nil { +@@ -401,11 +453,19 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) { + } + + func (c *Context) Decrypt(ciphertext, plaintext *Data) error { +- return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh)) ++ err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh)) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(ciphertext) ++ runtime.KeepAlive(plaintext) ++ return err + } + + func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error { +- return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh)) ++ err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh)) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(ciphertext) ++ runtime.KeepAlive(plaintext) ++ return err + } + + type Signature struct { +@@ -432,10 +492,20 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err + plainPtr = plain.dh + } + err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr)) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(sig) ++ if signedText != nil { ++ runtime.KeepAlive(signedText) ++ } ++ if plain != nil { ++ runtime.KeepAlive(plain) ++ } + if err != nil { + return "", nil, err + } + res := C.gpgme_op_verify_result(c.ctx) ++ runtime.KeepAlive(c) ++ // NOTE: c must be live as long as we are accessing res. + sigs := []Signature{} + for s := res.signatures; s != nil; s = s.next { + sig := Signature{ +@@ -455,7 +525,9 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err + } + sigs = append(sigs, sig) + } +- return C.GoString(res.file_name), sigs, nil ++ fileName := C.GoString(res.file_name) ++ runtime.KeepAlive(c) // for all accesses to res above ++ return fileName, sigs, nil + } + + func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error { +@@ -467,18 +539,116 @@ func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphe + *ptr = recipients[i].k + } + err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(recipients) ++ runtime.KeepAlive(plaintext) ++ runtime.KeepAlive(ciphertext) + return handleError(err) + } + + func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error { + C.gpgme_signers_clear(c.ctx) ++ runtime.KeepAlive(c) + for _, k := range signers { +- if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil { ++ err := handleError(C.gpgme_signers_add(c.ctx, k.k)) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(k) ++ if err != nil { + C.gpgme_signers_clear(c.ctx) ++ runtime.KeepAlive(c) + return err + } + } +- return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode))) ++ err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode))) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(plain) ++ runtime.KeepAlive(sig) ++ return err ++} ++ ++type AssuanDataCallback func(data []byte) error ++type AssuanInquireCallback func(name, args string) error ++type AssuanStatusCallback func(status, args string) error ++ ++// AssuanSend sends a raw Assuan command to gpg-agent ++func (c *Context) AssuanSend( ++ cmd string, ++ data AssuanDataCallback, ++ inquiry AssuanInquireCallback, ++ status AssuanStatusCallback, ++) error { ++ var operr C.gpgme_error_t ++ ++ dataPtr := callbackAdd(&data) ++ inquiryPtr := callbackAdd(&inquiry) ++ statusPtr := callbackAdd(&status) ++ cmdCStr := C.CString(cmd) ++ defer C.free(unsafe.Pointer(cmdCStr)) ++ err := C.gogpgme_op_assuan_transact_ext( ++ c.ctx, ++ cmdCStr, ++ C.uintptr_t(dataPtr), ++ C.uintptr_t(inquiryPtr), ++ C.uintptr_t(statusPtr), ++ &operr, ++ ) ++ runtime.KeepAlive(c) ++ ++ if handleError(operr) != nil { ++ return handleError(operr) ++ } ++ return handleError(err) ++} ++ ++//export gogpgme_assuan_data_callback ++func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t { ++ c := callbackLookup(uintptr(handle)).(*AssuanDataCallback) ++ if *c == nil { ++ return 0 ++ } ++ (*c)(C.GoBytes(data, C.int(datalen))) ++ return 0 ++} ++ ++//export gogpgme_assuan_inquiry_callback ++func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t { ++ name := C.GoString(cName) ++ args := C.GoString(cArgs) ++ c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback) ++ if *c == nil { ++ return 0 ++ } ++ (*c)(name, args) ++ return 0 ++} ++ ++//export gogpgme_assuan_status_callback ++func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t { ++ status := C.GoString(cStatus) ++ args := C.GoString(cArgs) ++ c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback) ++ if *c == nil { ++ return 0 ++ } ++ (*c)(status, args) ++ return 0 ++} ++ ++// ExportModeFlags defines how keys are exported from Export ++type ExportModeFlags uint ++ ++const ( ++ ExportModeExtern ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN ++ ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL ++) ++ ++func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error { ++ pat := C.CString(pattern) ++ defer C.free(unsafe.Pointer(pat)) ++ err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh)) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(data) ++ return err + } + + // ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned". +@@ -517,10 +687,14 @@ type ImportResult struct { + + func (c *Context) Import(keyData *Data) (*ImportResult, error) { + err := handleError(C.gpgme_op_import(c.ctx, keyData.dh)) ++ runtime.KeepAlive(c) ++ runtime.KeepAlive(keyData) + if err != nil { + return nil, err + } + res := C.gpgme_op_import_result(c.ctx) ++ runtime.KeepAlive(c) ++ // NOTE: c must be live as long as we are accessing res. + imports := []ImportStatus{} + for s := res.imports; s != nil; s = s.next { + imports = append(imports, ImportStatus{ +@@ -529,7 +703,7 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) { + Status: ImportStatusFlags(s.status), + }) + } +- return &ImportResult{ ++ importResult := &ImportResult{ + Considered: int(res.considered), + NoUserID: int(res.no_user_id), + Imported: int(res.imported), +@@ -544,11 +718,13 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) { + SecretUnchanged: int(res.secret_unchanged), + NotImported: int(res.not_imported), + Imports: imports, +- }, nil ++ } ++ runtime.KeepAlive(c) // for all accesses to res above ++ return importResult, nil + } + + type Key struct { +- k C.gpgme_key_t ++ k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C + } + + func newKey() *Key { +@@ -559,85 +735,122 @@ func newKey() *Key { + + func (k *Key) Release() { + C.gpgme_key_release(k.k) ++ runtime.KeepAlive(k) + k.k = nil + } + + func (k *Key) Revoked() bool { +- return C.key_revoked(k.k) != 0 ++ res := C.key_revoked(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) Expired() bool { +- return C.key_expired(k.k) != 0 ++ res := C.key_expired(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) Disabled() bool { +- return C.key_disabled(k.k) != 0 ++ res := C.key_disabled(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) Invalid() bool { +- return C.key_invalid(k.k) != 0 ++ res := C.key_invalid(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) CanEncrypt() bool { +- return C.key_can_encrypt(k.k) != 0 ++ res := C.key_can_encrypt(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) CanSign() bool { +- return C.key_can_sign(k.k) != 0 ++ res := C.key_can_sign(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) CanCertify() bool { +- return C.key_can_certify(k.k) != 0 ++ res := C.key_can_certify(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) Secret() bool { +- return C.key_secret(k.k) != 0 ++ res := C.key_secret(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) CanAuthenticate() bool { +- return C.key_can_authenticate(k.k) != 0 ++ res := C.key_can_authenticate(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) IsQualified() bool { +- return C.key_is_qualified(k.k) != 0 ++ res := C.key_is_qualified(k.k) != 0 ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) Protocol() Protocol { +- return Protocol(k.k.protocol) ++ res := Protocol(k.k.protocol) ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) IssuerSerial() string { +- return C.GoString(k.k.issuer_serial) ++ res := C.GoString(k.k.issuer_serial) ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) IssuerName() string { +- return C.GoString(k.k.issuer_name) ++ res := C.GoString(k.k.issuer_name) ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) ChainID() string { +- return C.GoString(k.k.chain_id) ++ res := C.GoString(k.k.chain_id) ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) OwnerTrust() Validity { +- return Validity(k.k.owner_trust) ++ res := Validity(k.k.owner_trust) ++ runtime.KeepAlive(k) ++ return res + } + + func (k *Key) SubKeys() *SubKey { +- if k.k.subkeys == nil { ++ subKeys := k.k.subkeys ++ runtime.KeepAlive(k) ++ if subKeys == nil { + return nil + } +- return &SubKey{k: k.k.subkeys, parent: k} ++ return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid + } + + func (k *Key) UserIDs() *UserID { +- if k.k.uids == nil { ++ uids := k.k.uids ++ runtime.KeepAlive(k) ++ if uids == nil { + return nil + } +- return &UserID{u: k.k.uids, parent: k} ++ return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid + } + + func (k *Key) KeyListMode() KeyListMode { +- return KeyListMode(k.k.keylist_mode) ++ res := KeyListMode(k.k.keylist_mode) ++ runtime.KeepAlive(k) ++ return res + } + + type SubKey struct { +@@ -737,12 +950,3 @@ func (u *UserID) Comment() string { + func (u *UserID) Email() string { + return C.GoString(u.u.email) + } +- +-// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG. +-// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved +-// - and cgo can't be used in tests. So, provide this helper for test initialization. +-func unsetenvGPGAgentInfo() { +- v := C.CString("GPG_AGENT_INFO") +- defer C.free(unsafe.Pointer(v)) +- C.unsetenv(v) +-} +diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go +new file mode 100644 +index 000000000..986aca59f +--- /dev/null ++++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go +@@ -0,0 +1,18 @@ ++// +build !windows ++ ++package gpgme ++ ++// #include ++import "C" ++import ( ++ "unsafe" ++) ++ ++// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG. ++// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved ++// - and cgo can't be used in tests. So, provide this helper for test initialization. ++func unsetenvGPGAgentInfo() { ++ v := C.CString("GPG_AGENT_INFO") ++ defer C.free(unsafe.Pointer(v)) ++ C.unsetenv(v) ++} +diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go +new file mode 100644 +index 000000000..431ec86d3 +--- /dev/null ++++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go +@@ -0,0 +1,14 @@ ++package gpgme ++ ++// #include ++import "C" ++import ( ++ "unsafe" ++) ++ ++// unsetenv is not available in mingw ++func unsetenvGPGAgentInfo() { ++ v := C.CString("GPG_AGENT_INFO=") ++ defer C.free(unsafe.Pointer(v)) ++ C.putenv(v) ++} diff --git a/SPECS/buildah.spec b/SPECS/buildah.spec index 4ea91b6..6d2d518 100644 --- a/SPECS/buildah.spec +++ b/SPECS/buildah.spec @@ -1,21 +1,16 @@ %global with_debug 1 - -%if 0%{?fedora} || 0%{?rhel} == 6 %global with_bundled 1 -%global with_check 1 -%else -%global with_bundled 0 -%global with_check 0 -%endif %if 0%{?with_debug} +%global _find_debuginfo_dwz_opts %{nil} %global _dwz_low_mem_die_limit 0 %else -%global debug_package %{nil} +%global debug_package %{nil} %endif %if ! 0%{?gobuild:1} -%define gobuild(o:) go build -buildmode pie -compiler gc -tags="rpm_crashtraceback ${BUILDTAGS:-}" -ldflags "${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '" -a -v -x %{?**}; +%define gobuild(o:) \ +scl enable go-toolset-1.12 -- go build -buildmode pie -compiler gc -tags="rpm_crashtraceback ${BUILDTAGS:-}" -ldflags "${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '%__global_ldflags'" -a -v -x %{?**}; %endif %global provider github @@ -25,35 +20,41 @@ # https://github.com/containers/buildah %global import_path %{provider}.%{provider_tld}/%{project}/%{repo} %global git0 https://%{import_path} -%global commit 00eb895d6f2f13d658a9cb78714382e494974afc -%global shortcommit %(c=%{commit}; echo ${c:0:7}) +%global commit0 9513cb8c7bec0f7789c696aee4d252ebf85194cc +%global shortcommit0 %(c=%{commit0}; echo ${c:0:7}) Name: %{repo} -Version: 1.9.0 -Release: 2%{?dist} +Version: 1.11.6 +Release: 8%{?dist} Summary: A command line tool used for creating OCI Images +ExcludeArch: %{ix86} s390 ppc ppc64 License: ASL 2.0 URL: https://%{name}.io -Source: %{git0}/archive/%{commit}/%{name}-%{shortcommit}.tar.gz -ExclusiveArch: aarch64 %{arm} ppc64le s390x x86_64 %{ix86} -%if 0%{?fedora} -BuildRequires: %{?go_compiler:compiler(go-compiler)}%{!?go_compiler:golang} -%else -BuildRequires: go-toolset-1.10 -%endif #fedora -BuildRequires: git -BuildRequires: glib2-devel -BuildRequires: ostree-devel -BuildRequires: glibc-static -BuildRequires: go-md2man -BuildRequires: gpgme-devel -BuildRequires: device-mapper-devel -BuildRequires: btrfs-progs-devel -BuildRequires: libassuan-devel -BuildRequires: libseccomp-devel -Requires: runc >= 1.0.0-59 -Requires: skopeo-containers >= 0.1.20-2 -Requires: container-selinux +Source: %{git0}/archive/%{commit0}/%{name}-%{shortcommit0}.tar.gz +Patch0: buildah-1792243.patch +# related bug: https://bugzilla.redhat.com/show_bug.cgi?id=1784950 +# backported: https://patch-diff.githubusercontent.com/raw/containers/buildah/pull/2031.patch +Patch1: buildah-1784950.patch +Patch2: buildah-1756986.patch +# tracker bug: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2020-8945 +# backported: https://github.com/containers/skopeo/pull/825.patch +Patch3: buildah-CVE-2020-8945.patch + +BuildRequires: go-toolset-1.12 +BuildRequires: git +BuildRequires: glib2-devel +BuildRequires: libseccomp-devel +BuildRequires: ostree-devel +BuildRequires: glibc-static +BuildRequires: go-md2man +BuildRequires: gpgme-devel +BuildRequires: device-mapper-devel +BuildRequires: libassuan-devel +BuildRequires: make +Requires: runc >= 1.0.0-26 +Requires: containers-common +Requires: container-selinux +Requires: slirp4netns >= 0.3-0 %description The %{name} package provides a command line tool which can be used to @@ -64,10 +65,22 @@ or * save container's root file system layer to create a new image * delete a working container or an image -%{?enable_gotoolset110} +%package tests +Summary: Tests for %{name} +Requires: %{name} = %{version}-%{release} +Requires: bzip2 +Requires: podman +Requires: golang + +%description tests +%{summary} + +This package contains system tests for %{name} %prep -%autosetup -Sgit -n %{name}-%{commit} +%autosetup -Sgit -n %{name}-%{commit0} +sed -i 's/GOMD2MAN =/GOMD2MAN ?=/' docs/Makefile +sed -i '/docs install/d' Makefile %build mkdir _build @@ -79,13 +92,20 @@ popd mv vendor src export GOPATH=$(pwd)/_build:$(pwd) -export BUILDTAGS='seccomp selinux' +export BUILDTAGS='seccomp selinux btrfs_noversion exclude_graphdriver_btrfs' +export GO111MODULE=off +rm -f src/github.com/containers/storage/drivers/register/register_btrfs.go %gobuild -o %{name} %{import_path}/cmd/%{name} -%{__make} docs +%gobuild -o imgtype %{import_path}/tests/imgtype +GOMD2MAN=go-md2man %{__make} -C docs %install -export GOPATH=$(pwd)/_build:$(pwd) +export GOPATH=$(pwd)/_build:$(pwd):%{gopath} make DESTDIR=%{buildroot} PREFIX=%{_prefix} install install.completions +install -d -p %{buildroot}/%{_datadir}/%{name}/test/system +cp -pav tests/. %{buildroot}/%{_datadir}/%{name}/test/system +cp imgtype %{buildroot}/%{_bindir}/%{name}-imgtype +make DESTDIR=%{buildroot} PREFIX=%{_prefix} -C docs install #define license tag if not already defined %{!?_licensedir:%global license %doc} @@ -99,7 +119,52 @@ make DESTDIR=%{buildroot} PREFIX=%{_prefix} install install.completions %dir %{_datadir}/bash-completion/completions %{_datadir}/bash-completion/completions/%{name} +%files tests +%license LICENSE +%{_bindir}/%{name}-imgtype +%{_datadir}/%{name}/test + %changelog +* Tue Mar 03 2020 Jindrich Novy - 1.11.6-8 +- fix "CVE-2020-8945 proglottis/gpgme: Use-after-free in GPGME bindings during container image pull" +- Resolves: #1803583 + +* Tue Mar 03 2020 Jindrich Novy - 1.11.6-7 +- fix "CVE-2020-8945 proglottis/gpgme: Use-after-free in GPGME bindings during container image pull" +- Resolves: #1806936 + +* Fri Feb 21 2020 Jindrich Novy - 1.11.6-6 +- Fix "COPY command takes long time with buildah" +- Resolves: #1756986 + +* Wed Feb 19 2020 Jindrich Novy - 1.11.6-5 +- fix "Podman support for FIPS Mode requires a bind mount inside the container" +- Resolves: #1804186 + +* Fri Jan 24 2020 Jindrich Novy - 1.11.6-4 +- resurrect s390x arch as kernel there now has the renameat2 syscall (#1773504) + +* Mon Jan 20 2020 Jindrich Novy - 1.11.6-3 +- Fix thread safety of gpgme (#1792243) + +* Thu Jan 16 2020 Jindrich Novy - 1.11.6-2 +- temporary disable s390x arch due to #1773504 causing fuse-overlayfs + failing to build - skopeo/contaners-common requires it + +* Thu Dec 05 2019 Jindrich Novy - 1.11.6-1 +- update to 1.11.6 +- Related: RHELPLAN-26239 + +* Wed Dec 04 2019 Jindrich Novy - 1.11.5-1 +- update to 1.11.5 +- Related: RHELPLAN-26239 + +* Tue Sep 17 2019 Jindrich Novy - 1.9.0-4 +- Use autosetup macro again. + +* Thu Sep 12 2019 Jindrich Novy - 1.9.0-3 +- Fix CVE-2019-10214. + * Fri Aug 02 2019 Jindrich Novy - 1.9.0-2 - use 1.9.0 in RHEL7u7