gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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 "gvisor.dev/gvisor/pkg/abi/linux" 22 "gvisor.dev/gvisor/pkg/hostarch" 23 "gvisor.dev/gvisor/pkg/marshal/primitive" 24 "gvisor.dev/gvisor/pkg/sentry/kernel" 25 "gvisor.dev/gvisor/pkg/sentry/seccheck" 26 pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto" 27 "gvisor.dev/gvisor/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(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 }