github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/syscalls/linux/points.go (about)

     1  // Copyright 2022 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 linux
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"google.golang.org/protobuf/proto"
    21  	"github.com/nicocha30/gvisor-ligolo/pkg/abi/linux"
    22  	"github.com/nicocha30/gvisor-ligolo/pkg/hostarch"
    23  	"github.com/nicocha30/gvisor-ligolo/pkg/marshal/primitive"
    24  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel"
    25  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/seccheck"
    26  	pb "github.com/nicocha30/gvisor-ligolo/pkg/sentry/seccheck/points/points_go_proto"
    27  	"github.com/nicocha30/gvisor-ligolo/pkg/usermem"
    28  )
    29  
    30  func newExitMaybe(info kernel.SyscallInfo) *pb.Exit {
    31  	if !info.Exit {
    32  		return nil
    33  	}
    34  	return &pb.Exit{
    35  		Result:  int64(info.Rval),
    36  		Errorno: int64(info.Errno),
    37  	}
    38  }
    39  
    40  func getFilePath(t *kernel.Task, fd int32) string {
    41  	if fd < 0 {
    42  		return ""
    43  	}
    44  	fdt := t.FDTable()
    45  	if fdt == nil {
    46  		return "[err: no FD table]"
    47  	}
    48  	file, _ := fdt.Get(fd)
    49  	if file == nil {
    50  		return "[err: FD not found]"
    51  	}
    52  	defer file.DecRef(t)
    53  
    54  	root := t.MountNamespace().Root()
    55  	path, err := t.Kernel().VFS().PathnameWithDeleted(t, root, file.VirtualDentry())
    56  	if err != nil {
    57  		return fmt.Sprintf("[err: %v]", err)
    58  	}
    59  	return path
    60  }
    61  
    62  func getIovecSize(t *kernel.Task, addr hostarch.Addr, iovcnt int) uint64 {
    63  	dst, err := t.IovecsIOSequence(addr, iovcnt, usermem.IOOpts{AddressSpaceActive: true})
    64  	if err != nil {
    65  		return 0
    66  	}
    67  	return uint64(dst.NumBytes())
    68  }
    69  
    70  // PointOpen converts open(2) syscall to proto.
    71  func PointOpen(t *kernel.Task, _ seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
    72  	p := &pb.Open{
    73  		ContextData: cxtData,
    74  		Sysno:       uint64(info.Sysno),
    75  		Fd:          linux.AT_FDCWD,
    76  		Flags:       info.Args[1].Uint(),
    77  		Mode:        uint32(info.Args[2].ModeT()),
    78  	}
    79  	addr := info.Args[0].Pointer()
    80  	if addr > 0 {
    81  		path, err := t.CopyInString(addr, linux.PATH_MAX)
    82  		if err == nil { // if NO error
    83  			p.Pathname = path
    84  		}
    85  	}
    86  	p.Exit = newExitMaybe(info)
    87  	return p, pb.MessageType_MESSAGE_SYSCALL_OPEN
    88  }
    89  
    90  // PointOpenat converts openat(2) syscall to proto.
    91  func PointOpenat(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
    92  	p := &pb.Open{
    93  		ContextData: cxtData,
    94  		Sysno:       uint64(info.Sysno),
    95  		Fd:          int64(info.Args[0].Int()),
    96  		Flags:       info.Args[2].Uint(),
    97  	}
    98  
    99  	addr := info.Args[1].Pointer()
   100  	if addr > 0 {
   101  		path, err := t.CopyInString(addr, linux.PATH_MAX)
   102  		if err == nil { // if NO error
   103  			p.Pathname = path
   104  		}
   105  	}
   106  	if p.Flags&linux.O_CREAT != 0 {
   107  		p.Mode = uint32(info.Args[3].ModeT())
   108  	}
   109  
   110  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   111  		p.FdPath = getFilePath(t, int32(p.Fd))
   112  	}
   113  
   114  	p.Exit = newExitMaybe(info)
   115  
   116  	return p, pb.MessageType_MESSAGE_SYSCALL_OPEN
   117  }
   118  
   119  // PointCreat converts creat(2) syscall to proto.
   120  func PointCreat(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   121  	p := &pb.Open{
   122  		ContextData: cxtData,
   123  		Sysno:       uint64(info.Sysno),
   124  		Fd:          linux.AT_FDCWD,
   125  		Flags:       linux.O_WRONLY | linux.O_CREAT | linux.O_TRUNC,
   126  		Mode:        uint32(info.Args[1].ModeT()),
   127  	}
   128  
   129  	addr := info.Args[0].Pointer()
   130  	if addr > 0 {
   131  		path, err := t.CopyInString(addr, linux.PATH_MAX)
   132  		if err == nil { // if NO error
   133  			p.Pathname = path
   134  		}
   135  	}
   136  
   137  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   138  		p.FdPath = getFilePath(t, int32(p.Fd))
   139  	}
   140  
   141  	p.Exit = newExitMaybe(info)
   142  
   143  	return p, pb.MessageType_MESSAGE_SYSCALL_OPEN
   144  }
   145  
   146  // PointClose converts close(2) syscall to proto.
   147  func PointClose(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   148  	p := &pb.Close{
   149  		ContextData: cxtData,
   150  		Sysno:       uint64(info.Sysno),
   151  		Fd:          int64(info.Args[0].Int()),
   152  	}
   153  
   154  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   155  		p.FdPath = getFilePath(t, int32(p.Fd))
   156  	}
   157  
   158  	p.Exit = newExitMaybe(info)
   159  	return p, pb.MessageType_MESSAGE_SYSCALL_CLOSE
   160  }
   161  
   162  // PointRead converts read(2) syscall to proto.
   163  func PointRead(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   164  	p := &pb.Read{
   165  		ContextData: cxtData,
   166  		Sysno:       uint64(info.Sysno),
   167  		Fd:          int64(info.Args[0].Int()),
   168  		Count:       uint64(info.Args[2].SizeT()),
   169  	}
   170  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   171  		p.FdPath = getFilePath(t, int32(p.Fd))
   172  	}
   173  
   174  	p.Exit = newExitMaybe(info)
   175  
   176  	return p, pb.MessageType_MESSAGE_SYSCALL_READ
   177  }
   178  
   179  // PointPread64 converts pread64(2) syscall to proto.
   180  func PointPread64(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   181  	p := &pb.Read{
   182  		ContextData: cxtData,
   183  		Sysno:       uint64(info.Sysno),
   184  		Fd:          int64(info.Args[0].Int()),
   185  		Count:       uint64(info.Args[2].SizeT()),
   186  		HasOffset:   true,
   187  		Offset:      info.Args[3].Int64(),
   188  	}
   189  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   190  		p.FdPath = getFilePath(t, int32(p.Fd))
   191  	}
   192  
   193  	p.Exit = newExitMaybe(info)
   194  
   195  	return p, pb.MessageType_MESSAGE_SYSCALL_READ
   196  }
   197  
   198  // PointReadv converts readv(2) syscall to proto.
   199  func PointReadv(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   200  	p := &pb.Read{
   201  		ContextData: cxtData,
   202  		Sysno:       uint64(info.Sysno),
   203  		Fd:          int64(info.Args[0].Int()),
   204  		Count:       getIovecSize(t, info.Args[1].Pointer(), int(info.Args[2].Int())),
   205  	}
   206  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   207  		p.FdPath = getFilePath(t, int32(p.Fd))
   208  	}
   209  
   210  	p.Exit = newExitMaybe(info)
   211  
   212  	return p, pb.MessageType_MESSAGE_SYSCALL_READ
   213  }
   214  
   215  // PointPreadv converts preadv(2) syscall to proto.
   216  func PointPreadv(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   217  	p := &pb.Read{
   218  		ContextData: cxtData,
   219  		Sysno:       uint64(info.Sysno),
   220  		Fd:          int64(info.Args[0].Int()),
   221  		Count:       getIovecSize(t, info.Args[1].Pointer(), int(info.Args[2].Int())),
   222  		HasOffset:   true,
   223  		Offset:      info.Args[3].Int64(),
   224  	}
   225  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   226  		p.FdPath = getFilePath(t, int32(p.Fd))
   227  	}
   228  
   229  	p.Exit = newExitMaybe(info)
   230  
   231  	return p, pb.MessageType_MESSAGE_SYSCALL_READ
   232  }
   233  
   234  // PointPreadv2 converts preadv2(2) syscall to proto.
   235  func PointPreadv2(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   236  	p := &pb.Read{
   237  		ContextData: cxtData,
   238  		Sysno:       uint64(info.Sysno),
   239  		Fd:          int64(info.Args[0].Int()),
   240  		Count:       getIovecSize(t, info.Args[1].Pointer(), int(info.Args[2].Int())),
   241  		HasOffset:   true,
   242  		Offset:      info.Args[3].Int64(),
   243  		Flags:       info.Args[5].Uint(),
   244  	}
   245  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   246  		p.FdPath = getFilePath(t, int32(p.Fd))
   247  	}
   248  
   249  	p.Exit = newExitMaybe(info)
   250  
   251  	return p, pb.MessageType_MESSAGE_SYSCALL_READ
   252  }
   253  
   254  // PointWrite converts write(2) syscall to proto.
   255  func PointWrite(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   256  	p := &pb.Write{
   257  		ContextData: cxtData,
   258  		Sysno:       uint64(info.Sysno),
   259  		Fd:          int64(info.Args[0].Int()),
   260  		Count:       uint64(info.Args[2].SizeT()),
   261  	}
   262  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   263  		p.FdPath = getFilePath(t, int32(p.Fd))
   264  	}
   265  
   266  	p.Exit = newExitMaybe(info)
   267  
   268  	return p, pb.MessageType_MESSAGE_SYSCALL_WRITE
   269  }
   270  
   271  // PointPwrite64 converts pwrite64(2) syscall to proto.
   272  func PointPwrite64(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   273  	p := &pb.Write{
   274  		ContextData: cxtData,
   275  		Sysno:       uint64(info.Sysno),
   276  		Fd:          int64(info.Args[0].Int()),
   277  		Count:       uint64(info.Args[2].SizeT()),
   278  		HasOffset:   true,
   279  		Offset:      info.Args[3].Int64(),
   280  	}
   281  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   282  		p.FdPath = getFilePath(t, int32(p.Fd))
   283  	}
   284  
   285  	p.Exit = newExitMaybe(info)
   286  
   287  	return p, pb.MessageType_MESSAGE_SYSCALL_WRITE
   288  }
   289  
   290  // PointWritev converts writev(2) syscall to proto.
   291  func PointWritev(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   292  	p := &pb.Write{
   293  		ContextData: cxtData,
   294  		Sysno:       uint64(info.Sysno),
   295  		Fd:          int64(info.Args[0].Int()),
   296  		Count:       getIovecSize(t, info.Args[1].Pointer(), int(info.Args[2].Int())),
   297  	}
   298  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   299  		p.FdPath = getFilePath(t, int32(p.Fd))
   300  	}
   301  
   302  	p.Exit = newExitMaybe(info)
   303  
   304  	return p, pb.MessageType_MESSAGE_SYSCALL_WRITE
   305  }
   306  
   307  // PointPwritev converts pwritev(2) syscall to proto.
   308  func PointPwritev(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   309  	p := &pb.Write{
   310  		ContextData: cxtData,
   311  		Sysno:       uint64(info.Sysno),
   312  		Fd:          int64(info.Args[0].Int()),
   313  		Count:       getIovecSize(t, info.Args[1].Pointer(), int(info.Args[2].Int())),
   314  		HasOffset:   true,
   315  		Offset:      info.Args[3].Int64(),
   316  	}
   317  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   318  		p.FdPath = getFilePath(t, int32(p.Fd))
   319  	}
   320  
   321  	p.Exit = newExitMaybe(info)
   322  
   323  	return p, pb.MessageType_MESSAGE_SYSCALL_WRITE
   324  }
   325  
   326  // PointPwritev2 converts pwritev2(2) syscall to proto.
   327  func PointPwritev2(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   328  	p := &pb.Write{
   329  		ContextData: cxtData,
   330  		Sysno:       uint64(info.Sysno),
   331  		Fd:          int64(info.Args[0].Int()),
   332  		Count:       getIovecSize(t, info.Args[1].Pointer(), int(info.Args[2].Int())),
   333  		HasOffset:   true,
   334  		Offset:      info.Args[3].Int64(),
   335  		Flags:       info.Args[5].Uint(),
   336  	}
   337  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   338  		p.FdPath = getFilePath(t, int32(p.Fd))
   339  	}
   340  
   341  	p.Exit = newExitMaybe(info)
   342  
   343  	return p, pb.MessageType_MESSAGE_SYSCALL_WRITE
   344  }
   345  
   346  // PointSocket converts socket(2) syscall to proto.
   347  func PointSocket(_ *kernel.Task, _ seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   348  	p := &pb.Socket{
   349  		ContextData: cxtData,
   350  		Sysno:       uint64(info.Sysno),
   351  		Domain:      info.Args[0].Int(),
   352  		Type:        info.Args[1].Int(),
   353  		Protocol:    info.Args[2].Int(),
   354  	}
   355  
   356  	p.Exit = newExitMaybe(info)
   357  
   358  	return p, pb.MessageType_MESSAGE_SYSCALL_SOCKET
   359  }
   360  
   361  // PointConnect converts connect(2) syscall to proto.
   362  func PointConnect(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   363  	p := &pb.Connect{
   364  		ContextData: cxtData,
   365  		Sysno:       uint64(info.Sysno),
   366  		Fd:          int64(info.Args[0].Int()),
   367  	}
   368  
   369  	addr := info.Args[1].Pointer()
   370  	addrlen := info.Args[2].Uint()
   371  	p.Address, _ = CaptureAddress(t, addr, addrlen)
   372  
   373  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   374  		p.FdPath = getFilePath(t, int32(p.Fd))
   375  	}
   376  
   377  	p.Exit = newExitMaybe(info)
   378  
   379  	return p, pb.MessageType_MESSAGE_SYSCALL_CONNECT
   380  }
   381  
   382  // PointExecve converts execve(2) syscall to proto.
   383  func PointExecve(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   384  	p := &pb.Execve{
   385  		ContextData: cxtData,
   386  		Sysno:       uint64(info.Sysno),
   387  	}
   388  	if pathname, err := t.CopyInString(info.Args[0].Pointer(), linux.PATH_MAX); err == nil { // if NO error
   389  		p.Pathname = pathname
   390  	}
   391  	if argvAddr := info.Args[1].Pointer(); argvAddr != 0 {
   392  		if argv, err := t.CopyInVector(argvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil { // if NO error
   393  			p.Argv = argv
   394  		}
   395  	}
   396  
   397  	if fields.Local.Contains(seccheck.FieldSyscallExecveEnvv) {
   398  		if envvAddr := info.Args[2].Pointer(); envvAddr != 0 {
   399  			if envv, err := t.CopyInVector(envvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil { // if NO error
   400  				p.Envv = envv
   401  			}
   402  		}
   403  	}
   404  
   405  	p.Exit = newExitMaybe(info)
   406  
   407  	return p, pb.MessageType_MESSAGE_SYSCALL_EXECVE
   408  }
   409  
   410  // PointExecveat converts execveat(2) syscall to proto.
   411  func PointExecveat(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   412  	p := &pb.Execve{
   413  		ContextData: cxtData,
   414  		Sysno:       uint64(info.Sysno),
   415  		Fd:          int64(info.Args[0].Int()),
   416  		Flags:       info.Args[4].Uint(),
   417  	}
   418  	if pathname, err := t.CopyInString(info.Args[1].Pointer(), linux.PATH_MAX); err == nil { // if NO error
   419  		p.Pathname = pathname
   420  	}
   421  	if argvAddr := info.Args[2].Pointer(); argvAddr != 0 {
   422  		if argv, err := t.CopyInVector(argvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil { // if NO error
   423  			p.Argv = argv
   424  		}
   425  	}
   426  
   427  	if fields.Local.Contains(seccheck.FieldSyscallExecveEnvv) {
   428  		if envvAddr := info.Args[3].Pointer(); envvAddr != 0 {
   429  			if envv, err := t.CopyInVector(envvAddr, ExecMaxElemSize, ExecMaxTotalSize); err == nil { // if NO error
   430  				p.Envv = envv
   431  			}
   432  		}
   433  	}
   434  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   435  		p.FdPath = getFilePath(t, int32(p.Fd))
   436  	}
   437  
   438  	p.Exit = newExitMaybe(info)
   439  
   440  	return p, pb.MessageType_MESSAGE_SYSCALL_EXECVE
   441  }
   442  
   443  // pointChdirHelper converts chdir(2) and fchdir(2) syscall to proto.
   444  func pointChdirHelper(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo, fd int64, path hostarch.Addr) (proto.Message, pb.MessageType) {
   445  	p := &pb.Chdir{
   446  		ContextData: cxtData,
   447  		Sysno:       uint64(info.Sysno),
   448  		Fd:          fd,
   449  	}
   450  
   451  	if path > 0 {
   452  		pathname, err := t.CopyInString(path, linux.PATH_MAX)
   453  		if err == nil { // if NO error
   454  			p.Pathname = pathname
   455  		}
   456  	}
   457  
   458  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   459  		p.FdPath = getFilePath(t, int32(p.Fd))
   460  	}
   461  
   462  	p.Exit = newExitMaybe(info)
   463  
   464  	return p, pb.MessageType_MESSAGE_SYSCALL_CHDIR
   465  }
   466  
   467  // PointChdir calls pointChdirHelper to convert chdir(2) syscall to proto.
   468  func PointChdir(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   469  	path := info.Args[0].Pointer()
   470  	return pointChdirHelper(t, fields, cxtData, info, linux.AT_FDCWD, path)
   471  }
   472  
   473  // PointFchdir calls pointChdirHelper to convert fchdir(2) syscall to proto.
   474  func PointFchdir(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   475  	fd := int64(info.Args[0].Int())
   476  	path := info.Args[1].Pointer()
   477  	return pointChdirHelper(t, fields, cxtData, info, fd, path)
   478  }
   479  
   480  // pointSetidHelper converts setuid(2) and setgid(2) syscall to proto.
   481  func pointSetidHelper(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo, id uint32) (proto.Message, pb.MessageType) {
   482  	p := &pb.Setid{
   483  		ContextData: cxtData,
   484  		Sysno:       uint64(info.Sysno),
   485  		Id:          id,
   486  	}
   487  
   488  	p.Exit = newExitMaybe(info)
   489  
   490  	return p, pb.MessageType_MESSAGE_SYSCALL_SETID
   491  }
   492  
   493  // PointSetuid calls pointSetidHelper to convert setuid(2) syscall to proto.
   494  func PointSetuid(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   495  	id := info.Args[0].Uint()
   496  	return pointSetidHelper(t, fields, cxtData, info, id)
   497  }
   498  
   499  // PointSetgid calls pointSetidHelper to convert setgid(2) syscall to proto.
   500  func PointSetgid(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   501  	id := info.Args[0].Uint()
   502  	return pointSetidHelper(t, fields, cxtData, info, id)
   503  }
   504  
   505  // PointSetsid calls pointSetidHelper to convert setsid(2) syscall to proto.
   506  func PointSetsid(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   507  	return pointSetidHelper(t, fields, cxtData, info, 0)
   508  }
   509  
   510  // pointSetresidHelper converts setresuid(2) and setresgid(2) syscall to proto.
   511  func pointSetresidHelper(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   512  	p := &pb.Setresid{
   513  		ContextData: cxtData,
   514  		Sysno:       uint64(info.Sysno),
   515  		Rid:         info.Args[0].Uint(),
   516  		Eid:         info.Args[1].Uint(),
   517  		Sid:         info.Args[2].Uint(),
   518  	}
   519  
   520  	p.Exit = newExitMaybe(info)
   521  
   522  	return p, pb.MessageType_MESSAGE_SYSCALL_SETRESID
   523  }
   524  
   525  // PointSetresuid calls pointSetresidHelper to convert setresuid(2) syscall to proto.
   526  func PointSetresuid(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   527  	return pointSetresidHelper(t, fields, cxtData, info)
   528  }
   529  
   530  // PointSetresgid calls pointSetresidHelper to convert setresgid(2) syscall to proto.
   531  func PointSetresgid(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   532  	return pointSetresidHelper(t, fields, cxtData, info)
   533  }
   534  
   535  func rlimits(rlimit rlimit64) *pb.StructRlimit {
   536  	limit := rlimit.toLimit()
   537  	return &pb.StructRlimit{
   538  		Cur: limit.Cur,
   539  		Max: limit.Max,
   540  	}
   541  }
   542  
   543  // PointPrlimit64 call converts prlimit64(2) syscall to proto.
   544  func PointPrlimit64(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   545  	p := &pb.Prlimit{
   546  		ContextData: cxtData,
   547  		Sysno:       uint64(info.Sysno),
   548  		Pid:         int32(info.Args[0].Int()),
   549  		Resource:    info.Args[1].Int64(),
   550  	}
   551  
   552  	if newRlimitAddr := info.Args[2].Pointer(); newRlimitAddr != 0 {
   553  		var nrl rlimit64
   554  		if err := nrl.copyIn(t, newRlimitAddr); err == nil { // if NO error
   555  			p.NewLimit = rlimits(nrl)
   556  		}
   557  	}
   558  
   559  	if oldRlimitAddr := info.Args[3].Pointer(); oldRlimitAddr != 0 {
   560  		var orl rlimit64
   561  		if err := orl.copyIn(t, oldRlimitAddr); err == nil { // if NO error
   562  			p.OldLimit = rlimits(orl)
   563  		}
   564  	}
   565  
   566  	p.Exit = newExitMaybe(info)
   567  
   568  	return p, pb.MessageType_MESSAGE_SYSCALL_PRLIMIT64
   569  }
   570  
   571  // pipeHelper converts pipe(2) and pipe2(2) syscall to proto.
   572  func pipeHelper(t *kernel.Task, cxtData *pb.ContextData, info kernel.SyscallInfo, flags uint32) (proto.Message, pb.MessageType) {
   573  	p := &pb.Pipe{
   574  		ContextData: cxtData,
   575  		Sysno:       uint64(info.Sysno),
   576  		Flags:       flags,
   577  	}
   578  	if info.Exit {
   579  		if pipeFDAddr := info.Args[0].Pointer(); pipeFDAddr != 0 {
   580  			var pipeFDs [2]int32
   581  			if _, err := primitive.CopyInt32SliceIn(t, pipeFDAddr, pipeFDs[:]); err == nil { // if NO error
   582  				p.Reader = pipeFDs[0]
   583  				p.Writer = pipeFDs[1]
   584  			}
   585  		}
   586  	}
   587  
   588  	p.Exit = newExitMaybe(info)
   589  	return p, pb.MessageType_MESSAGE_SYSCALL_PIPE
   590  }
   591  
   592  // PointPipe calls pipeHelper to convert pipe(2) syscall to proto.
   593  func PointPipe(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   594  	return pipeHelper(t, cxtData, info, 0)
   595  }
   596  
   597  // PointPipe2 calls pipeHelper to convert pipe2(2) syscall to proto.
   598  func PointPipe2(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   599  	flags := info.Args[1].Uint()
   600  	return pipeHelper(t, cxtData, info, flags)
   601  }
   602  
   603  // eventfdHelper converts eventfd(2) and eventfd2(2) syscall to proto.
   604  func eventfdHelper(cxtData *pb.ContextData, info kernel.SyscallInfo, flags uint32) (proto.Message, pb.MessageType) {
   605  	p := &pb.Eventfd{
   606  		ContextData: cxtData,
   607  		Sysno:       uint64(info.Sysno),
   608  		Val:         int32(info.Args[0].Int()),
   609  		Flags:       flags,
   610  	}
   611  
   612  	p.Exit = newExitMaybe(info)
   613  	return p, pb.MessageType_MESSAGE_SYSCALL_EVENTFD
   614  }
   615  
   616  // PointEventfd calls pipeHelper to convert eventfd(2) syscall to proto.
   617  func PointEventfd(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   618  	return eventfdHelper(cxtData, info, 0)
   619  }
   620  
   621  // PointEventfd2 calls pipeHelper to convert eventfd2(2) syscall to proto.
   622  func PointEventfd2(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   623  	flags := info.Args[1].Uint()
   624  	return eventfdHelper(cxtData, info, flags)
   625  }
   626  
   627  // PointFcntl converts fcntl(2) syscall to proto.
   628  func PointFcntl(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   629  	p := &pb.Fcntl{
   630  		ContextData: cxtData,
   631  		Sysno:       uint64(info.Sysno),
   632  		Fd:          info.Args[0].Int(),
   633  		Cmd:         info.Args[1].Int(),
   634  		Args:        info.Args[2].Int64(),
   635  	}
   636  
   637  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   638  		p.FdPath = getFilePath(t, int32(p.Fd))
   639  	}
   640  
   641  	p.Exit = newExitMaybe(info)
   642  	return p, pb.MessageType_MESSAGE_SYSCALL_FCNTL
   643  }
   644  
   645  // pointDupHelper converts dup(2), dup2(2), and dup3(2) syscall to proto.
   646  func pointDupHelper(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo, oldFD, newFD int32, flags uint32) (proto.Message, pb.MessageType) {
   647  	p := &pb.Dup{
   648  		ContextData: cxtData,
   649  		Sysno:       uint64(info.Sysno),
   650  		OldFd:       oldFD,
   651  		NewFd:       newFD,
   652  		Flags:       flags,
   653  	}
   654  
   655  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   656  		p.FdPath = getFilePath(t, int32(p.OldFd))
   657  	}
   658  
   659  	p.Exit = newExitMaybe(info)
   660  	return p, pb.MessageType_MESSAGE_SYSCALL_DUP
   661  }
   662  
   663  // PointDup calls pointDupHelper to convert dup(2) syscall to proto.
   664  func PointDup(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   665  	oldFD := info.Args[0].Int()
   666  	return pointDupHelper(t, fields, cxtData, info, oldFD, 0, 0)
   667  }
   668  
   669  // PointDup2 calls pointDupHelper to convert dup2(2) syscall to proto.
   670  func PointDup2(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   671  	oldFD := info.Args[0].Int()
   672  	newFD := info.Args[1].Int()
   673  	return pointDupHelper(t, fields, cxtData, info, oldFD, newFD, 0)
   674  }
   675  
   676  // PointDup3 calls pointDupHelper to convert dup3(2) syscall to proto.
   677  func PointDup3(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   678  	oldFD := info.Args[0].Int()
   679  	newFD := info.Args[1].Int()
   680  	flags := info.Args[2].Uint()
   681  	return pointDupHelper(t, fields, cxtData, info, oldFD, newFD, flags)
   682  }
   683  
   684  // signalfdHelper converts signalfd(2) and signalfd4(2) syscall to proto.
   685  func signalfdHelper(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo, flags int32) (proto.Message, pb.MessageType) {
   686  	p := &pb.Signalfd{
   687  		ContextData: cxtData,
   688  		Sysno:       uint64(info.Sysno),
   689  		Fd:          info.Args[0].Int(),
   690  		Flags:       flags,
   691  	}
   692  	sigset := info.Args[1].Pointer()
   693  	sigsetsize := info.Args[2].SizeT()
   694  	mask, err := copyInSigSet(t, sigset, sigsetsize)
   695  	if err == nil { // if NO error
   696  		p.Sigset = uint64(mask)
   697  		p.Sigset = uint64(mask)
   698  	}
   699  
   700  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   701  		p.FdPath = getFilePath(t, int32(p.Fd))
   702  	}
   703  
   704  	p.Exit = newExitMaybe(info)
   705  	return p, pb.MessageType_MESSAGE_SYSCALL_SIGNALFD
   706  }
   707  
   708  // PointSignalfd calls signalfdHelper to convert signalfd(2) syscall to proto.
   709  func PointSignalfd(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   710  	return signalfdHelper(t, fields, cxtData, info, 0)
   711  }
   712  
   713  // PointSignalfd4 calls signalfdHelper to convert signalfd4(2) syscall to proto.
   714  func PointSignalfd4(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   715  	flags := info.Args[3].Int()
   716  	return signalfdHelper(t, fields, cxtData, info, flags)
   717  }
   718  
   719  // PointChroot converts chroot(2) syscall to proto.
   720  func PointChroot(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   721  	p := &pb.Chroot{
   722  		ContextData: cxtData,
   723  		Sysno:       uint64(info.Sysno),
   724  	}
   725  	if pathname, err := t.CopyInString(info.Args[0].Pointer(), linux.PATH_MAX); err == nil { // if NO error
   726  		p.Pathname = pathname
   727  	}
   728  	p.Exit = newExitMaybe(info)
   729  	return p, pb.MessageType_MESSAGE_SYSCALL_CHROOT
   730  }
   731  
   732  // PointClone converts clone(2) syscall to proto.
   733  func PointClone(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   734  	p := &pb.Clone{
   735  		ContextData: cxtData,
   736  		Sysno:       uint64(info.Sysno),
   737  		Flags:       info.Args[0].Uint64(),
   738  		Stack:       uint64(info.Args[1].Pointer()),
   739  		Tls:         uint64(info.Args[4].Pointer()),
   740  	}
   741  	var parTid kernel.ThreadID
   742  
   743  	parentTidAddr := info.Args[2].Pointer()
   744  	if _, err := parTid.CopyIn(t, parentTidAddr); err == nil { // if NO error
   745  		p.NewTid = uint64(parTid)
   746  	}
   747  
   748  	p.Exit = newExitMaybe(info)
   749  	return p, pb.MessageType_MESSAGE_SYSCALL_CLONE
   750  }
   751  
   752  // PointBind converts bind(2) syscall to proto.
   753  func PointBind(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   754  	p := &pb.Bind{
   755  		ContextData: cxtData,
   756  		Sysno:       uint64(info.Sysno),
   757  		Fd:          info.Args[0].Int(),
   758  	}
   759  	addr := info.Args[1].Pointer()
   760  	addrLen := info.Args[2].Uint()
   761  	if address, err := CaptureAddress(t, addr, addrLen); err == nil { // if NO error
   762  		p.Address = address
   763  	}
   764  
   765  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   766  		p.FdPath = getFilePath(t, int32(p.Fd))
   767  	}
   768  
   769  	p.Exit = newExitMaybe(info)
   770  	return p, pb.MessageType_MESSAGE_SYSCALL_BIND
   771  }
   772  
   773  func acceptHelper(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo, flags int32) (proto.Message, pb.MessageType) {
   774  	p := &pb.Accept{
   775  		ContextData: cxtData,
   776  		Sysno:       uint64(info.Sysno),
   777  		Fd:          info.Args[0].Int(),
   778  		Flags:       flags,
   779  	}
   780  	addr := info.Args[1].Pointer()
   781  	if addrLenPointer := info.Args[2].Pointer(); addrLenPointer != 0 {
   782  		var addrLen uint32
   783  		if _, err := primitive.CopyUint32In(t, addrLenPointer, &addrLen); err == nil { // if NO error
   784  			if address, err := CaptureAddress(t, addr, addrLen); err == nil { // if NO error
   785  				p.Address = address
   786  			}
   787  		}
   788  	}
   789  
   790  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   791  		p.FdPath = getFilePath(t, int32(p.Fd))
   792  	}
   793  
   794  	p.Exit = newExitMaybe(info)
   795  	return p, pb.MessageType_MESSAGE_SYSCALL_ACCEPT
   796  }
   797  
   798  // PointAccept converts accept(2) syscall to proto.
   799  func PointAccept(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   800  	return acceptHelper(t, fields, cxtData, info, 0)
   801  }
   802  
   803  // PointAccept4 converts accept4(2) syscall to proto.
   804  func PointAccept4(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   805  	flags := info.Args[3].Int()
   806  	return acceptHelper(t, fields, cxtData, info, flags)
   807  }
   808  
   809  // PointTimerfdCreate converts timerfd_create(2) syscall to proto.
   810  func PointTimerfdCreate(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   811  	p := &pb.TimerfdCreate{
   812  		ContextData: cxtData,
   813  		Sysno:       uint64(info.Sysno),
   814  		ClockId:     info.Args[0].Int(),
   815  		Flags:       info.Args[1].Int(),
   816  	}
   817  
   818  	p.Exit = newExitMaybe(info)
   819  	return p, pb.MessageType_MESSAGE_SYSCALL_TIMERFD_CREATE
   820  }
   821  
   822  func getValues(values linux.Timespec) *pb.Timespec {
   823  	return &pb.Timespec{
   824  		Sec:  values.Sec,
   825  		Nsec: values.Nsec,
   826  	}
   827  }
   828  
   829  // PointTimerfdSettime converts timerfd_settime(2) syscall to proto.
   830  func PointTimerfdSettime(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   831  	p := &pb.TimerfdSetTime{
   832  		ContextData: cxtData,
   833  		Sysno:       uint64(info.Sysno),
   834  		Fd:          info.Args[0].Int(),
   835  		Flags:       info.Args[1].Int(),
   836  	}
   837  
   838  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   839  		p.FdPath = getFilePath(t, int32(p.Fd))
   840  	}
   841  
   842  	var newVal linux.Itimerspec
   843  	if newValAddr := info.Args[2].Pointer(); newValAddr != 0 {
   844  		if _, err := newVal.CopyIn(t, newValAddr); err == nil {
   845  			p.NewValue = &pb.ItimerSpec{
   846  				Interval: getValues(newVal.Interval),
   847  				Value:    getValues(newVal.Value),
   848  			}
   849  		}
   850  	}
   851  	if info.Exit {
   852  		var oldVal linux.Itimerspec
   853  		if oldValAddr := info.Args[3].Pointer(); oldValAddr != 0 {
   854  			if _, err := oldVal.CopyIn(t, oldValAddr); err == nil {
   855  				p.OldValue = &pb.ItimerSpec{
   856  					Interval: getValues(oldVal.Interval),
   857  					Value:    getValues(oldVal.Value),
   858  				}
   859  			}
   860  		}
   861  	}
   862  
   863  	p.Exit = newExitMaybe(info)
   864  	return p, pb.MessageType_MESSAGE_SYSCALL_TIMERFD_SETTIME
   865  }
   866  
   867  // PointTimerfdGettime converts timerfd_gettime(2) syscall to proto.
   868  func PointTimerfdGettime(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   869  	p := &pb.TimerfdGetTime{
   870  		ContextData: cxtData,
   871  		Sysno:       uint64(info.Sysno),
   872  		Fd:          info.Args[0].Int(),
   873  	}
   874  
   875  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   876  		p.FdPath = getFilePath(t, int32(p.Fd))
   877  	}
   878  
   879  	if curValAddr := info.Args[1].Pointer(); curValAddr != 0 {
   880  		var curVal linux.Itimerspec
   881  		if _, err := curVal.CopyIn(t, curValAddr); err == nil {
   882  			p.CurValue = &pb.ItimerSpec{
   883  				Interval: getValues(curVal.Interval),
   884  				Value:    getValues(curVal.Value),
   885  			}
   886  		}
   887  	}
   888  
   889  	p.Exit = newExitMaybe(info)
   890  	return p, pb.MessageType_MESSAGE_SYSCALL_TIMERFD_GETTIME
   891  }
   892  
   893  // pointForkHelper converts fork(2) and vfork(2) syscall to proto.
   894  func pointForkHelper(cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   895  	p := &pb.Fork{
   896  		ContextData: cxtData,
   897  		Sysno:       uint64(info.Sysno),
   898  	}
   899  
   900  	p.Exit = newExitMaybe(info)
   901  	return p, pb.MessageType_MESSAGE_SYSCALL_FORK
   902  }
   903  
   904  // PointFork converts fork(2) syscall to proto.
   905  func PointFork(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   906  	return pointForkHelper(cxtData, info)
   907  }
   908  
   909  // PointVfork converts vfork(2) syscall to proto.
   910  func PointVfork(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   911  	return pointForkHelper(cxtData, info)
   912  }
   913  
   914  // pointInotifyInitHelper converts inotify_init(2) and inotify_init1(2) syscall to proto.
   915  func pointInotifyInitHelper(cxtData *pb.ContextData, info kernel.SyscallInfo, flags int32) (proto.Message, pb.MessageType) {
   916  	p := &pb.InotifyInit{
   917  		ContextData: cxtData,
   918  		Sysno:       uint64(info.Sysno),
   919  		Flags:       flags,
   920  	}
   921  
   922  	p.Exit = newExitMaybe(info)
   923  	return p, pb.MessageType_MESSAGE_SYSCALL_INOTIFY_INIT
   924  }
   925  
   926  // PointInotifyInit converts inotify_init(2) syscall to proto.
   927  func PointInotifyInit(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   928  	return pointInotifyInitHelper(cxtData, info, 0)
   929  }
   930  
   931  // PointInotifyInit1 converts inotify_init1(2) syscall to proto.
   932  func PointInotifyInit1(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   933  	flags := info.Args[0].Int()
   934  	return pointInotifyInitHelper(cxtData, info, flags)
   935  }
   936  
   937  // PointInotifyAddWatch converts inotify_add_watch(2) syscall to proto.
   938  func PointInotifyAddWatch(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   939  	p := &pb.InotifyAddWatch{
   940  		ContextData: cxtData,
   941  		Sysno:       uint64(info.Sysno),
   942  		Fd:          info.Args[0].Int(),
   943  		Mask:        info.Args[2].Uint(),
   944  	}
   945  	if pathAddr := info.Args[1].Pointer(); pathAddr > 0 {
   946  		p.Pathname, _ = t.CopyInString(pathAddr, linux.PATH_MAX)
   947  	}
   948  
   949  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   950  		p.FdPath = getFilePath(t, int32(p.Fd))
   951  	}
   952  
   953  	p.Exit = newExitMaybe(info)
   954  	return p, pb.MessageType_MESSAGE_SYSCALL_INOTIFY_ADD_WATCH
   955  }
   956  
   957  // PointInotifyRmWatch converts inotify_add_watch(2) syscall to proto.
   958  func PointInotifyRmWatch(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   959  	p := &pb.InotifyRmWatch{
   960  		ContextData: cxtData,
   961  		Sysno:       uint64(info.Sysno),
   962  		Fd:          info.Args[0].Int(),
   963  		Wd:          info.Args[2].Int(),
   964  	}
   965  
   966  	if fields.Local.Contains(seccheck.FieldSyscallPath) {
   967  		p.FdPath = getFilePath(t, int32(p.Fd))
   968  	}
   969  
   970  	p.Exit = newExitMaybe(info)
   971  	return p, pb.MessageType_MESSAGE_SYSCALL_INOTIFY_RM_WATCH
   972  }
   973  
   974  // PointSocketpair converts socketpair(2) syscall to proto.
   975  func PointSocketpair(t *kernel.Task, fields seccheck.FieldSet, cxtData *pb.ContextData, info kernel.SyscallInfo) (proto.Message, pb.MessageType) {
   976  	p := &pb.SocketPair{
   977  		ContextData: cxtData,
   978  		Sysno:       uint64(info.Sysno),
   979  		Domain:      info.Args[0].Int(),
   980  		Type:        info.Args[1].Int(),
   981  		Protocol:    info.Args[2].Int(),
   982  	}
   983  	if info.Exit {
   984  		sockets := info.Args[3].Pointer()
   985  		var fds [2]int32
   986  		if _, err := primitive.CopyInt32SliceIn(t, sockets, fds[:]); err == nil { // if NO error
   987  			p.Socket1 = fds[0]
   988  			p.Socket2 = fds[1]
   989  		}
   990  	}
   991  	p.Exit = newExitMaybe(info)
   992  	return p, pb.MessageType_MESSAGE_SYSCALL_SOCKETPAIR
   993  }