fix: add symlink handling in createFirejailedBinary (#108)
All checks were successful
Update alr-git / changelog (push) Successful in 30s
All checks were successful
Update alr-git / changelog (push) Successful in 30s
closes #107 Reviewed-on: #108 Co-authored-by: Maxim Slipenko <no-reply@maxim.slipenko.com> Co-committed-by: Maxim Slipenko <no-reply@maxim.slipenko.com>
This commit is contained in:
@ -28,7 +28,6 @@ import (
|
||||
"github.com/goreleaser/nfpm/v2/files"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/osutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
@ -51,6 +50,92 @@ var binaryDirectories = []string{
|
||||
"/usr/local/bin/",
|
||||
}
|
||||
|
||||
func moveWithSymlinkHandling(src, dst string) error {
|
||||
srcInfo, err := os.Lstat(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get source info: %w", err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
|
||||
return fmt.Errorf("failed to create destination directory: %w", err)
|
||||
}
|
||||
|
||||
if srcInfo.Mode()&os.ModeSymlink != 0 {
|
||||
return moveSymlink(src, dst)
|
||||
}
|
||||
|
||||
if err := os.Rename(src, dst); err != nil {
|
||||
return copyAndRemove(src, dst)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func moveSymlink(src, dst string) error {
|
||||
target, err := os.Readlink(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read symlink: %w", err)
|
||||
}
|
||||
|
||||
if err := os.Symlink(target, dst); err != nil {
|
||||
return fmt.Errorf("failed to create symlink: %w", err)
|
||||
}
|
||||
|
||||
if err := os.Remove(src); err != nil {
|
||||
os.Remove(dst)
|
||||
return fmt.Errorf("failed to remove original symlink: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyAndRemove(src, dst string) error {
|
||||
srcFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open source: %w", err)
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
dstFile, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create destination: %w", err)
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
if _, err := io.Copy(dstFile, srcFile); err != nil {
|
||||
return fmt.Errorf("failed to copy content: %w", err)
|
||||
}
|
||||
|
||||
srcInfo, err := srcFile.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get source stats: %w", err)
|
||||
}
|
||||
|
||||
if err := dstFile.Chmod(srcInfo.Mode()); err != nil {
|
||||
return fmt.Errorf("failed to set permissions: %w", err)
|
||||
}
|
||||
|
||||
if err := os.Remove(src); err != nil {
|
||||
return fmt.Errorf("failed to remove source: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func moveFileWithErrorHandling(src, dst string) error {
|
||||
err := moveWithSymlinkHandling(src, dst)
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
return fmt.Errorf("permission denied: %w", err)
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("source file does not exist: %w", err)
|
||||
}
|
||||
return fmt.Errorf("failed to move file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyFirejailIntegration(
|
||||
vars *alrsh.Package,
|
||||
dirs types.Directories,
|
||||
@ -143,12 +228,15 @@ func createFirejailedBinary(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := osutils.Move(content.Source, filepath.Join(dirs.PkgDir, origFilePath)); err != nil {
|
||||
if err := moveFileWithErrorHandling(filepath.Join(dirs.PkgDir, content.Destination), filepath.Join(dirs.PkgDir, origFilePath)); err != nil {
|
||||
return nil, fmt.Errorf("failed to move original binary: %w", err)
|
||||
}
|
||||
|
||||
content.Type = "file"
|
||||
content.Source = filepath.Join(dirs.PkgDir, content.Destination)
|
||||
|
||||
// Create wrapper script
|
||||
if err := createWrapperScript(content.Source, origFilePath, dest); err != nil {
|
||||
if err := createWrapperScript(filepath.Join(dirs.PkgDir, content.Destination), origFilePath, dest); err != nil {
|
||||
return nil, fmt.Errorf("failed to create wrapper script: %w", err)
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,10 @@ func TestCreateFirejailedBinary(t *testing.T) {
|
||||
os.MkdirAll(pkgDir, 0o755)
|
||||
os.MkdirAll(scriptDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(tmpDir, "test-binary")
|
||||
binDir := filepath.Join(pkgDir, "usr", "bin")
|
||||
os.MkdirAll(binDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(binDir, "test-binary")
|
||||
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho test"), 0o755)
|
||||
|
||||
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
||||
@ -154,7 +157,7 @@ func TestCreateFirejailedBinary(t *testing.T) {
|
||||
|
||||
content := &files.Content{
|
||||
Source: srcBinary,
|
||||
Destination: "./usr/bin/test-binary",
|
||||
Destination: "/usr/bin/test-binary",
|
||||
Type: "file",
|
||||
}
|
||||
|
||||
@ -172,7 +175,10 @@ func TestCreateFirejailedBinary(t *testing.T) {
|
||||
os.MkdirAll(pkgDir, 0o755)
|
||||
os.MkdirAll(scriptDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(tmpDir, "special-binary")
|
||||
binDir := filepath.Join(pkgDir, "usr", "bin")
|
||||
os.MkdirAll(binDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(binDir, "special-binary")
|
||||
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho special"), 0o755)
|
||||
|
||||
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
||||
@ -191,7 +197,7 @@ func TestCreateFirejailedBinary(t *testing.T) {
|
||||
|
||||
content := &files.Content{
|
||||
Source: srcBinary,
|
||||
Destination: "./usr/bin/special-binary",
|
||||
Destination: "/usr/bin/special-binary",
|
||||
Type: "file",
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ msgstr ""
|
||||
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
|
||||
#: internal/build/firejail.go:59
|
||||
#: internal/build/firejail.go:144
|
||||
msgid "Applying FireJail integration"
|
||||
msgstr ""
|
||||
|
||||
|
@ -12,8 +12,8 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Gtranslator 48.0\n"
|
||||
|
||||
#: build.go:42
|
||||
@ -231,7 +231,7 @@ msgid "AutoReq is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
|
||||
|
||||
#: internal/build/firejail.go:59
|
||||
#: internal/build/firejail.go:144
|
||||
msgid "Applying FireJail integration"
|
||||
msgstr "Применение интеграции FireJail"
|
||||
|
||||
@ -356,8 +356,8 @@ msgid ""
|
||||
"This command is deprecated and would be removed in the future, use \"%s\" "
|
||||
"instead!"
|
||||
msgstr ""
|
||||
"Эта команда устарела и будет удалена в будущем, используйте вместо нее "
|
||||
"\"%s\"!"
|
||||
"Эта команда устарела и будет удалена в будущем, используйте вместо нее \"%s"
|
||||
"\"!"
|
||||
|
||||
#: internal/db/db.go:76
|
||||
msgid "Database version mismatch; resetting"
|
||||
|
Reference in New Issue
Block a user