diff options
author | Nicolas Lacasse <nlacasse@google.com> | 2018-09-14 12:28:43 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-09-14 12:29:46 -0700 |
commit | b84bfa570d76e6979d5cfc40c235ffe74de9f9ca (patch) | |
tree | b4d293d11723538830a00fc333d12e724c23a932 /pkg/sentry/syscalls | |
parent | 0380bcb3a4125723dc5248f70174ff64fb1942a2 (diff) |
Make gVisor hard link check match Linux's.
Linux permits hard-linking if the target is owned by the user OR the target has
Read+Write permission.
PiperOrigin-RevId: 213024613
Change-Id: If642066317b568b99084edd33ee4e8822ec9cbb3
Diffstat (limited to 'pkg/sentry/syscalls')
-rw-r--r-- | pkg/sentry/syscalls/linux/sys_file.go | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go index 3e28d4b8a..97881a1f5 100644 --- a/pkg/sentry/syscalls/linux/sys_file.go +++ b/pkg/sentry/syscalls/linux/sys_file.go @@ -1122,15 +1122,32 @@ func Symlinkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys // // This corresponds to Linux's fs/namei.c:may_linkat. func mayLinkAt(t *kernel.Task, target *fs.Inode) error { + // Linux will impose the following restrictions on hard links only if + // sysctl_protected_hardlinks is enabled. The kernel disables this + // setting by default for backward compatibility (see commit + // 561ec64ae67e), but also recommends that distributions enable it (and + // Debian does: + // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=889098). + // + // gVisor currently behaves as though sysctl_protected_hardlinks is + // always enabled, and thus imposes the following restrictions on hard + // links. + // Technically Linux is more restrictive in 3.11.10 (requires CAP_FOWNER in // root user namespace); this is from the later f2ca379642d7 "namei: permit // linking with CAP_FOWNER in userns". - if !target.CheckOwnership(t) { - return syserror.EPERM + if target.CheckOwnership(t) { + // fs/namei.c:may_linkat: "Source inode owner (or CAP_FOWNER) + // can hardlink all they like." + return nil } - // Check that the target is not a directory and that permissions are okay. - if fs.IsDir(target.StableAttr) || target.CheckPermission(t, fs.PermMask{Read: true, Write: true}) != nil { + // If we are not the owner, then the file must be regular and have + // Read+Write permissions. + if !fs.IsRegular(target.StableAttr) { + return syserror.EPERM + } + if target.CheckPermission(t, fs.PermMask{Read: true, Write: true}) != nil { return syserror.EPERM } |