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