Source file src/net/unixsock_readmsg_test.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build unix
     6  
     7  package net
     8  
     9  import (
    10  	"os"
    11  	"syscall"
    12  	"testing"
    13  	"time"
    14  )
    15  
    16  func TestUnixConnReadMsgUnixSCMRightsCloseOnExec(t *testing.T) {
    17  	if !testableNetwork("unix") {
    18  		t.Skip("not unix system")
    19  	}
    20  
    21  	scmFile, err := os.Open(os.DevNull)
    22  	if err != nil {
    23  		t.Fatalf("file open: %v", err)
    24  	}
    25  	defer scmFile.Close()
    26  
    27  	rights := syscall.UnixRights(int(scmFile.Fd()))
    28  	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
    29  	if err != nil {
    30  		t.Fatalf("Socketpair: %v", err)
    31  	}
    32  
    33  	writeFile := os.NewFile(uintptr(fds[0]), "write-socket")
    34  	defer writeFile.Close()
    35  	readFile := os.NewFile(uintptr(fds[1]), "read-socket")
    36  	defer readFile.Close()
    37  
    38  	cw, err := FileConn(writeFile)
    39  	if err != nil {
    40  		t.Fatalf("FileConn: %v", err)
    41  	}
    42  	defer cw.Close()
    43  	cr, err := FileConn(readFile)
    44  	if err != nil {
    45  		t.Fatalf("FileConn: %v", err)
    46  	}
    47  	defer cr.Close()
    48  
    49  	ucw, ok := cw.(*UnixConn)
    50  	if !ok {
    51  		t.Fatalf("got %T; want UnixConn", cw)
    52  	}
    53  	ucr, ok := cr.(*UnixConn)
    54  	if !ok {
    55  		t.Fatalf("got %T; want UnixConn", cr)
    56  	}
    57  
    58  	oob := make([]byte, syscall.CmsgSpace(4))
    59  	err = ucw.SetWriteDeadline(time.Now().Add(5 * time.Second))
    60  	if err != nil {
    61  		t.Fatalf("Can't set unix connection timeout: %v", err)
    62  	}
    63  	_, _, err = ucw.WriteMsgUnix(nil, rights, nil)
    64  	if err != nil {
    65  		t.Fatalf("UnixConn readMsg: %v", err)
    66  	}
    67  	err = ucr.SetReadDeadline(time.Now().Add(5 * time.Second))
    68  	if err != nil {
    69  		t.Fatalf("Can't set unix connection timeout: %v", err)
    70  	}
    71  	_, oobn, _, _, err := ucr.ReadMsgUnix(nil, oob)
    72  	if err != nil {
    73  		t.Fatalf("UnixConn readMsg: %v", err)
    74  	}
    75  
    76  	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
    77  	if err != nil {
    78  		t.Fatalf("ParseSocketControlMessage: %v", err)
    79  	}
    80  	if len(scms) != 1 {
    81  		t.Fatalf("got scms = %#v; expected 1 SocketControlMessage", scms)
    82  	}
    83  	scm := scms[0]
    84  	gotFDs, err := syscall.ParseUnixRights(&scm)
    85  	if err != nil {
    86  		t.Fatalf("syscall.ParseUnixRights: %v", err)
    87  	}
    88  	if len(gotFDs) != 1 {
    89  		t.Fatalf("got FDs %#v: wanted only 1 fd", gotFDs)
    90  	}
    91  	defer func() {
    92  		if err := syscall.Close(gotFDs[0]); err != nil {
    93  			t.Fatalf("fail to close gotFDs: %v", err)
    94  		}
    95  	}()
    96  
    97  	flags, err := fcntl(gotFDs[0], syscall.F_GETFD, 0)
    98  	if err != nil {
    99  		t.Fatalf("Can't get flags of fd:%#v, with err:%v", gotFDs[0], err)
   100  	}
   101  	if flags&syscall.FD_CLOEXEC == 0 {
   102  		t.Fatalf("got flags %#x, want %#x (FD_CLOEXEC) set", flags, syscall.FD_CLOEXEC)
   103  	}
   104  }
   105  

View as plain text