-
Notifications
You must be signed in to change notification settings - Fork 983
Open
Description
Full log of tinygo build .
attached
$ tinygo build .
SIGSEGV: segmentation violation
PC=0x635f4d5 m=10 sigcode=1 addr=0x40
signal arrived during cgo execution
When compiling following program
module noisy
go 1.24.2
require (
github.com/noisysockets/netstack v0.9.0
gvisor.dev/gvisor v0.0.0-20250819051428-5ba23728415e
)
require (
github.com/google/btree v1.1.2 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/time v0.7.0 // indirect
)
//go:build linux
// tapstack/main.go
package main
import (
"crypto/rand"
"encoding/binary"
"flag"
"fmt"
"log"
"net"
"time"
"unsafe"
"golang.org/x/sys/unix"
// Netstack (noisysockets fork)
"github.com/noisysockets/netstack/pkg/tcpip"
"github.com/noisysockets/netstack/pkg/tcpip/adapters/gonet"
"github.com/noisysockets/netstack/pkg/tcpip/link/fdbased"
"github.com/noisysockets/netstack/pkg/tcpip/network/arp"
"github.com/noisysockets/netstack/pkg/tcpip/network/ipv4"
"github.com/noisysockets/netstack/pkg/tcpip/network/ipv6"
"github.com/noisysockets/netstack/pkg/tcpip/stack"
"github.com/noisysockets/netstack/pkg/tcpip/transport/tcp"
)
const (
nicID = tcpip.NICID(1)
// from <linux/if_tun.h>
cIFFTAP = 0x0002
cIFFNO_PI = 0x1000
)
type ifreq struct {
Name [unix.IFNAMSIZ]byte
Flags uint16
_ [24 - 2]byte // sizeof(struct ifreq) varies; this is enough for TUNSETIFF
}
func openTAP(name string) (int, error) {
fd, err := unix.Open("/dev/net/tun", unix.O_RDWR|unix.O_NONBLOCK, 0)
if err != nil {
return -1, err
}
var req ifreq
copy(req.Name[:], name)
req.Flags = cIFFTAP | cIFFNO_PI
// TUNSETIFF = 0x400454ca on most arch; use unix.IoctlSetInt is tricky here,
// so call Ioctl with the struct pointer directly.
const TUNSETIFF = 0x400454ca
if _, _, e := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(TUNSETIFF), uintptr(unsafe.Pointer(&req))); e != 0 {
unix.Close(fd)
return -1, e
}
return fd, nil
}
func parseCIDR4(cidr string) ([4]byte, int) {
ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
log.Fatalf("invalid -cidr %q: %v", cidr, err)
}
ip = ip.To4()
if ip == nil {
log.Fatalf("-cidr must be IPv4")
}
prefix, _ := ipnet.Mask.Size()
var ip4 [4]byte
copy(ip4[:], ip)
return ip4, prefix
}
func defaultSubnet() tcpip.Subnet {
return (tcpip.AddressWithPrefix{
Address: tcpip.AddrFrom4([4]byte{}),
PrefixLen: 0,
}).Subnet()
}
func randLaaMAC() tcpip.LinkAddress {
var b [6]byte
if _, err := rand.Read(b[:]); err != nil {
// fall back to time-based
now := time.Now().UnixNano()
binary.LittleEndian.PutUint64(append(b[:0], make([]byte, 8)...), uint64(now))
copy(b[:], append(b[:0], byte(now), byte(now>>8), byte(now>>16), byte(now>>24), byte(now>>32), byte(now>>40)))
}
// Set locally-administered, unicast: set bit1, clear bit0 of first byte.
b[0] = (b[0] | 0x02) &^ 0x01
return tcpip.LinkAddress(b[:])
}
func main() {
dev := flag.String("dev", "tap0", "TAP device name (e.g. tap0)")
cidr := flag.String("cidr", "10.0.0.2/24", "IPv4 address/prefix for the stack (e.g. 10.0.0.2/24)")
gw := flag.String("gw", "", "default gateway IPv4 (optional, e.g. 10.0.0.1)")
port := flag.Int("port", 8080, "TCP port to listen on (echo server)")
mtu := flag.Int("mtu", 1500, "interface MTU")
macStr := flag.String("mac", "", "MAC address to use on TAP (optional; random LAA if empty)")
flag.Parse()
// Open TAP (no kernel IP header; raw Ethernet frames).
fd, err := openTAP(*dev)
if err != nil {
log.Fatalf("openTAP(%s): %v", *dev, err)
}
// Choose MAC address.
var linkAddr tcpip.LinkAddress
if *macStr != "" {
la, err := tcpip.ParseMACAddress(*macStr)
if err != nil {
log.Fatalf("parse MAC: %v", err)
}
linkAddr = la
} else {
linkAddr = randLaaMAC()
}
// Wire TAP into netstack as an Ethernet link endpoint.
linkEP, err := fdbased.New(&fdbased.Options{
FDs: []int{fd},
MTU: uint32(*mtu),
EthernetHeader: true,
Address: linkAddr,
})
if err != nil {
log.Fatalf("fdbased.New: %v", err)
}
// Build the stack (ARP, IPv4/IPv6, TCP).
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{
arp.NewProtocol,
ipv4.NewProtocol,
ipv6.NewProtocol,
},
TransportProtocols: []stack.TransportProtocolFactory{
tcp.NewProtocol,
},
})
// Create NIC on the link endpoint.
if err := s.CreateNIC(nicID, linkEP); err != nil {
log.Fatalf("CreateNIC: %v", err)
}
// Assign IPv4 address.
ip4, prefix := parseCIDR4(*cidr)
addrWithPrefix := tcpip.AddressWithPrefix{
Address: tcpip.AddrFrom4(ip4),
PrefixLen: prefix,
}
terr := s.AddProtocolAddress(nicID, tcpip.ProtocolAddress{
Protocol: ipv4.ProtocolNumber,
AddressWithPrefix: addrWithPrefix,
}, stack.AddressProperties{})
if terr != nil {
log.Fatalf("AddProtocolAddress: %v", terr)
}
// Routes: on-link subnet + optional default route via gw.
routes := []tcpip.Route{
{Destination: addrWithPrefix.Subnet(), NIC: nicID},
}
if *gw != "" {
ip := net.ParseIP(*gw).To4()
if ip == nil {
log.Fatalf("-gw must be IPv4")
}
routes = append(routes, tcpip.Route{
Destination: defaultSubnet(),
Gateway: tcpip.AddrFrom4([4]byte{ip[0], ip[1], ip[2], ip[3]}),
NIC: nicID,
})
}
s.SetRouteTable(routes)
// Listen on TCP <stack-ip>:port using the gonet adapter.
laddr := tcpip.FullAddress{
NIC: nicID,
Addr: addrWithPrefix.Address,
Port: uint16(*port),
}
ln, err := gonet.ListenTCP(s, laddr, ipv4.ProtocolNumber)
if err != nil {
log.Fatalf("ListenTCP: %v", err)
}
defer ln.Close()
fmt.Printf("netstack up on %s (MAC %s, MTU %d)\n", *dev, linkAddr.String(), *mtu)
fmt.Printf("IPv4 %s, listening on TCP %d\n", addrWithPrefix.String(), *port)
if *gw != "" {
fmt.Printf("Default route via %s\n", *gw)
}
fmt.Println("Echo server ready.")
for {
c, err := ln.Accept()
if err != nil {
log.Fatalf("Accept: %v", err)
}
go func(conn net.Conn) {
defer conn.Close()
_ = conn.SetDeadline(time.Now().Add(5 * time.Minute))
buf := make([]byte, 32<<10)
for {
n, err := conn.Read(buf)
if n > 0 {
_, _ = conn.Write(buf[:n]) // echo
}
if err != nil {
return
}
}
}(c)
}
}
Metadata
Metadata
Assignees
Labels
No labels