github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/syscalls/linux/sys_key.go (about) 1 // Copyright 2023 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 "fmt" 19 "math" 20 21 "github.com/metacubex/gvisor/pkg/abi/linux" 22 "github.com/metacubex/gvisor/pkg/errors/linuxerr" 23 "github.com/metacubex/gvisor/pkg/log" 24 "github.com/metacubex/gvisor/pkg/sentry/arch" 25 "github.com/metacubex/gvisor/pkg/sentry/kernel" 26 "github.com/metacubex/gvisor/pkg/sentry/kernel/auth" 27 ) 28 29 // Keyctl implements Linux syscall keyctl(2). 30 func Keyctl(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 31 switch args[0].Int() { 32 case linux.KEYCTL_GET_KEYRING_ID: 33 return keyCtlGetKeyringID(t, args) 34 case linux.KEYCTL_DESCRIBE: 35 return keyctlDescribe(t, args) 36 case linux.KEYCTL_JOIN_SESSION_KEYRING: 37 return keyctlJoinSessionKeyring(t, args) 38 case linux.KEYCTL_SETPERM: 39 return keyctlSetPerm(t, args) 40 } 41 log.Debugf("Unimplemented keyctl operation: %d", args[0].Int()) 42 kernel.IncrementUnimplementedSyscallCounter(sysno) 43 return 0, nil, linuxerr.ENOSYS 44 } 45 46 // keyCtlGetKeyringID implements keyctl(2) with operation 47 // KEYCTL_GET_KEYRING_ID. 48 func keyCtlGetKeyringID(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 49 keyID := auth.KeySerial(args[1].Int()) 50 var key *auth.Key 51 var err error 52 if keyID > 0 { 53 // Not a special key ID, so return as-is. 54 return uintptr(keyID), nil, nil 55 } 56 switch keyID { 57 case linux.KEY_SPEC_SESSION_KEYRING: 58 key, err = t.SessionKeyring() 59 default: 60 if keyID <= 0 { 61 // Other special key IDs are not implemented. 62 return 0, nil, linuxerr.ENOSYS 63 } 64 // For positive key IDs, KEYCTL_GET_KEYRING_ID can be used as an existence 65 // and permissions check. 66 key, err = t.LookupKey(keyID) 67 } 68 if err != nil { 69 return 0, nil, err 70 } 71 return uintptr(key.ID), nil, nil 72 } 73 74 // keyctlDescribe implements keyctl(2) with operation KEYCTL_DESCRIBE. 75 func keyctlDescribe(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 76 keyID := auth.KeySerial(args[1].Int()) 77 bufPtr := args[2].Pointer() 78 bufSize := args[3].SizeT() 79 80 // Get address range to write to. 81 if bufSize > math.MaxInt32 { 82 bufSize = math.MaxInt32 83 } 84 85 var key *auth.Key 86 var err error 87 switch keyID { 88 case linux.KEY_SPEC_SESSION_KEYRING: 89 key, err = t.SessionKeyring() 90 default: 91 key, err = t.LookupKey(keyID) 92 } 93 if err != nil { 94 return 0, nil, err 95 } 96 uid := t.UserNamespace().MapFromKUID(key.KUID()) 97 gid := t.UserNamespace().MapFromKGID(key.KGID()) 98 keyDesc := fmt.Sprintf("%s;%d;%d;%08x;%s\x00", key.Type(), uid, gid, uint64(key.Permissions()), key.Description) 99 if bufSize > 0 { 100 toWrite := uint(len(keyDesc)) 101 if toWrite > bufSize { 102 toWrite = bufSize 103 } 104 _, err = t.CopyOutBytes(bufPtr, []byte(keyDesc)[:toWrite]) 105 } 106 // The KEYCTL_DESCRIBE operation returns the length of the full string, 107 // regardless of whether or not it was fully written out to userspace. 108 // It includes the zero byte at the end in the returned length. 109 return uintptr(len(keyDesc)), nil, err 110 } 111 112 // keyctlJoinSessionKeyring implements keyctl(2) with operation 113 // KEYCTL_JOIN_SESSION_KEYRING. 114 func keyctlJoinSessionKeyring(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 115 keyDescPtr := args[1].Pointer() 116 var key *auth.Key 117 var err error 118 if keyDescPtr == 0 { 119 // Creating an anonymous keyring. 120 key, err = t.JoinSessionKeyring(nil) 121 } else { 122 // Joining a named keyring. Read in its description. 123 var keyringDesc string 124 keyringDesc, err = t.CopyInString(keyDescPtr, auth.MaxKeyDescSize) 125 if err != nil { 126 return 0, nil, err 127 } 128 key, err = t.JoinSessionKeyring(&keyringDesc) 129 } 130 if err != nil { 131 return 0, nil, err 132 } 133 return uintptr(key.ID), nil, nil 134 } 135 136 // keyctlSetPerm implements keyctl(2) with operation KEYCTL_SETPERM. 137 func keyctlSetPerm(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 138 keyID := auth.KeySerial(args[1].Int()) 139 newPerms := auth.KeyPermissions(args[2].Uint64()) 140 var key *auth.Key 141 var err error 142 switch keyID { 143 case linux.KEY_SPEC_SESSION_KEYRING: 144 key, err = t.SessionKeyring() 145 default: 146 key, err = t.UserNamespace().Keys.Lookup(keyID) 147 } 148 if err != nil { 149 return 0, nil, err 150 } 151 return 0, nil, t.SetPermsOnKey(key, newPerms) 152 }