-
Notifications
You must be signed in to change notification settings - Fork 68
Fix Lchmod() for Linux+Go1.11 #120
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
Changes from all commits
d2ce1bc
2b69c16
9ab0ec6
94af800
6d0b394
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 |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package driver | ||
|
|
||
| import ( | ||
| "os" | ||
|
|
||
| "golang.org/x/sys/unix" | ||
| ) | ||
|
|
||
| // Lchmod changes the mode of a file not following symlinks. | ||
| func (d *driver) Lchmod(path string, mode os.FileMode) error { | ||
| // On Linux, file mode is not supported for symlinks, | ||
| // and fchmodat() does not support AT_SYMLINK_NOFOLLOW, | ||
| // so symlinks need to be skipped entirely. | ||
| if st, err := os.Stat(path); err == nil && st.Mode()&os.ModeSymlink != 0 { | ||
| return nil | ||
| } | ||
|
Member
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.
Contributor
Author
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. This was my original approach, but then I realized I am changing the behavior that way (as previously the error (like ENOENT or EACCESS) was returned from This code assumes that if
Member
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. ahh, because the
Contributor
Author
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. For one thing, yes. I didn't want to inadvertently open a can of worms. In general it's a problem that is out of scope for this PR. The problem is, some errors returned by continuity come from high-level Go functions (like the ones from Based on the above, it would be good to review and unify errors returned (I am in favor of |
||
|
|
||
| return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // +build darwin freebsd solaris | ||
|
|
||
| package driver | ||
|
|
||
| import ( | ||
| "os" | ||
|
|
||
| "golang.org/x/sys/unix" | ||
| ) | ||
|
|
||
| // Lchmod changes the mode of a file not following symlinks. | ||
| func (d *driver) Lchmod(path string, mode os.FileMode) error { | ||
| return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW) | ||
| } |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
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.
(Perhaps overthinking it, but leaving this here because I learned to never "assume" things 😅)
From https://go-review.googlesource.com/c/go/+/118658
That patch mentions the possibility that in future, other options may actually
become active.
Instead of skipping
sysx.Fchmodat()for symlinks, should we always run it, but check if the returned error was anEOPNOTSUPP, then returnnilif the path was a symlink?Uh oh!
There was an error while loading. Please reload this page.
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.
syscall.Fchmodat()from golang < 1.11 does not return the error (same for unix.Fchmodat() from golang.org/x/sys/unix before golang/sys@c23410a which only landed about a year ago), instead changing the mode for the file that a symlink points to (bad bad bad!). So we can't rely on it returning the proper error, and from the correctness/security standpoint it makes sense to avoid the call.Linux won't support mode for symlinks, ever (I mean, I can't speak for Linus, but it looks like it). The patch being referred to above (https://patchwork.kernel.org/patch/9596301/) only adds flags argument to fchmodat(), for the sake of returning an error in case flags are specified. Even that one didn't made it to the kernel, and it seems to be the 3rd attempt, previous two happened in 2015 (https://groups.google.com/d/msg/linux.kernel/Z2z3_MR2aM8/mFz04xQhZEIJ) and 2014 (https://groups.google.com/d/msg/linux.kernel/8lnkJ-naNRI/QvkfwNih6rcJ).
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.
Please ignore the previous comment; while correct it misses the biggest issue, that is, EOPNOTSUPP is returned always, not just for the symlinks. In other words, calling
Fchmodat()with flags != 0 is useless, it does nothing but returns an error, and it happens for all files, not just symlinks.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.
Thanks for doing the digging; looks like the current approach is best then!