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/goreleaser/nfpm/v2/files"
|
||||||
"github.com/leonelquinteros/gotext"
|
"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/alrsh"
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||||
)
|
)
|
||||||
@ -51,6 +50,92 @@ var binaryDirectories = []string{
|
|||||||
"/usr/local/bin/",
|
"/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(
|
func applyFirejailIntegration(
|
||||||
vars *alrsh.Package,
|
vars *alrsh.Package,
|
||||||
dirs types.Directories,
|
dirs types.Directories,
|
||||||
@ -143,12 +228,15 @@ func createFirejailedBinary(
|
|||||||
return nil, err
|
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)
|
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
|
// 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)
|
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(pkgDir, 0o755)
|
||||||
os.MkdirAll(scriptDir, 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)
|
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho test"), 0o755)
|
||||||
|
|
||||||
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
||||||
@ -154,7 +157,7 @@ func TestCreateFirejailedBinary(t *testing.T) {
|
|||||||
|
|
||||||
content := &files.Content{
|
content := &files.Content{
|
||||||
Source: srcBinary,
|
Source: srcBinary,
|
||||||
Destination: "./usr/bin/test-binary",
|
Destination: "/usr/bin/test-binary",
|
||||||
Type: "file",
|
Type: "file",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +175,10 @@ func TestCreateFirejailedBinary(t *testing.T) {
|
|||||||
os.MkdirAll(pkgDir, 0o755)
|
os.MkdirAll(pkgDir, 0o755)
|
||||||
os.MkdirAll(scriptDir, 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)
|
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho special"), 0o755)
|
||||||
|
|
||||||
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
||||||
@ -191,7 +197,7 @@ func TestCreateFirejailedBinary(t *testing.T) {
|
|||||||
|
|
||||||
content := &files.Content{
|
content := &files.Content{
|
||||||
Source: srcBinary,
|
Source: srcBinary,
|
||||||
Destination: "./usr/bin/special-binary",
|
Destination: "/usr/bin/special-binary",
|
||||||
Type: "file",
|
Type: "file",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ msgstr ""
|
|||||||
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: internal/build/firejail.go:59
|
#: internal/build/firejail.go:144
|
||||||
msgid "Applying FireJail integration"
|
msgid "Applying FireJail integration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ msgstr ""
|
|||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||||
"X-Generator: Gtranslator 48.0\n"
|
"X-Generator: Gtranslator 48.0\n"
|
||||||
|
|
||||||
#: build.go:42
|
#: build.go:42
|
||||||
@ -231,7 +231,7 @@ msgid "AutoReq is not implemented for this package format, so it's skipped"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
|
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
|
||||||
|
|
||||||
#: internal/build/firejail.go:59
|
#: internal/build/firejail.go:144
|
||||||
msgid "Applying FireJail integration"
|
msgid "Applying FireJail integration"
|
||||||
msgstr "Применение интеграции FireJail"
|
msgstr "Применение интеграции FireJail"
|
||||||
|
|
||||||
@ -356,8 +356,8 @@ msgid ""
|
|||||||
"This command is deprecated and would be removed in the future, use \"%s\" "
|
"This command is deprecated and would be removed in the future, use \"%s\" "
|
||||||
"instead!"
|
"instead!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Эта команда устарела и будет удалена в будущем, используйте вместо нее "
|
"Эта команда устарела и будет удалена в будущем, используйте вместо нее \"%s"
|
||||||
"\"%s\"!"
|
"\"!"
|
||||||
|
|
||||||
#: internal/db/db.go:76
|
#: internal/db/db.go:76
|
||||||
msgid "Database version mismatch; resetting"
|
msgid "Database version mismatch; resetting"
|
||||||
|
Reference in New Issue
Block a user