github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/linux/sys_capability.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package linux 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/abi/linux" 19 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 20 "github.com/SagerNet/gvisor/pkg/sentry/arch" 21 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 22 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 23 "github.com/SagerNet/gvisor/pkg/syserror" 24 ) 25 26 func lookupCaps(t *kernel.Task, tid kernel.ThreadID) (permitted, inheritable, effective auth.CapabilitySet, err error) { 27 if tid < 0 { 28 err = linuxerr.EINVAL 29 return 30 } 31 if tid > 0 { 32 t = t.PIDNamespace().TaskWithID(tid) 33 } 34 if t == nil { 35 err = syserror.ESRCH 36 return 37 } 38 creds := t.Credentials() 39 permitted, inheritable, effective = creds.PermittedCaps, creds.InheritableCaps, creds.EffectiveCaps 40 return 41 } 42 43 // Capget implements Linux syscall capget. 44 func Capget(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 45 hdrAddr := args[0].Pointer() 46 dataAddr := args[1].Pointer() 47 48 var hdr linux.CapUserHeader 49 if _, err := hdr.CopyIn(t, hdrAddr); err != nil { 50 return 0, nil, err 51 } 52 // hdr.Pid doesn't need to be valid if this capget() is a "version probe" 53 // (hdr.Version is unrecognized and dataAddr is null), so we can't do the 54 // lookup yet. 55 switch hdr.Version { 56 case linux.LINUX_CAPABILITY_VERSION_1: 57 if dataAddr == 0 { 58 return 0, nil, nil 59 } 60 p, i, e, err := lookupCaps(t, kernel.ThreadID(hdr.Pid)) 61 if err != nil { 62 return 0, nil, err 63 } 64 data := linux.CapUserData{ 65 Effective: uint32(e), 66 Permitted: uint32(p), 67 Inheritable: uint32(i), 68 } 69 _, err = data.CopyOut(t, dataAddr) 70 return 0, nil, err 71 72 case linux.LINUX_CAPABILITY_VERSION_2, linux.LINUX_CAPABILITY_VERSION_3: 73 if dataAddr == 0 { 74 return 0, nil, nil 75 } 76 p, i, e, err := lookupCaps(t, kernel.ThreadID(hdr.Pid)) 77 if err != nil { 78 return 0, nil, err 79 } 80 data := [2]linux.CapUserData{ 81 { 82 Effective: uint32(e), 83 Permitted: uint32(p), 84 Inheritable: uint32(i), 85 }, 86 { 87 Effective: uint32(e >> 32), 88 Permitted: uint32(p >> 32), 89 Inheritable: uint32(i >> 32), 90 }, 91 } 92 _, err = linux.CopyCapUserDataSliceOut(t, dataAddr, data[:]) 93 return 0, nil, err 94 95 default: 96 hdr.Version = linux.HighestCapabilityVersion 97 if _, err := hdr.CopyOut(t, hdrAddr); err != nil { 98 return 0, nil, err 99 } 100 if dataAddr != 0 { 101 return 0, nil, linuxerr.EINVAL 102 } 103 return 0, nil, nil 104 } 105 } 106 107 // Capset implements Linux syscall capset. 108 func Capset(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 109 hdrAddr := args[0].Pointer() 110 dataAddr := args[1].Pointer() 111 112 var hdr linux.CapUserHeader 113 if _, err := hdr.CopyIn(t, hdrAddr); err != nil { 114 return 0, nil, err 115 } 116 switch hdr.Version { 117 case linux.LINUX_CAPABILITY_VERSION_1: 118 if tid := kernel.ThreadID(hdr.Pid); tid != 0 && tid != t.ThreadID() { 119 return 0, nil, linuxerr.EPERM 120 } 121 var data linux.CapUserData 122 if _, err := data.CopyIn(t, dataAddr); err != nil { 123 return 0, nil, err 124 } 125 p := auth.CapabilitySet(data.Permitted) & auth.AllCapabilities 126 i := auth.CapabilitySet(data.Inheritable) & auth.AllCapabilities 127 e := auth.CapabilitySet(data.Effective) & auth.AllCapabilities 128 return 0, nil, t.SetCapabilitySets(p, i, e) 129 130 case linux.LINUX_CAPABILITY_VERSION_2, linux.LINUX_CAPABILITY_VERSION_3: 131 if tid := kernel.ThreadID(hdr.Pid); tid != 0 && tid != t.ThreadID() { 132 return 0, nil, linuxerr.EPERM 133 } 134 var data [2]linux.CapUserData 135 if _, err := linux.CopyCapUserDataSliceIn(t, dataAddr, data[:]); err != nil { 136 return 0, nil, err 137 } 138 p := (auth.CapabilitySet(data[0].Permitted) | (auth.CapabilitySet(data[1].Permitted) << 32)) & auth.AllCapabilities 139 i := (auth.CapabilitySet(data[0].Inheritable) | (auth.CapabilitySet(data[1].Inheritable) << 32)) & auth.AllCapabilities 140 e := (auth.CapabilitySet(data[0].Effective) | (auth.CapabilitySet(data[1].Effective) << 32)) & auth.AllCapabilities 141 return 0, nil, t.SetCapabilitySets(p, i, e) 142 143 default: 144 hdr.Version = linux.HighestCapabilityVersion 145 if _, err := hdr.CopyOut(t, hdrAddr); err != nil { 146 return 0, nil, err 147 } 148 return 0, nil, linuxerr.EINVAL 149 } 150 }