github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/strace/socket.go (about) 1 // Copyright 2018 Google LLC. 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 strace 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/mvdan/u-root-coreutils/pkg/align" 22 "github.com/mvdan/u-root-coreutils/pkg/strace/internal/abi" 23 "github.com/mvdan/u-root-coreutils/pkg/strace/internal/binary" 24 "github.com/mvdan/u-root-coreutils/pkg/ubinary" 25 "golang.org/x/sys/unix" 26 ) 27 28 func cmsghdr(t Task, addr Addr, length uint64, maxBytes uint64) string { 29 if length > maxBytes { 30 return fmt.Sprintf("%#x (error decoding control: invalid length (%d))", addr, length) 31 } 32 33 buf := make([]byte, length) 34 if _, err := t.Read(addr, &buf); err != nil { 35 return fmt.Sprintf("%#x (error decoding control: %v)", addr, err) 36 } 37 38 var strs []string 39 40 for i := 0; i < len(buf); { 41 if i+abi.SizeOfControlMessageHeader > len(buf) { 42 strs = append(strs, "{invalid control message (too short)}") 43 break 44 } 45 46 var h abi.ControlMessageHeader 47 binary.Unmarshal(buf[i:i+abi.SizeOfControlMessageHeader], ubinary.NativeEndian, &h) 48 49 var skipData bool 50 level := "SOL_SOCKET" 51 if h.Level != unix.SOL_SOCKET { 52 skipData = true 53 level = fmt.Sprint(h.Level) 54 } 55 56 typ, ok := abi.ControlMessageType[h.Type] 57 if !ok { 58 skipData = true 59 typ = fmt.Sprint(h.Type) 60 } 61 62 if h.Length > uint64(len(buf)-i) { 63 strs = append(strs, fmt.Sprintf( 64 "{level=%s, type=%s, length=%d, content extends beyond buffer}", 65 level, 66 typ, 67 h.Length, 68 )) 69 break 70 } 71 72 i += abi.SizeOfControlMessageHeader 73 // TODO: uh, what 74 width := archWidth 75 length := int(h.Length) - abi.SizeOfControlMessageHeader 76 77 if skipData { 78 strs = append(strs, fmt.Sprintf("{level=%s, type=%s, length=%d}", level, typ, h.Length)) 79 i += int(align.Up(uint(length), uint(width))) 80 continue 81 } 82 83 switch h.Type { 84 case unix.SCM_RIGHTS: 85 rightsSize := int(align.Down(uint(length), abi.SizeOfControlMessageRight)) 86 87 numRights := rightsSize / abi.SizeOfControlMessageRight 88 fds := make(abi.ControlMessageRights, numRights) 89 binary.Unmarshal(buf[i:i+rightsSize], ubinary.NativeEndian, &fds) 90 91 rights := make([]string, 0, len(fds)) 92 for _, fd := range fds { 93 rights = append(rights, fmt.Sprint(fd)) 94 } 95 96 strs = append(strs, fmt.Sprintf( 97 "{level=%s, type=%s, length=%d, content: %s}", 98 level, 99 typ, 100 h.Length, 101 strings.Join(rights, ","), 102 )) 103 104 case unix.SCM_CREDENTIALS: 105 if length < abi.SizeOfControlMessageCredentials { 106 strs = append(strs, fmt.Sprintf( 107 "{level=%s, type=%s, length=%d, content too short}", 108 level, 109 typ, 110 h.Length, 111 )) 112 break 113 } 114 115 var creds abi.ControlMessageCredentials 116 binary.Unmarshal(buf[i:i+abi.SizeOfControlMessageCredentials], binary.LittleEndian, &creds) 117 118 strs = append(strs, fmt.Sprintf( 119 "{level=%s, type=%s, length=%d, pid: %d, uid: %d, gid: %d}", 120 level, 121 typ, 122 h.Length, 123 creds.PID, 124 creds.UID, 125 creds.GID, 126 )) 127 128 case unix.SO_TIMESTAMP: 129 if length < abi.SizeOfTimeval { 130 strs = append(strs, fmt.Sprintf( 131 "{level=%s, type=%s, length=%d, content too short}", 132 level, 133 typ, 134 h.Length, 135 )) 136 break 137 } 138 139 var tv unix.Timeval 140 binary.Unmarshal(buf[i:i+abi.SizeOfTimeval], ubinary.NativeEndian, &tv) 141 142 strs = append(strs, fmt.Sprintf( 143 "{level=%s, type=%s, length=%d, Sec: %d, Usec: %d}", 144 level, 145 typ, 146 h.Length, 147 tv.Sec, 148 tv.Usec, 149 )) 150 151 default: 152 panic("unreachable") 153 } 154 i += int(align.Up(uint(length), uint(width))) 155 } 156 157 return fmt.Sprintf("%#x %s", addr, strings.Join(strs, ", ")) 158 } 159 160 func msghdr(t Task, addr Addr, printContent bool, maxBytes uint64) string { 161 var msg abi.MessageHeader64 162 if _, err := t.Read(addr, &msg); err != nil { 163 return fmt.Sprintf("%#x (error decoding msghdr: %v)", addr, err) 164 } 165 166 s := fmt.Sprintf( 167 "%#x {name=%#x, namelen=%d, iovecs=%s", 168 addr, 169 msg.Name, 170 msg.NameLen, 171 iovecs(t, Addr(msg.Iov), int(msg.IovLen), printContent, maxBytes), 172 ) 173 if printContent { 174 s = fmt.Sprintf("%s, control={%s}", s, cmsghdr(t, Addr(msg.Control), msg.ControlLen, maxBytes)) 175 } else { 176 s = fmt.Sprintf("%s, control=%#x, control_len=%d", s, msg.Control, msg.ControlLen) 177 } 178 return fmt.Sprintf("%s, flags=%d}", s, msg.Flags) 179 } 180 181 func sockAddr(t Task, addr Addr, length uint32) string { 182 if addr == 0 { 183 return "null" 184 } 185 186 b, err := CaptureAddress(t, addr, length) 187 if err != nil { 188 return fmt.Sprintf("%#x {error reading address: %v}", addr, err) 189 } 190 191 // Extract address family. 192 if len(b) < 2 { 193 return fmt.Sprintf("%#x {address too short: %d bytes}", addr, len(b)) 194 } 195 family := ubinary.NativeEndian.Uint16(b) 196 197 familyStr := abi.SocketFamily.Parse(uint64(family)) 198 199 switch family { 200 case unix.AF_INET, unix.AF_INET6, unix.AF_UNIX: 201 fa, err := GetAddress(t, b) 202 if err != nil { 203 return fmt.Sprintf("%#x {Family: %s, error extracting address: %v}", addr, familyStr, err) 204 } 205 206 if family == unix.AF_UNIX { 207 return fmt.Sprintf("%#x {Family: %s, Addr: %q}", addr, familyStr, fa.Addr) 208 } 209 210 return fmt.Sprintf("%#x {Family: %s, Addr: %#02x, Port: %d}", addr, familyStr, []byte(fa.Addr), fa.Port) 211 case unix.AF_NETLINK: 212 // sa, err := netlink.ExtractSockAddr(b) 213 // if err != nil { 214 return fmt.Sprintf("%#x {Family: %s, error extracting address: %v}", addr, familyStr, err) 215 //} 216 //return fmt.Sprintf("%#x {Family: %s, PortID: %d, Groups: %d}", addr, familyStr, sa.PortID, sa.Groups) 217 default: 218 return fmt.Sprintf("%#x {Family: %s, family addr format unknown}", addr, familyStr) 219 } 220 } 221 222 func postSockAddr(t Task, addr Addr, lengthPtr Addr) string { 223 if addr == 0 { 224 return "null" 225 } 226 227 if lengthPtr == 0 { 228 return fmt.Sprintf("%#x {length null}", addr) 229 } 230 231 l, err := copySockLen(t, lengthPtr) 232 if err != nil { 233 return fmt.Sprintf("%#x {error reading length: %v}", addr, err) 234 } 235 236 return sockAddr(t, addr, l) 237 } 238 239 func copySockLen(t Task, addr Addr) (uint32, error) { 240 // socklen_t is 32-bits. 241 var l uint32 242 _, err := t.Read(addr, &l) 243 return l, err 244 } 245 246 func sockLenPointer(t Task, addr Addr) string { 247 if addr == 0 { 248 return "null" 249 } 250 l, err := copySockLen(t, addr) 251 if err != nil { 252 return fmt.Sprintf("%#x {error reading length: %v}", addr, err) 253 } 254 return fmt.Sprintf("%#x {length=%v}", addr, l) 255 }