-
-
Notifications
You must be signed in to change notification settings - Fork 308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix windows permissions #1766
base: develop
Are you sure you want to change the base?
Fix windows permissions #1766
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,15 +2,14 @@ package dataroot | |
|
||
import ( | ||
"errors" | ||
"os" | ||
|
||
"github.com/safing/portmaster/base/utils" | ||
) | ||
|
||
var root *utils.DirStructure | ||
|
||
// Initialize initializes the data root directory. | ||
func Initialize(rootDir string, perm os.FileMode) error { | ||
func Initialize(rootDir string, perm utils.FSPermission) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Update permission value in notifier/main.go to use utils.FSPermission The verification shows that most callers have been updated to use
🔗 Analysis chainVerify all callers of Initialize function The parameter type change from 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for any remaining direct calls using os.FileMode
rg -A 2 "Initialize\([^,]+,\s*os\."
# Search for all calls to Initialize to verify they've been updated
rg -A 2 "dataroot\.Initialize\("
Length of output: 897 |
||
if root != nil { | ||
return errors.New("already initialized") | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -14,10 +14,10 @@ import ( | |||||
"path/filepath" | ||||||
"time" | ||||||
|
||||||
"github.com/hectane/go-acl" | ||||||
"github.com/safing/jess/filesig" | ||||||
"github.com/safing/jess/lhash" | ||||||
"github.com/safing/portmaster/base/log" | ||||||
"github.com/safing/portmaster/base/utils" | ||||||
"github.com/safing/portmaster/base/utils/renameio" | ||||||
) | ||||||
|
||||||
|
@@ -137,17 +137,10 @@ func (reg *ResourceRegistry) fetchFile(ctx context.Context, client *http.Client, | |||||
return fmt.Errorf("%s: failed to finalize file %s: %w", reg.Name, rv.storagePath(), err) | ||||||
} | ||||||
// set permissions | ||||||
if onWindows { | ||||||
err = acl.Chmod(rv.storagePath(), 0o0755) | ||||||
if err != nil { | ||||||
log.Warningf("%s: failed to set permissions on downloaded file %s: %s", reg.Name, rv.storagePath(), err) | ||||||
} | ||||||
} else { | ||||||
// TODO: only set executable files to 0755, set other to 0644 | ||||||
err = os.Chmod(rv.storagePath(), 0o0755) //nolint:gosec // See TODO above. | ||||||
if err != nil { | ||||||
log.Warningf("%s: failed to set permissions on downloaded file %s: %s", reg.Name, rv.storagePath(), err) | ||||||
} | ||||||
// TODO: distinguish between executable and non executable files. | ||||||
err = utils.SetExecPermission(rv.storagePath(), utils.PublicReadPermission) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function
Suggested change
Copilot is powered by AI, so mistakes are possible. Review output carefully before use. |
||||||
if err != nil { | ||||||
log.Warningf("%s: failed to set permissions on downloaded file %s: %s", reg.Name, rv.storagePath(), err) | ||||||
Comment on lines
+140
to
+143
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Let me analyze the current findings and generate a final response based on the code search results. Executable detection should be based on file extension and platform The codebase already has platform-specific handling for executables, particularly for Windows (
Suggested improvements:
🔗 Analysis chainConsider implementing TODO for executable detection. The current implementation sets execution permissions on all files, but the TODO suggests a need for differentiation. This could be important for security and functionality. Consider implementing the following improvements:
🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Check current file types and their permissions
# Test: Look for patterns that could help identify executable files
# Check file extensions of resources
rg "NewResource\(" -A 3
# Check for existing executable detection logic
rg -g "*.go" "executable|\.exe"
Length of output: 37839 |
||||||
} | ||||||
|
||||||
log.Debugf("%s: fetched %s and stored to %s", reg.Name, downloadURL, rv.storagePath()) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//go:build !windows | ||
|
||
package utils | ||
|
||
import "os" | ||
|
||
// SetDirPermission sets the permission of a directory. | ||
func SetDirPermission(path string, perm FSPermission) error { | ||
return os.Chmod(path, perm.AsUnixDirExecPermission()) | ||
} | ||
|
||
// SetExecPermission sets the permission of an executable file. | ||
func SetExecPermission(path string, perm FSPermission) error { | ||
return SetDirPermission(path, perm) | ||
} | ||
|
||
// SetFilePermission sets the permission of a non executable file. | ||
func SetFilePermission(path string, perm FSPermission) error { | ||
return os.Chmod(path, perm.AsUnixFilePermission()) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
//go:build windows | ||
|
||
package utils | ||
|
||
import ( | ||
"github.com/hectane/go-acl" | ||
"golang.org/x/sys/windows" | ||
) | ||
|
||
var ( | ||
systemSID *windows.SID | ||
adminsSID *windows.SID | ||
usersSID *windows.SID | ||
) | ||
|
||
func init() { | ||
var err error | ||
systemSID, err = windows.StringToSid("S-1-5") // NT Authority / SYSTEM | ||
if err != nil { | ||
panic(err) | ||
} | ||
adminsSID, err = windows.StringToSid("S-1-5-32-544") // Administrators | ||
if err != nil { | ||
panic(err) | ||
} | ||
usersSID, err = windows.StringToSid("S-1-5-32-545") // Users | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Improve error handling and variable scope Several improvements are needed in the initialization code:
Consider this safer implementation: -var (
+var (
- systemSID *windows.SID
- adminsSID *windows.SID
- usersSID *windows.SID
+ systemSID *windows.SID
+ adminsSID *windows.SID
+ usersSID *windows.SID
+ initErr error
)
+// validateSID checks if the provided SID string is valid
+func validateSID(sidStr string) bool {
+ sid, err := windows.StringToSid(sidStr)
+ return err == nil && sid != nil
+}
func init() {
- var err error
+ // Validate SID strings first
+ if !validateSID("S-1-5") || !validateSID("S-1-5-32-544") || !validateSID("S-1-5-32-545") {
+ initErr = fmt.Errorf("invalid SID string")
+ return
+ }
systemSID, err = windows.StringToSid("S-1-5") // NT Authority / SYSTEM
if err != nil {
- panic(err)
+ initErr = fmt.Errorf("failed to initialize system SID: %w", err)
+ return
}
// ... similar changes for other SIDs
}
+// ensureInitialized checks if initialization was successful
+func ensureInitialized() error {
+ if initErr != nil {
+ return fmt.Errorf("windows permissions not properly initialized: %w", initErr)
+ }
+ return nil
+}
|
||
|
||
// SetDirPermission sets the permission of a directory. | ||
func SetDirPermission(path string, perm FSPermission) error { | ||
SetFilePermission(path, perm) | ||
return nil | ||
} | ||
|
||
// SetExecPermission sets the permission of an executable file. | ||
func SetExecPermission(path string, perm FSPermission) error { | ||
SetFilePermission(path, perm) | ||
return nil | ||
} | ||
Comment on lines
+34
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor duplicate functions
Consider this implementation: -func SetDirPermission(path string, perm FSPermission) error {
- SetFilePermission(path, perm)
- return nil
-}
-
-func SetExecPermission(path string, perm FSPermission) error {
- SetFilePermission(path, perm)
- return nil
-}
+// FileType represents the type of file being secured
+type FileType int
+
+const (
+ TypeDirectory FileType = iota
+ TypeExecutable
+ TypeRegularFile
+)
+
+func SetPermission(path string, perm FSPermission, fileType FileType) error {
+ if err := ensureInitialized(); err != nil {
+ return err
+ }
+
+ // Add file type specific handling if needed
+ switch fileType {
+ case TypeDirectory:
+ // Directory specific checks/handling
+ case TypeExecutable:
+ // Executable specific checks/handling
+ }
+
+ return setFilePermission(path, perm)
+}
|
||
|
||
// SetFilePermission sets the permission of a non executable file. | ||
func SetFilePermission(path string, perm FSPermission) { | ||
switch perm { | ||
case AdminOnlyPermission: | ||
// Set only admin rights, remove all others. | ||
acl.Apply( | ||
path, | ||
true, | ||
false, | ||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, systemSID), | ||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, adminsSID), | ||
) | ||
case PublicReadPermission: | ||
// Set admin rights and read/execute rights for users, remove all others. | ||
acl.Apply( | ||
path, | ||
true, | ||
false, | ||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, systemSID), | ||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, adminsSID), | ||
acl.GrantSid(windows.GENERIC_READ|windows.GENERIC_EXECUTE, usersSID), | ||
) | ||
case PublicWritePermission: | ||
// Set full control to admin and regular users. Guest users will not have access. | ||
acl.Apply( | ||
path, | ||
true, | ||
false, | ||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, systemSID), | ||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, adminsSID), | ||
acl.GrantSid(windows.GENERIC_ALL|windows.STANDARD_RIGHTS_ALL, usersSID), | ||
) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider implementing Windows-specific permission handling.
The TODO comment correctly identifies that Windows requires the full path for setting permissions. Consider implementing this using the Windows-specific APIs from the
go-acl
package that's already imported.Here's a suggested implementation: