Skip to content
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

interp: fix cd builtin: call a system function to determine access instead of reverse-engineering it ourselves #1034

Merged
merged 4 commits into from
Sep 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion interp/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ func (r *Runner) changeDir(ctx context.Context, path string) int {
if err != nil || !info.IsDir() {
return 1
}
if !hasPermissionToDir(info) {
if !hasPermissionToDir(path) {
return 1
}
r.Dir = path
Expand Down
3 changes: 1 addition & 2 deletions interp/os_notunix.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ package interp

import (
"fmt"
"os"
)

func mkfifo(path string, mode uint32) error {
return fmt.Errorf("unsupported")
}

// hasPermissionToDir is a no-op on Windows.
func hasPermissionToDir(info os.FileInfo) bool {
func hasPermissionToDir(string) bool {
return true
}
45 changes: 4 additions & 41 deletions interp/os_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,15 @@
package interp

import (
"os"
"os/user"
"strconv"
"syscall"

"golang.org/x/sys/unix"
)

func mkfifo(path string, mode uint32) error {
return unix.Mkfifo(path, mode)
}

// hasPermissionToDir returns if the OS current user has execute permission
// to the given directory
func hasPermissionToDir(info os.FileInfo) bool {
user, err := user.Current()
if err != nil {
return false // unknown user; assume no permissions
}
uid, err := strconv.Atoi(user.Uid)
if err != nil {
return false // on POSIX systems, Uid should always be a decimal number
}
if uid == 0 {
return true // super-user
}

st, _ := info.Sys().(*syscall.Stat_t)
if st == nil {
panic("unexpected info.Sys type")
}
perm := info.Mode().Perm()
// user (u)
if perm&0o100 != 0 && st.Uid == uint32(uid) {
return true
}

gid, _ := strconv.Atoi(user.Gid)
// other users in group (g)
if perm&0o010 != 0 && st.Uid != uint32(uid) && st.Gid == uint32(gid) {
return true
}
// remaining users (o)
if perm&0o001 != 0 && st.Uid != uint32(uid) && st.Gid != uint32(gid) {
return true
}

return false
// hasPermissionToDir returns true if the OS current user has execute
// permission to the given directory
func hasPermissionToDir(path string) bool {
return unix.Access(path, unix.X_OK) == nil
}