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