github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/control/control.go (about)

     1  // Copyright 2018 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 control provides internal representations of socket control
    16  // messages.
    17  package control
    18  
    19  import (
    20  	"github.com/SagerNet/gvisor/pkg/abi/linux"
    21  	"github.com/SagerNet/gvisor/pkg/bits"
    22  	"github.com/SagerNet/gvisor/pkg/context"
    23  	"github.com/SagerNet/gvisor/pkg/errors/linuxerr"
    24  	"github.com/SagerNet/gvisor/pkg/hostarch"
    25  	"github.com/SagerNet/gvisor/pkg/marshal"
    26  	"github.com/SagerNet/gvisor/pkg/marshal/primitive"
    27  	"github.com/SagerNet/gvisor/pkg/sentry/fs"
    28  	"github.com/SagerNet/gvisor/pkg/sentry/kernel"
    29  	"github.com/SagerNet/gvisor/pkg/sentry/kernel/auth"
    30  	"github.com/SagerNet/gvisor/pkg/sentry/socket"
    31  	"github.com/SagerNet/gvisor/pkg/sentry/socket/unix/transport"
    32  )
    33  
    34  const maxInt = int(^uint(0) >> 1)
    35  
    36  // SCMCredentials represents a SCM_CREDENTIALS socket control message.
    37  type SCMCredentials interface {
    38  	transport.CredentialsControlMessage
    39  
    40  	// Credentials returns properly namespaced values for the sender's pid, uid
    41  	// and gid.
    42  	Credentials(t *kernel.Task) (kernel.ThreadID, auth.UID, auth.GID)
    43  }
    44  
    45  // LINT.IfChange
    46  
    47  // SCMRights represents a SCM_RIGHTS socket control message.
    48  type SCMRights interface {
    49  	transport.RightsControlMessage
    50  
    51  	// Files returns up to max RightsFiles.
    52  	//
    53  	// Returned files are consumed and ownership is transferred to the caller.
    54  	// Subsequent calls to Files will return the next files.
    55  	Files(ctx context.Context, max int) (rf RightsFiles, truncated bool)
    56  }
    57  
    58  // RightsFiles represents a SCM_RIGHTS socket control message. A reference is
    59  // maintained for each fs.File and is release either when an FD is created or
    60  // when the Release method is called.
    61  //
    62  // +stateify savable
    63  type RightsFiles []*fs.File
    64  
    65  // NewSCMRights creates a new SCM_RIGHTS socket control message representation
    66  // using local sentry FDs.
    67  func NewSCMRights(t *kernel.Task, fds []int32) (SCMRights, error) {
    68  	files := make(RightsFiles, 0, len(fds))
    69  	for _, fd := range fds {
    70  		file := t.GetFile(fd)
    71  		if file == nil {
    72  			files.Release(t)
    73  			return nil, linuxerr.EBADF
    74  		}
    75  		files = append(files, file)
    76  	}
    77  	return &files, nil
    78  }
    79  
    80  // Files implements SCMRights.Files.
    81  func (fs *RightsFiles) Files(ctx context.Context, max int) (RightsFiles, bool) {
    82  	n := max
    83  	var trunc bool
    84  	if l := len(*fs); n > l {
    85  		n = l
    86  	} else if n < l {
    87  		trunc = true
    88  	}
    89  	rf := (*fs)[:n]
    90  	*fs = (*fs)[n:]
    91  	return rf, trunc
    92  }
    93  
    94  // Clone implements transport.RightsControlMessage.Clone.
    95  func (fs *RightsFiles) Clone() transport.RightsControlMessage {
    96  	nfs := append(RightsFiles(nil), *fs...)
    97  	for _, nf := range nfs {
    98  		nf.IncRef()
    99  	}
   100  	return &nfs
   101  }
   102  
   103  // Release implements transport.RightsControlMessage.Release.
   104  func (fs *RightsFiles) Release(ctx context.Context) {
   105  	for _, f := range *fs {
   106  		f.DecRef(ctx)
   107  	}
   108  	*fs = nil
   109  }
   110  
   111  // rightsFDs gets up to the specified maximum number of FDs.
   112  func rightsFDs(t *kernel.Task, rights SCMRights, cloexec bool, max int) ([]int32, bool) {
   113  	files, trunc := rights.Files(t, max)
   114  	fds := make([]int32, 0, len(files))
   115  	for i := 0; i < max && len(files) > 0; i++ {
   116  		fd, err := t.NewFDFrom(0, files[0], kernel.FDFlags{
   117  			CloseOnExec: cloexec,
   118  		})
   119  		files[0].DecRef(t)
   120  		files = files[1:]
   121  		if err != nil {
   122  			t.Warningf("Error inserting FD: %v", err)
   123  			// This is what Linux does.
   124  			break
   125  		}
   126  
   127  		fds = append(fds, int32(fd))
   128  	}
   129  	return fds, trunc
   130  }
   131  
   132  // PackRights packs as many FDs as will fit into the unused capacity of buf.
   133  func PackRights(t *kernel.Task, rights SCMRights, cloexec bool, buf []byte, flags int) ([]byte, int) {
   134  	maxFDs := (cap(buf) - len(buf) - linux.SizeOfControlMessageHeader) / 4
   135  	// Linux does not return any FDs if none fit.
   136  	if maxFDs <= 0 {
   137  		flags |= linux.MSG_CTRUNC
   138  		return buf, flags
   139  	}
   140  	fds, trunc := rightsFDs(t, rights, cloexec, maxFDs)
   141  	if trunc {
   142  		flags |= linux.MSG_CTRUNC
   143  	}
   144  	align := t.Arch().Width()
   145  	return putCmsg(buf, flags, linux.SCM_RIGHTS, align, fds)
   146  }
   147  
   148  // LINT.ThenChange(./control_vfs2.go)
   149  
   150  // scmCredentials represents an SCM_CREDENTIALS socket control message.
   151  //
   152  // +stateify savable
   153  type scmCredentials struct {
   154  	t    *kernel.Task
   155  	kuid auth.KUID
   156  	kgid auth.KGID
   157  }
   158  
   159  // NewSCMCredentials creates a new SCM_CREDENTIALS socket control message
   160  // representation.
   161  func NewSCMCredentials(t *kernel.Task, cred linux.ControlMessageCredentials) (SCMCredentials, error) {
   162  	tcred := t.Credentials()
   163  	kuid, err := tcred.UseUID(auth.UID(cred.UID))
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	kgid, err := tcred.UseGID(auth.GID(cred.GID))
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  	if kernel.ThreadID(cred.PID) != t.ThreadGroup().ID() && !t.HasCapabilityIn(linux.CAP_SYS_ADMIN, t.PIDNamespace().UserNamespace()) {
   172  		return nil, linuxerr.EPERM
   173  	}
   174  	return &scmCredentials{t, kuid, kgid}, nil
   175  }
   176  
   177  // Equals implements transport.CredentialsControlMessage.Equals.
   178  func (c *scmCredentials) Equals(oc transport.CredentialsControlMessage) bool {
   179  	if oc, _ := oc.(*scmCredentials); oc != nil && *c == *oc {
   180  		return true
   181  	}
   182  	return false
   183  }
   184  
   185  func putUint64(buf []byte, n uint64) []byte {
   186  	hostarch.ByteOrder.PutUint64(buf[len(buf):len(buf)+8], n)
   187  	return buf[:len(buf)+8]
   188  }
   189  
   190  func putUint32(buf []byte, n uint32) []byte {
   191  	hostarch.ByteOrder.PutUint32(buf[len(buf):len(buf)+4], n)
   192  	return buf[:len(buf)+4]
   193  }
   194  
   195  // putCmsg writes a control message header and as much data as will fit into
   196  // the unused capacity of a buffer.
   197  func putCmsg(buf []byte, flags int, msgType uint32, align uint, data []int32) ([]byte, int) {
   198  	space := bits.AlignDown(cap(buf)-len(buf), 4)
   199  
   200  	// We can't write to space that doesn't exist, so if we are going to align
   201  	// the available space, we must align down.
   202  	//
   203  	// align must be >= 4 and each data int32 is 4 bytes. The length of the
   204  	// header is already aligned, so if we align to the width of the data there
   205  	// are two cases:
   206  	// 1. The aligned length is less than the length of the header. The
   207  	// unaligned length was also less than the length of the header, so we
   208  	// can't write anything.
   209  	// 2. The aligned length is greater than or equal to the length of the
   210  	// header. We can write the header plus zero or more bytes of data. We can't
   211  	// write a partial int32, so the length of the message will be
   212  	// min(aligned length, header + data).
   213  	if space < linux.SizeOfControlMessageHeader {
   214  		flags |= linux.MSG_CTRUNC
   215  		return buf, flags
   216  	}
   217  
   218  	length := 4*len(data) + linux.SizeOfControlMessageHeader
   219  	if length > space {
   220  		length = space
   221  	}
   222  	buf = putUint64(buf, uint64(length))
   223  	buf = putUint32(buf, linux.SOL_SOCKET)
   224  	buf = putUint32(buf, msgType)
   225  	for _, d := range data {
   226  		if len(buf)+4 > cap(buf) {
   227  			flags |= linux.MSG_CTRUNC
   228  			break
   229  		}
   230  		buf = putUint32(buf, uint32(d))
   231  	}
   232  	return alignSlice(buf, align), flags
   233  }
   234  
   235  func putCmsgStruct(buf []byte, msgLevel, msgType uint32, align uint, data marshal.Marshallable) []byte {
   236  	if cap(buf)-len(buf) < linux.SizeOfControlMessageHeader {
   237  		return buf
   238  	}
   239  	ob := buf
   240  
   241  	buf = putUint64(buf, uint64(linux.SizeOfControlMessageHeader))
   242  	buf = putUint32(buf, msgLevel)
   243  	buf = putUint32(buf, msgType)
   244  
   245  	hdrBuf := buf
   246  	buf = append(buf, marshal.Marshal(data)...)
   247  
   248  	// If the control message data brought us over capacity, omit it.
   249  	if cap(buf) != cap(ob) {
   250  		return hdrBuf
   251  	}
   252  
   253  	// Update control message length to include data.
   254  	putUint64(ob, uint64(len(buf)-len(ob)))
   255  
   256  	return alignSlice(buf, align)
   257  }
   258  
   259  // Credentials implements SCMCredentials.Credentials.
   260  func (c *scmCredentials) Credentials(t *kernel.Task) (kernel.ThreadID, auth.UID, auth.GID) {
   261  	// "When a process's user and group IDs are passed over a UNIX domain
   262  	// socket to a process in a different user namespace (see the description
   263  	// of SCM_CREDENTIALS in unix(7)), they are translated into the
   264  	// corresponding values as per the receiving process's user and group ID
   265  	// mappings." - user_namespaces(7)
   266  	pid := t.PIDNamespace().IDOfTask(c.t)
   267  	uid := c.kuid.In(t.UserNamespace()).OrOverflow()
   268  	gid := c.kgid.In(t.UserNamespace()).OrOverflow()
   269  
   270  	return pid, uid, gid
   271  }
   272  
   273  // PackCredentials packs the credentials in the control message (or default
   274  // credentials if none) into a buffer.
   275  func PackCredentials(t *kernel.Task, creds SCMCredentials, buf []byte, flags int) ([]byte, int) {
   276  	align := t.Arch().Width()
   277  
   278  	// Default credentials if none are available.
   279  	pid := kernel.ThreadID(0)
   280  	uid := auth.UID(auth.NobodyKUID)
   281  	gid := auth.GID(auth.NobodyKGID)
   282  
   283  	if creds != nil {
   284  		pid, uid, gid = creds.Credentials(t)
   285  	}
   286  	c := []int32{int32(pid), int32(uid), int32(gid)}
   287  	return putCmsg(buf, flags, linux.SCM_CREDENTIALS, align, c)
   288  }
   289  
   290  // alignSlice extends a slice's length (up to the capacity) to align it.
   291  func alignSlice(buf []byte, align uint) []byte {
   292  	aligned := bits.AlignUp(len(buf), align)
   293  	if aligned > cap(buf) {
   294  		// Linux allows unaligned data if there isn't room for alignment.
   295  		// Since there isn't room for alignment, there isn't room for any
   296  		// additional messages either.
   297  		return buf
   298  	}
   299  	return buf[:aligned]
   300  }
   301  
   302  // PackTimestamp packs a SO_TIMESTAMP socket control message.
   303  func PackTimestamp(t *kernel.Task, timestamp int64, buf []byte) []byte {
   304  	timestampP := linux.NsecToTimeval(timestamp)
   305  	return putCmsgStruct(
   306  		buf,
   307  		linux.SOL_SOCKET,
   308  		linux.SO_TIMESTAMP,
   309  		t.Arch().Width(),
   310  		&timestampP,
   311  	)
   312  }
   313  
   314  // PackInq packs a TCP_INQ socket control message.
   315  func PackInq(t *kernel.Task, inq int32, buf []byte) []byte {
   316  	return putCmsgStruct(
   317  		buf,
   318  		linux.SOL_TCP,
   319  		linux.TCP_INQ,
   320  		t.Arch().Width(),
   321  		primitive.AllocateInt32(inq),
   322  	)
   323  }
   324  
   325  // PackTOS packs an IP_TOS socket control message.
   326  func PackTOS(t *kernel.Task, tos uint8, buf []byte) []byte {
   327  	return putCmsgStruct(
   328  		buf,
   329  		linux.SOL_IP,
   330  		linux.IP_TOS,
   331  		t.Arch().Width(),
   332  		primitive.AllocateUint8(tos),
   333  	)
   334  }
   335  
   336  // PackTClass packs an IPV6_TCLASS socket control message.
   337  func PackTClass(t *kernel.Task, tClass uint32, buf []byte) []byte {
   338  	return putCmsgStruct(
   339  		buf,
   340  		linux.SOL_IPV6,
   341  		linux.IPV6_TCLASS,
   342  		t.Arch().Width(),
   343  		primitive.AllocateUint32(tClass),
   344  	)
   345  }
   346  
   347  // PackIPPacketInfo packs an IP_PKTINFO socket control message.
   348  func PackIPPacketInfo(t *kernel.Task, packetInfo *linux.ControlMessageIPPacketInfo, buf []byte) []byte {
   349  	return putCmsgStruct(
   350  		buf,
   351  		linux.SOL_IP,
   352  		linux.IP_PKTINFO,
   353  		t.Arch().Width(),
   354  		packetInfo,
   355  	)
   356  }
   357  
   358  // PackOriginalDstAddress packs an IP_RECVORIGINALDSTADDR socket control message.
   359  func PackOriginalDstAddress(t *kernel.Task, originalDstAddress linux.SockAddr, buf []byte) []byte {
   360  	var level uint32
   361  	var optType uint32
   362  	switch originalDstAddress.(type) {
   363  	case *linux.SockAddrInet:
   364  		level = linux.SOL_IP
   365  		optType = linux.IP_RECVORIGDSTADDR
   366  	case *linux.SockAddrInet6:
   367  		level = linux.SOL_IPV6
   368  		optType = linux.IPV6_RECVORIGDSTADDR
   369  	default:
   370  		panic("invalid address type, must be an IP address for IP_RECVORIGINALDSTADDR cmsg")
   371  	}
   372  	return putCmsgStruct(
   373  		buf, level, optType, t.Arch().Width(), originalDstAddress)
   374  }
   375  
   376  // PackSockExtendedErr packs an IP*_RECVERR socket control message.
   377  func PackSockExtendedErr(t *kernel.Task, sockErr linux.SockErrCMsg, buf []byte) []byte {
   378  	return putCmsgStruct(
   379  		buf,
   380  		sockErr.CMsgLevel(),
   381  		sockErr.CMsgType(),
   382  		t.Arch().Width(),
   383  		sockErr,
   384  	)
   385  }
   386  
   387  // PackControlMessages packs control messages into the given buffer.
   388  //
   389  // We skip control messages specific to Unix domain sockets.
   390  //
   391  // Note that some control messages may be truncated if they do not fit under
   392  // the capacity of buf.
   393  func PackControlMessages(t *kernel.Task, cmsgs socket.ControlMessages, buf []byte) []byte {
   394  	if cmsgs.IP.HasTimestamp {
   395  		buf = PackTimestamp(t, cmsgs.IP.Timestamp, buf)
   396  	}
   397  
   398  	if cmsgs.IP.HasInq {
   399  		// In Linux, TCP_CM_INQ is added after SO_TIMESTAMP.
   400  		buf = PackInq(t, cmsgs.IP.Inq, buf)
   401  	}
   402  
   403  	if cmsgs.IP.HasTOS {
   404  		buf = PackTOS(t, cmsgs.IP.TOS, buf)
   405  	}
   406  
   407  	if cmsgs.IP.HasTClass {
   408  		buf = PackTClass(t, cmsgs.IP.TClass, buf)
   409  	}
   410  
   411  	if cmsgs.IP.HasIPPacketInfo {
   412  		buf = PackIPPacketInfo(t, &cmsgs.IP.PacketInfo, buf)
   413  	}
   414  
   415  	if cmsgs.IP.OriginalDstAddress != nil {
   416  		buf = PackOriginalDstAddress(t, cmsgs.IP.OriginalDstAddress, buf)
   417  	}
   418  
   419  	if cmsgs.IP.SockErr != nil {
   420  		buf = PackSockExtendedErr(t, cmsgs.IP.SockErr, buf)
   421  	}
   422  
   423  	return buf
   424  }
   425  
   426  // cmsgSpace is equivalent to CMSG_SPACE in Linux.
   427  func cmsgSpace(t *kernel.Task, dataLen int) int {
   428  	return linux.SizeOfControlMessageHeader + bits.AlignUp(dataLen, t.Arch().Width())
   429  }
   430  
   431  // CmsgsSpace returns the number of bytes needed to fit the control messages
   432  // represented in cmsgs.
   433  func CmsgsSpace(t *kernel.Task, cmsgs socket.ControlMessages) int {
   434  	space := 0
   435  
   436  	if cmsgs.IP.HasTimestamp {
   437  		space += cmsgSpace(t, linux.SizeOfTimeval)
   438  	}
   439  
   440  	if cmsgs.IP.HasInq {
   441  		space += cmsgSpace(t, linux.SizeOfControlMessageInq)
   442  	}
   443  
   444  	if cmsgs.IP.HasTOS {
   445  		space += cmsgSpace(t, linux.SizeOfControlMessageTOS)
   446  	}
   447  
   448  	if cmsgs.IP.HasTClass {
   449  		space += cmsgSpace(t, linux.SizeOfControlMessageTClass)
   450  	}
   451  
   452  	if cmsgs.IP.HasIPPacketInfo {
   453  		space += cmsgSpace(t, linux.SizeOfControlMessageIPPacketInfo)
   454  	}
   455  
   456  	if cmsgs.IP.OriginalDstAddress != nil {
   457  		space += cmsgSpace(t, cmsgs.IP.OriginalDstAddress.SizeBytes())
   458  	}
   459  
   460  	if cmsgs.IP.SockErr != nil {
   461  		space += cmsgSpace(t, cmsgs.IP.SockErr.SizeBytes())
   462  	}
   463  
   464  	return space
   465  }
   466  
   467  // Parse parses a raw socket control message into portable objects.
   468  func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint) (socket.ControlMessages, error) {
   469  	var (
   470  		cmsgs socket.ControlMessages
   471  		fds   linux.ControlMessageRights
   472  	)
   473  
   474  	for i := 0; i < len(buf); {
   475  		if i+linux.SizeOfControlMessageHeader > len(buf) {
   476  			return cmsgs, linuxerr.EINVAL
   477  		}
   478  
   479  		var h linux.ControlMessageHeader
   480  		h.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageHeader])
   481  
   482  		if h.Length < uint64(linux.SizeOfControlMessageHeader) {
   483  			return socket.ControlMessages{}, linuxerr.EINVAL
   484  		}
   485  		if h.Length > uint64(len(buf)-i) {
   486  			return socket.ControlMessages{}, linuxerr.EINVAL
   487  		}
   488  
   489  		i += linux.SizeOfControlMessageHeader
   490  		length := int(h.Length) - linux.SizeOfControlMessageHeader
   491  
   492  		switch h.Level {
   493  		case linux.SOL_SOCKET:
   494  			switch h.Type {
   495  			case linux.SCM_RIGHTS:
   496  				rightsSize := bits.AlignDown(length, linux.SizeOfControlMessageRight)
   497  				numRights := rightsSize / linux.SizeOfControlMessageRight
   498  
   499  				if len(fds)+numRights > linux.SCM_MAX_FD {
   500  					return socket.ControlMessages{}, linuxerr.EINVAL
   501  				}
   502  
   503  				for j := i; j < i+rightsSize; j += linux.SizeOfControlMessageRight {
   504  					fds = append(fds, int32(hostarch.ByteOrder.Uint32(buf[j:j+linux.SizeOfControlMessageRight])))
   505  				}
   506  
   507  				i += bits.AlignUp(length, width)
   508  
   509  			case linux.SCM_CREDENTIALS:
   510  				if length < linux.SizeOfControlMessageCredentials {
   511  					return socket.ControlMessages{}, linuxerr.EINVAL
   512  				}
   513  
   514  				var creds linux.ControlMessageCredentials
   515  				creds.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageCredentials])
   516  				scmCreds, err := NewSCMCredentials(t, creds)
   517  				if err != nil {
   518  					return socket.ControlMessages{}, err
   519  				}
   520  				cmsgs.Unix.Credentials = scmCreds
   521  				i += bits.AlignUp(length, width)
   522  
   523  			case linux.SO_TIMESTAMP:
   524  				if length < linux.SizeOfTimeval {
   525  					return socket.ControlMessages{}, linuxerr.EINVAL
   526  				}
   527  				var ts linux.Timeval
   528  				ts.UnmarshalUnsafe(buf[i : i+linux.SizeOfTimeval])
   529  				cmsgs.IP.Timestamp = ts.ToNsecCapped()
   530  				cmsgs.IP.HasTimestamp = true
   531  				i += bits.AlignUp(length, width)
   532  
   533  			default:
   534  				// Unknown message type.
   535  				return socket.ControlMessages{}, linuxerr.EINVAL
   536  			}
   537  		case linux.SOL_IP:
   538  			switch h.Type {
   539  			case linux.IP_TOS:
   540  				if length < linux.SizeOfControlMessageTOS {
   541  					return socket.ControlMessages{}, linuxerr.EINVAL
   542  				}
   543  				cmsgs.IP.HasTOS = true
   544  				var tos primitive.Uint8
   545  				tos.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageTOS])
   546  				cmsgs.IP.TOS = uint8(tos)
   547  				i += bits.AlignUp(length, width)
   548  
   549  			case linux.IP_PKTINFO:
   550  				if length < linux.SizeOfControlMessageIPPacketInfo {
   551  					return socket.ControlMessages{}, linuxerr.EINVAL
   552  				}
   553  
   554  				cmsgs.IP.HasIPPacketInfo = true
   555  				var packetInfo linux.ControlMessageIPPacketInfo
   556  				packetInfo.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageIPPacketInfo])
   557  
   558  				cmsgs.IP.PacketInfo = packetInfo
   559  				i += bits.AlignUp(length, width)
   560  
   561  			case linux.IP_RECVORIGDSTADDR:
   562  				var addr linux.SockAddrInet
   563  				if length < addr.SizeBytes() {
   564  					return socket.ControlMessages{}, linuxerr.EINVAL
   565  				}
   566  				addr.UnmarshalUnsafe(buf[i : i+addr.SizeBytes()])
   567  				cmsgs.IP.OriginalDstAddress = &addr
   568  				i += bits.AlignUp(length, width)
   569  
   570  			case linux.IP_RECVERR:
   571  				var errCmsg linux.SockErrCMsgIPv4
   572  				if length < errCmsg.SizeBytes() {
   573  					return socket.ControlMessages{}, linuxerr.EINVAL
   574  				}
   575  
   576  				errCmsg.UnmarshalBytes(buf[i : i+errCmsg.SizeBytes()])
   577  				cmsgs.IP.SockErr = &errCmsg
   578  				i += bits.AlignUp(length, width)
   579  
   580  			default:
   581  				return socket.ControlMessages{}, linuxerr.EINVAL
   582  			}
   583  		case linux.SOL_IPV6:
   584  			switch h.Type {
   585  			case linux.IPV6_TCLASS:
   586  				if length < linux.SizeOfControlMessageTClass {
   587  					return socket.ControlMessages{}, linuxerr.EINVAL
   588  				}
   589  				cmsgs.IP.HasTClass = true
   590  				var tclass primitive.Uint32
   591  				tclass.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageTClass])
   592  				cmsgs.IP.TClass = uint32(tclass)
   593  				i += bits.AlignUp(length, width)
   594  
   595  			case linux.IPV6_RECVORIGDSTADDR:
   596  				var addr linux.SockAddrInet6
   597  				if length < addr.SizeBytes() {
   598  					return socket.ControlMessages{}, linuxerr.EINVAL
   599  				}
   600  				addr.UnmarshalUnsafe(buf[i : i+addr.SizeBytes()])
   601  				cmsgs.IP.OriginalDstAddress = &addr
   602  				i += bits.AlignUp(length, width)
   603  
   604  			case linux.IPV6_RECVERR:
   605  				var errCmsg linux.SockErrCMsgIPv6
   606  				if length < errCmsg.SizeBytes() {
   607  					return socket.ControlMessages{}, linuxerr.EINVAL
   608  				}
   609  
   610  				errCmsg.UnmarshalBytes(buf[i : i+errCmsg.SizeBytes()])
   611  				cmsgs.IP.SockErr = &errCmsg
   612  				i += bits.AlignUp(length, width)
   613  
   614  			default:
   615  				return socket.ControlMessages{}, linuxerr.EINVAL
   616  			}
   617  		default:
   618  			return socket.ControlMessages{}, linuxerr.EINVAL
   619  		}
   620  	}
   621  
   622  	if cmsgs.Unix.Credentials == nil {
   623  		cmsgs.Unix.Credentials = makeCreds(t, socketOrEndpoint)
   624  	}
   625  
   626  	if len(fds) > 0 {
   627  		if kernel.VFS2Enabled {
   628  			rights, err := NewSCMRightsVFS2(t, fds)
   629  			if err != nil {
   630  				return socket.ControlMessages{}, err
   631  			}
   632  			cmsgs.Unix.Rights = rights
   633  		} else {
   634  			rights, err := NewSCMRights(t, fds)
   635  			if err != nil {
   636  				return socket.ControlMessages{}, err
   637  			}
   638  			cmsgs.Unix.Rights = rights
   639  		}
   640  	}
   641  
   642  	return cmsgs, nil
   643  }
   644  
   645  func makeCreds(t *kernel.Task, socketOrEndpoint interface{}) SCMCredentials {
   646  	if t == nil || socketOrEndpoint == nil {
   647  		return nil
   648  	}
   649  	if cr, ok := socketOrEndpoint.(transport.Credentialer); ok && (cr.Passcred() || cr.ConnectedPasscred()) {
   650  		return MakeCreds(t)
   651  	}
   652  	return nil
   653  }
   654  
   655  // MakeCreds creates default SCMCredentials.
   656  func MakeCreds(t *kernel.Task) SCMCredentials {
   657  	if t == nil {
   658  		return nil
   659  	}
   660  	tcred := t.Credentials()
   661  	return &scmCredentials{t, tcred.EffectiveKUID, tcred.EffectiveKGID}
   662  }
   663  
   664  // LINT.IfChange
   665  
   666  // New creates default control messages if needed.
   667  func New(t *kernel.Task, socketOrEndpoint interface{}, rights SCMRights) transport.ControlMessages {
   668  	return transport.ControlMessages{
   669  		Credentials: makeCreds(t, socketOrEndpoint),
   670  		Rights:      rights,
   671  	}
   672  }
   673  
   674  // LINT.ThenChange(./control_vfs2.go)