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