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  }