加固超级管理员本机重置通道权限校验
Some checks failed
Security Checks / security (push) Has been cancelled

This commit is contained in:
smail 2026-08-28 14:54:23 +08:00
parent dd04bdb49e
commit ce1b557ea9
2 changed files with 66 additions and 2 deletions

View File

@ -91,3 +91,41 @@ func TestUnixEmptyAllowedUIDsRejectConnection(t *testing.T) {
t.Fatalf("response = %+v", response)
}
}
func TestUnixListenRejectsWritableControlDirectory(t *testing.T) {
parent := t.TempDir() + "/control"
if err := os.Mkdir(parent, 0700); err != nil {
t.Fatal(err)
}
if err := os.Chmod(parent, 0777); err != nil {
t.Fatal(err)
}
if _, err := ListenUnix(parent+"/control.sock", []uint32{uint32(os.Getuid())}); err == nil {
t.Fatal("writable control directory was accepted")
}
}
func TestUnixControlSocketUsesRestrictedPermissions(t *testing.T) {
parent := t.TempDir() + "/control"
path := parent + "/control.sock"
server, err := ListenUnix(path, []uint32{uint32(os.Getuid())})
if err != nil {
t.Fatal(err)
}
defer server.Close()
parentInfo, err := os.Stat(parent)
if err != nil {
t.Fatal(err)
}
if parentInfo.Mode().Perm() != 0750 {
t.Fatalf("control directory permissions = %04o, want 0750", parentInfo.Mode().Perm())
}
socketInfo, err := os.Lstat(path)
if err != nil {
t.Fatal(err)
}
if socketInfo.Mode().Perm() != 0600 {
t.Fatalf("control socket permissions = %04o, want 0600", socketInfo.Mode().Perm())
}
}

View File

@ -30,8 +30,8 @@ func ListenUnix(path string, allowedUIDs []uint32) (*UnixServer, error) {
if err := os.MkdirAll(parent, 0750); err != nil {
return nil, fmt.Errorf("create control directory: %w", err)
}
if info, err := os.Lstat(parent); err != nil || info.Mode()&os.ModeSymlink != 0 || !info.IsDir() {
return nil, fmt.Errorf("control directory is not secure")
if err := validateControlDirectory(parent); err != nil {
return nil, err
}
if err := os.Chmod(parent, 0750); err != nil {
return nil, fmt.Errorf("set control directory permissions: %w", err)
@ -40,6 +40,9 @@ func ListenUnix(path string, allowedUIDs []uint32) (*UnixServer, error) {
if info.Mode()&os.ModeSymlink != 0 || info.Mode()&os.ModeSocket == 0 {
return nil, fmt.Errorf("control path is not a socket")
}
if err := validateControlSocketOwner(info); err != nil {
return nil, err
}
if conn, dialErr := net.DialTimeout("unix", path, 100*time.Millisecond); dialErr == nil {
_ = conn.Close()
return nil, fmt.Errorf("control socket is already active")
@ -66,6 +69,29 @@ func ListenUnix(path string, allowedUIDs []uint32) (*UnixServer, error) {
return &UnixServer{listener: listener, path: path, allowed: allowed}, nil
}
func validateControlDirectory(path string) error {
info, err := os.Lstat(path)
if err != nil || info.Mode()&os.ModeSymlink != 0 || !info.IsDir() {
return fmt.Errorf("control directory is not secure")
}
if info.Mode().Perm()&0o022 != 0 {
return fmt.Errorf("control directory must not be writable by group or other users")
}
return validateControlOwner(info, "control directory")
}
func validateControlSocketOwner(info os.FileInfo) error {
return validateControlOwner(info, "control socket")
}
func validateControlOwner(info os.FileInfo, resource string) error {
stat, ok := info.Sys().(*syscall.Stat_t)
if !ok || stat.Uid != uint32(os.Geteuid()) {
return fmt.Errorf("%s owner does not match service identity", resource)
}
return nil
}
func (s *UnixServer) Serve(ctx context.Context, handler ResetHandler, guard *SessionGuard) error {
if s == nil || s.listener == nil || handler == nil || guard == nil {
return ErrInvalidRequest