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 ×tampP, 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)