Support a TMPDIR variable in case /tmp/ is mounted noexec

This commit is contained in:
David Dworken 2022-11-03 18:04:16 -07:00
parent d0ce6efb32
commit 846f256fa4
No known key found for this signature in database
2 changed files with 25 additions and 14 deletions

View File

@ -26,12 +26,15 @@ else:
with urllib.request.urlopen(download_url) as response: with urllib.request.urlopen(download_url) as response:
hishtory_binary = response.read() hishtory_binary = response.read()
if os.path.exists('/tmp/hishtory-client'):
os.remove('/tmp/hishtory-client') tmpdir = os.environ.get('TMPDIR', '') or '/tmp/'
with open('/tmp/hishtory-client', 'wb') as f: tmpFilePath = tmpdir+'hishtory-client'
if os.path.exists(tmpFilePath):
os.remove(tmpFilePath)
with open(tmpFilePath, 'wb') as f:
f.write(hishtory_binary) f.write(hishtory_binary)
os.system('chmod +x /tmp/hishtory-client') os.system('chmod +x ' + tmpFilePath)
exitCode = os.system('/tmp/hishtory-client install') exitCode = os.system(tmpFilePath + ' install')
if exitCode != 0: if exitCode != 0:
raise Exception("failed to install downloaded hishtory client via `/tmp/hishtory-client install`!") raise Exception("failed to install downloaded hishtory client via `" + tmpFilePath +" install` (is that directory mounted noexec? Consider setting an alternate directory via the TMPDIR environment variable)!")
print('Succesfully installed hishtory! Open a new terminal, try running a command, and then running `hishtory query`.') print('Succesfully installed hishtory! Open a new terminal, try running a command, and then running `hishtory query`.')

View File

@ -922,6 +922,14 @@ func GetDownloadData() (shared.UpdateInfo, error) {
return downloadData, nil return downloadData, nil
} }
func getTmpClientPath() string {
tmpDir := "/tmp/"
if os.Getenv("TMPDIR") != "" {
tmpDir = os.Getenv("TMPDIR")
}
return path.Join(tmpDir, "hishtory-client")
}
func Update(ctx *context.Context) error { func Update(ctx *context.Context) error {
// Download the binary // Download the binary
downloadData, err := GetDownloadData() downloadData, err := GetDownloadData()
@ -940,9 +948,9 @@ func Update(ctx *context.Context) error {
// Verify the SLSA attestation // Verify the SLSA attestation
var slsaError error var slsaError error
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
slsaError = verifyBinaryMac(ctx, "/tmp/hishtory-client", downloadData) slsaError = verifyBinaryMac(ctx, getTmpClientPath(), downloadData)
} else { } else {
slsaError = verifyBinary(ctx, "/tmp/hishtory-client", "/tmp/hishtory-client.intoto.jsonl", downloadData.Version) slsaError = verifyBinary(ctx, getTmpClientPath(), getTmpClientPath()+".intoto.jsonl", downloadData.Version)
} }
if slsaError != nil { if slsaError != nil {
err = handleSlsaFailure(slsaError) err = handleSlsaFailure(slsaError)
@ -961,7 +969,7 @@ func Update(ctx *context.Context) error {
} }
// Install the new one // Install the new one
cmd := exec.Command("chmod", "+x", "/tmp/hishtory-client") cmd := exec.Command("chmod", "+x", getTmpClientPath())
var stdout bytes.Buffer var stdout bytes.Buffer
cmd.Stdout = &stdout cmd.Stdout = &stdout
var stderr bytes.Buffer var stderr bytes.Buffer
@ -970,13 +978,13 @@ func Update(ctx *context.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to chmod +x the update (stdout=%#v, stderr=%#v): %v", stdout.String(), stderr.String(), err) return fmt.Errorf("failed to chmod +x the update (stdout=%#v, stderr=%#v): %v", stdout.String(), stderr.String(), err)
} }
cmd = exec.Command("/tmp/hishtory-client", "install") cmd = exec.Command(getTmpClientPath(), "install")
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
stderr = bytes.Buffer{} stderr = bytes.Buffer{}
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
err = cmd.Run() err = cmd.Run()
if err != nil { if err != nil {
return fmt.Errorf("failed to install update (stderr=%#v): %v", stderr.String(), err) return fmt.Errorf("failed to install update (stderr=%#v), is %s in a noexec directory? (if so, set the TMPDIR environment variable): %v", stderr.String(), getTmpClientPath(), err)
} }
fmt.Printf("Successfully updated hishtory from v0.%s to %s\n", Version, downloadData.Version) fmt.Printf("Successfully updated hishtory from v0.%s to %s\n", Version, downloadData.Version)
return nil return nil
@ -1024,7 +1032,7 @@ func verifyBinaryMac(ctx *context.Context, binaryPath string, downloadData share
} }
// Step 4: Use SLSA to verify the unsigned binary // Step 4: Use SLSA to verify the unsigned binary
return verifyBinary(ctx, unsignedBinaryPath, "/tmp/hishtory-client.intoto.jsonl", downloadData.Version) return verifyBinary(ctx, unsignedBinaryPath, getTmpClientPath()+".intoto.jsonl", downloadData.Version)
} }
func assertIdenticalBinaries(bin1Path, bin2Path string) error { func assertIdenticalBinaries(bin1Path, bin2Path string) error {
@ -1089,11 +1097,11 @@ func downloadFiles(updateInfo shared.UpdateInfo) error {
} else { } else {
return fmt.Errorf("no update info found for GOOS=%s, GOARCH=%s", runtime.GOOS, runtime.GOARCH) return fmt.Errorf("no update info found for GOOS=%s, GOARCH=%s", runtime.GOOS, runtime.GOARCH)
} }
err := downloadFile("/tmp/hishtory-client", clientUrl) err := downloadFile(getTmpClientPath(), clientUrl)
if err != nil { if err != nil {
return err return err
} }
err = downloadFile("/tmp/hishtory-client.intoto.jsonl", clientProvenanceUrl) err = downloadFile(getTmpClientPath()+".intoto.jsonl", clientProvenanceUrl)
if err != nil { if err != nil {
return err return err
} }