github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/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/nicocha30/gvisor-ligolo/pkg/abi/linux" 19 "github.com/nicocha30/gvisor-ligolo/pkg/errors/linuxerr" 20 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/arch" 21 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel" 22 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel/auth" 23 ) 24 25 func lookupCaps(t *kernel.Task, tid kernel.ThreadID) (permitted, inheritable, effective auth.CapabilitySet, err error) { 26 if tid < 0 { 27 err = linuxerr.EINVAL 28 return 29 } 30 if tid > 0 { 31 t = t.PIDNamespace().TaskWithID(tid) 32 } 33 if t == nil { 34 err = linuxerr.ESRCH 35 return 36 } 37 creds := t.Credentials() 38 permitted, inheritable, effective = creds.PermittedCaps, creds.InheritableCaps, creds.EffectiveCaps 39 return 40 } 41 42 // Capget implements Linux syscall capget. 43 func Capget(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 44 hdrAddr := args[0].Pointer() 45 dataAddr := args[1].Pointer() 46 47 var hdr linux.CapUserHeader 48 if _, err := hdr.CopyIn(t, hdrAddr); err != nil { 49 return 0, nil, err 50 } 51 // hdr.Pid doesn't need to be valid if this capget() is a "version probe" 52 // (hdr.Version is unrecognized and dataAddr is null), so we can't do the 53 // lookup yet. 54 switch hdr.Version { 55 case linux.LINUX_CAPABILITY_VERSION_1: 56 if dataAddr == 0 { 57 return 0, nil, nil 58 } 59 p, i, e, err := lookupCaps(t, kernel.ThreadID(hdr.Pid)) 60 if err != nil { 61 return 0, nil, err 62 } 63 data := linux.CapUserData{ 64 Effective: uint32(e), 65 Permitted: uint32(p), 66 Inheritable: uint32(i), 67 } 68 _, err = data.CopyOut(t, dataAddr) 69 return 0, nil, err 70 71 case linux.LINUX_CAPABILITY_VERSION_2, linux.LINUX_CAPABILITY_VERSION_3: 72 if dataAddr == 0 { 73 return 0, nil, nil 74 } 75 p, i, e, err := lookupCaps(t, kernel.ThreadID(hdr.Pid)) 76 if err != nil { 77 return 0, nil, err 78 } 79 data := [2]linux.CapUserData{ 80 { 81 Effective: uint32(e), 82 Permitted: uint32(p), 83 Inheritable: uint32(i), 84 }, 85 { 86 Effective: uint32(e >> 32), 87 Permitted: uint32(p >> 32), 88 Inheritable: uint32(i >> 32), 89 }, 90 } 91 _, err = linux.CopyCapUserDataSliceOut(t, dataAddr, data[:]) 92 return 0, nil, err 93 94 default: 95 hdr.Version = linux.HighestCapabilityVersion 96 if _, err := hdr.CopyOut(t, hdrAddr); err != nil { 97 return 0, nil, err 98 } 99 if dataAddr != 0 { 100 return 0, nil, linuxerr.EINVAL 101 } 102 return 0, nil, nil 103 } 104 } 105 106 // Capset implements Linux syscall capset. 107 func Capset(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 108 hdrAddr := args[0].Pointer() 109 dataAddr := args[1].Pointer() 110 111 var hdr linux.CapUserHeader 112 if _, err := hdr.CopyIn(t, hdrAddr); err != nil { 113 return 0, nil, err 114 } 115 switch hdr.Version { 116 case linux.LINUX_CAPABILITY_VERSION_1: 117 if tid := kernel.ThreadID(hdr.Pid); tid != 0 && tid != t.ThreadID() { 118 return 0, nil, linuxerr.EPERM 119 } 120 var data linux.CapUserData 121 if _, err := data.CopyIn(t, dataAddr); err != nil { 122 return 0, nil, err 123 } 124 p := auth.CapabilitySet(data.Permitted) & auth.AllCapabilities 125 i := auth.CapabilitySet(data.Inheritable) & auth.AllCapabilities 126 e := auth.CapabilitySet(data.Effective) & auth.AllCapabilities 127 return 0, nil, t.SetCapabilitySets(p, i, e) 128 129 case linux.LINUX_CAPABILITY_VERSION_2, linux.LINUX_CAPABILITY_VERSION_3: 130 if tid := kernel.ThreadID(hdr.Pid); tid != 0 && tid != t.ThreadID() { 131 return 0, nil, linuxerr.EPERM 132 } 133 var data [2]linux.CapUserData 134 if _, err := linux.CopyCapUserDataSliceIn(t, dataAddr, data[:]); err != nil { 135 return 0, nil, err 136 } 137 p := (auth.CapabilitySet(data[0].Permitted) | (auth.CapabilitySet(data[1].Permitted) << 32)) & auth.AllCapabilities 138 i := (auth.CapabilitySet(data[0].Inheritable) | (auth.CapabilitySet(data[1].Inheritable) << 32)) & auth.AllCapabilities 139 e := (auth.CapabilitySet(data[0].Effective) | (auth.CapabilitySet(data[1].Effective) << 32)) & auth.AllCapabilities 140 return 0, nil, t.SetCapabilitySets(p, i, e) 141 142 default: 143 hdr.Version = linux.HighestCapabilityVersion 144 if _, err := hdr.CopyOut(t, hdrAddr); err != nil { 145 return 0, nil, err 146 } 147 return 0, nil, linuxerr.EINVAL 148 } 149 }