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 }