github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/compiler/eval/model_test.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 // Package eval holds eval related files 7 package eval 8 9 import ( 10 "container/list" 11 "fmt" 12 "net" 13 "reflect" 14 "syscall" 15 "unsafe" 16 ) 17 18 var legacyFields = map[Field]Field{ 19 "process.legacy_name": "process.name", 20 } 21 22 type testItem struct { 23 key int 24 value string 25 flag bool 26 } 27 28 type testProcess struct { 29 name string 30 argv0 string 31 uid int 32 gid int 33 pid int 34 isRoot bool 35 list *list.List 36 array []*testItem 37 createdAt int64 38 39 // overridden values 40 orName string 41 orNameValues func() *StringValues 42 orArray []*testItem 43 orArrayValues func() *StringValues 44 } 45 46 type testItemListIterator struct { 47 prev *list.Element 48 } 49 50 func (t *testItemListIterator) Front(ctx *Context) unsafe.Pointer { 51 if front := ctx.Event.(*testEvent).process.list.Front(); front != nil { 52 t.prev = front 53 return unsafe.Pointer(front) 54 } 55 return nil 56 } 57 58 func (t *testItemListIterator) Next() unsafe.Pointer { 59 if next := t.prev.Next(); next != nil { 60 t.prev = next 61 return unsafe.Pointer(next) 62 } 63 return nil 64 } 65 66 type testItemArrayIterator struct { 67 event *testEvent 68 index int 69 } 70 71 func (t *testItemArrayIterator) Front(ctx *Context) unsafe.Pointer { 72 t.event = ctx.Event.(*testEvent) 73 74 array := ctx.Event.(*testEvent).process.array 75 if t.index < len(array) { 76 t.index++ 77 return unsafe.Pointer(array[0]) 78 } 79 return nil 80 } 81 82 func (t *testItemArrayIterator) Next() unsafe.Pointer { 83 array := t.event.process.array 84 if t.index < len(array) { 85 value := array[t.index] 86 t.index++ 87 88 return unsafe.Pointer(value) 89 } 90 91 return nil 92 } 93 94 type testOpen struct { 95 filename string 96 mode int 97 flags int 98 openedAt int64 99 } 100 101 type testMkdir struct { 102 filename string 103 mode int 104 } 105 106 type testNetwork struct { 107 ip net.IPNet 108 ips []net.IPNet 109 cidr net.IPNet 110 cidrs []net.IPNet 111 } 112 113 type testEvent struct { 114 id string 115 kind string 116 117 process testProcess 118 network testNetwork 119 open testOpen 120 mkdir testMkdir 121 122 listEvaluated bool 123 uidEvaluated bool 124 gidEvaluated bool 125 } 126 127 type testModel struct { 128 } 129 130 func (e *testEvent) GetType() string { 131 return e.kind 132 } 133 134 func (e *testEvent) GetTags() []string { 135 return []string{} 136 } 137 138 func (m *testModel) NewEvent() Event { 139 return &testEvent{} 140 } 141 142 func (m *testModel) ValidateField(key string, value FieldValue) error { 143 switch key { 144 case "process.uid": 145 uid, ok := value.Value.(int) 146 if !ok { 147 return fmt.Errorf("invalid type for process.ui: %v", reflect.TypeOf(value.Value)) 148 } 149 150 if uid < 0 { 151 return fmt.Errorf("process.uid cannot be negative: %d", uid) 152 } 153 } 154 155 return nil 156 } 157 158 func (m *testModel) GetIterator(field Field) (Iterator, error) { 159 switch field { 160 case "process.list": 161 return &testItemListIterator{}, nil 162 case "process.array": 163 return &testItemArrayIterator{}, nil 164 } 165 166 return nil, &ErrIteratorNotSupported{Field: field} 167 } 168 169 func (m *testModel) GetEvaluator(field Field, _ RegisterID) (Evaluator, error) { 170 switch field { 171 172 case "network.ip": 173 174 return &CIDREvaluator{ 175 EvalFnc: func(ctx *Context) net.IPNet { 176 return ctx.Event.(*testEvent).network.ip 177 }, 178 Field: field, 179 }, nil 180 181 case "network.cidr": 182 183 return &CIDREvaluator{ 184 EvalFnc: func(ctx *Context) net.IPNet { 185 return ctx.Event.(*testEvent).network.cidr 186 }, 187 Field: field, 188 }, nil 189 190 case "network.ips": 191 192 return &CIDRArrayEvaluator{ 193 EvalFnc: func(ctx *Context) []net.IPNet { 194 var ipnets []net.IPNet 195 ipnets = append(ipnets, ctx.Event.(*testEvent).network.ips...) 196 return ipnets 197 }, 198 }, nil 199 200 case "network.cidrs": 201 202 return &CIDRArrayEvaluator{ 203 EvalFnc: func(ctx *Context) []net.IPNet { 204 return ctx.Event.(*testEvent).network.cidrs 205 }, 206 Field: field, 207 }, nil 208 209 case "process.name": 210 211 return &StringEvaluator{ 212 EvalFnc: func(ctx *Context) string { return ctx.Event.(*testEvent).process.name }, 213 Field: field, 214 OpOverrides: GlobCmp, 215 }, nil 216 217 case "process.argv0": 218 219 return &StringEvaluator{ 220 EvalFnc: func(ctx *Context) string { return ctx.Event.(*testEvent).process.argv0 }, 221 Field: field, 222 }, nil 223 224 case "process.uid": 225 226 return &IntEvaluator{ 227 EvalFnc: func(ctx *Context) int { 228 // to test optimisation 229 ctx.Event.(*testEvent).uidEvaluated = true 230 231 return ctx.Event.(*testEvent).process.uid 232 }, 233 Field: field, 234 }, nil 235 236 case "process.gid": 237 238 return &IntEvaluator{ 239 EvalFnc: func(ctx *Context) int { 240 // to test optimisation 241 ctx.Event.(*testEvent).gidEvaluated = true 242 243 return ctx.Event.(*testEvent).process.gid 244 }, 245 Field: field, 246 }, nil 247 248 case "process.pid": 249 250 return &IntEvaluator{ 251 EvalFnc: func(ctx *Context) int { 252 // to test optimisation 253 ctx.Event.(*testEvent).uidEvaluated = true 254 255 return ctx.Event.(*testEvent).process.pid 256 }, 257 Field: field, 258 }, nil 259 260 case "process.is_root": 261 262 return &BoolEvaluator{ 263 EvalFnc: func(ctx *Context) bool { return ctx.Event.(*testEvent).process.isRoot }, 264 Field: field, 265 }, nil 266 267 case "process.list.key": 268 269 return &IntArrayEvaluator{ 270 EvalFnc: func(ctx *Context) []int { 271 // to test optimisation 272 ctx.Event.(*testEvent).listEvaluated = true 273 274 var result []int 275 276 el := ctx.Event.(*testEvent).process.list.Front() 277 for el != nil { 278 result = append(result, el.Value.(*testItem).key) 279 el = el.Next() 280 } 281 282 return result 283 }, 284 Field: field, 285 Weight: IteratorWeight, 286 }, nil 287 288 case "process.list.value": 289 290 return &StringArrayEvaluator{ 291 EvalFnc: func(ctx *Context) []string { 292 // to test optimisation 293 ctx.Event.(*testEvent).listEvaluated = true 294 295 var values []string 296 297 el := ctx.Event.(*testEvent).process.list.Front() 298 for el != nil { 299 values = append(values, el.Value.(*testItem).value) 300 el = el.Next() 301 } 302 303 return values 304 }, 305 Field: field, 306 Weight: IteratorWeight, 307 }, nil 308 309 case "process.list.flag": 310 311 return &BoolArrayEvaluator{ 312 EvalFnc: func(ctx *Context) []bool { 313 // to test optimisation 314 ctx.Event.(*testEvent).listEvaluated = true 315 316 var result []bool 317 318 el := ctx.Event.(*testEvent).process.list.Front() 319 for el != nil { 320 result = append(result, el.Value.(*testItem).flag) 321 el = el.Next() 322 } 323 324 return result 325 }, 326 Field: field, 327 Weight: IteratorWeight, 328 }, nil 329 330 case "process.array.key": 331 332 return &IntArrayEvaluator{ 333 EvalFnc: func(ctx *Context) []int { 334 var result []int 335 336 for _, el := range ctx.Event.(*testEvent).process.array { 337 result = append(result, el.key) 338 } 339 340 return result 341 }, 342 Field: field, 343 Weight: IteratorWeight, 344 }, nil 345 346 case "process.array.value": 347 348 return &StringArrayEvaluator{ 349 EvalFnc: func(ctx *Context) []string { 350 var values []string 351 352 for _, el := range ctx.Event.(*testEvent).process.array { 353 values = append(values, el.value) 354 } 355 356 return values 357 }, 358 Field: field, 359 Weight: IteratorWeight, 360 }, nil 361 362 case "process.array.flag": 363 364 return &BoolArrayEvaluator{ 365 EvalFnc: func(ctx *Context) []bool { 366 var result []bool 367 368 for _, el := range ctx.Event.(*testEvent).process.array { 369 result = append(result, el.flag) 370 } 371 372 return result 373 }, 374 Field: field, 375 Weight: IteratorWeight, 376 }, nil 377 378 case "process.created_at": 379 380 return &IntEvaluator{ 381 EvalFnc: func(ctx *Context) int { 382 return int(ctx.Event.(*testEvent).process.createdAt) 383 }, 384 Field: field, 385 }, nil 386 387 case "process.or_name": 388 389 return &StringEvaluator{ 390 EvalFnc: func(ctx *Context) string { 391 return ctx.Event.(*testEvent).process.orName 392 }, 393 Field: field, 394 OpOverrides: &OpOverrides{ 395 StringValuesContains: func(a *StringEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) { 396 evaluator := StringValuesEvaluator{ 397 EvalFnc: func(ctx *Context) *StringValues { 398 return ctx.Event.(*testEvent).process.orNameValues() 399 }, 400 } 401 402 return StringValuesContains(a, &evaluator, state) 403 }, 404 StringEquals: func(a *StringEvaluator, b *StringEvaluator, state *State) (*BoolEvaluator, error) { 405 evaluator := StringValuesEvaluator{ 406 EvalFnc: func(ctx *Context) *StringValues { 407 return ctx.Event.(*testEvent).process.orNameValues() 408 }, 409 } 410 411 return StringValuesContains(a, &evaluator, state) 412 }, 413 }, 414 }, nil 415 416 case "process.or_array.value": 417 418 return &StringArrayEvaluator{ 419 EvalFnc: func(ctx *Context) []string { 420 var values []string 421 422 for _, el := range ctx.Event.(*testEvent).process.orArray { 423 values = append(values, el.value) 424 } 425 426 return values 427 }, 428 Field: field, 429 OpOverrides: &OpOverrides{ 430 StringArrayContains: func(a *StringEvaluator, b *StringArrayEvaluator, state *State) (*BoolEvaluator, error) { 431 evaluator := StringValuesEvaluator{ 432 EvalFnc: func(ctx *Context) *StringValues { 433 return ctx.Event.(*testEvent).process.orArrayValues() 434 }, 435 } 436 437 return StringArrayMatches(b, &evaluator, state) 438 }, 439 StringArrayMatches: func(a *StringArrayEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) { 440 evaluator := StringValuesEvaluator{ 441 EvalFnc: func(ctx *Context) *StringValues { 442 return ctx.Event.(*testEvent).process.orArrayValues() 443 }, 444 } 445 446 return StringArrayMatches(a, &evaluator, state) 447 }, 448 }, 449 }, nil 450 451 case "open.filename": 452 453 return &StringEvaluator{ 454 EvalFnc: func(ctx *Context) string { return ctx.Event.(*testEvent).open.filename }, 455 Field: field, 456 }, nil 457 458 case "open.flags": 459 460 return &IntEvaluator{ 461 EvalFnc: func(ctx *Context) int { return ctx.Event.(*testEvent).open.flags }, 462 Field: field, 463 }, nil 464 465 case "open.mode": 466 467 return &IntEvaluator{ 468 EvalFnc: func(ctx *Context) int { return ctx.Event.(*testEvent).open.mode }, 469 Field: field, 470 }, nil 471 472 case "open.opened_at": 473 474 return &IntEvaluator{ 475 EvalFnc: func(ctx *Context) int { 476 return int(ctx.Event.(*testEvent).open.openedAt) 477 }, 478 Field: field, 479 }, nil 480 481 case "mkdir.filename": 482 483 return &StringEvaluator{ 484 EvalFnc: func(ctx *Context) string { return ctx.Event.(*testEvent).mkdir.filename }, 485 Field: field, 486 }, nil 487 488 case "mkdir.mode": 489 490 return &IntEvaluator{ 491 EvalFnc: func(ctx *Context) int { return ctx.Event.(*testEvent).mkdir.mode }, 492 Field: field, 493 }, nil 494 } 495 496 return nil, &ErrFieldNotFound{Field: field} 497 } 498 499 func (e *testEvent) Init() {} 500 501 func (e *testEvent) GetFieldValue(field Field) (interface{}, error) { 502 switch field { 503 504 case "network.ip": 505 return e.network.ip, nil 506 507 case "network.ips": 508 return e.network.ips, nil 509 510 case "network.cidr": 511 return e.network.cidr, nil 512 513 case "network.cidrs": 514 return e.network.cidrs, nil 515 516 case "process.name": 517 518 return e.process.name, nil 519 520 case "process.argv0": 521 522 return e.process.argv0, nil 523 524 case "process.uid": 525 526 return e.process.uid, nil 527 528 case "process.gid": 529 530 return e.process.gid, nil 531 532 case "process.pid": 533 534 return e.process.pid, nil 535 536 case "process.is_root": 537 538 return e.process.isRoot, nil 539 540 case "process.created_at": 541 542 return e.process.createdAt, nil 543 544 case "open.filename": 545 546 return e.open.filename, nil 547 548 case "open.flags": 549 550 return e.open.flags, nil 551 552 case "open.mode": 553 554 return e.open.mode, nil 555 556 case "open.opened_at": 557 558 return e.open.openedAt, nil 559 560 case "mkdir.filename": 561 562 return e.mkdir.filename, nil 563 564 case "mkdir.mode": 565 566 return e.mkdir.mode, nil 567 568 } 569 570 return nil, &ErrFieldNotFound{Field: field} 571 } 572 573 func (e *testEvent) GetFieldEventType(field Field) (string, error) { 574 switch field { 575 576 case "network.ip": 577 578 return "network", nil 579 580 case "network.ips": 581 582 return "network", nil 583 584 case "network.cidr": 585 586 return "network", nil 587 588 case "network.cidrs": 589 590 return "network", nil 591 592 case "process.name": 593 594 return "*", nil 595 596 case "process.argv0": 597 598 return "*", nil 599 600 case "process.uid": 601 602 return "*", nil 603 604 case "process.gid": 605 606 return "*", nil 607 608 case "process.pid": 609 610 return "*", nil 611 612 case "process.is_root": 613 614 return "*", nil 615 616 case "process.list.key": 617 618 return "*", nil 619 620 case "process.list.value": 621 622 return "*", nil 623 624 case "process.list.flag": 625 626 return "*", nil 627 628 case "process.array.key": 629 630 return "*", nil 631 632 case "process.array.value": 633 634 return "*", nil 635 636 case "process.array.flag": 637 638 return "*", nil 639 640 case "process.created_at": 641 642 return "*", nil 643 644 case "process.or_name": 645 646 return "*", nil 647 648 case "process.or_array.value": 649 650 return "*", nil 651 652 case "open.filename": 653 654 return "open", nil 655 656 case "open.flags": 657 658 return "open", nil 659 660 case "open.mode": 661 662 return "open", nil 663 664 case "open.opened_at": 665 666 return "open", nil 667 668 case "mkdir.filename": 669 670 return "mkdir", nil 671 672 case "mkdir.mode": 673 674 return "mkdir", nil 675 676 } 677 678 return "", &ErrFieldNotFound{Field: field} 679 } 680 681 func (e *testEvent) SetFieldValue(field Field, value interface{}) error { 682 switch field { 683 684 case "network.ip": 685 686 e.network.ip = value.(net.IPNet) 687 return nil 688 689 case "network.ips": 690 691 e.network.ips = value.([]net.IPNet) 692 693 case "network.cidr": 694 695 e.network.cidr = value.(net.IPNet) 696 return nil 697 698 case "network.cidrs": 699 700 e.network.cidrs = value.([]net.IPNet) 701 return nil 702 703 case "process.name": 704 705 e.process.name = value.(string) 706 return nil 707 708 case "process.argv0": 709 710 e.process.argv0 = value.(string) 711 return nil 712 713 case "process.uid": 714 715 e.process.uid = value.(int) 716 return nil 717 718 case "process.gid": 719 720 e.process.gid = value.(int) 721 return nil 722 723 case "process.pid": 724 725 e.process.pid = value.(int) 726 return nil 727 728 case "process.is_root": 729 730 e.process.isRoot = value.(bool) 731 return nil 732 733 case "process.created_at": 734 735 e.process.createdAt = value.(int64) 736 return nil 737 738 case "open.filename": 739 740 e.open.filename = value.(string) 741 return nil 742 743 case "open.flags": 744 745 e.open.flags = value.(int) 746 return nil 747 748 case "open.mode": 749 750 e.open.mode = value.(int) 751 return nil 752 753 case "open.opened_at": 754 755 e.open.openedAt = value.(int64) 756 return nil 757 758 case "mkdir.filename": 759 760 e.mkdir.filename = value.(string) 761 return nil 762 763 case "mkdir.mode": 764 765 e.mkdir.mode = value.(int) 766 return nil 767 768 } 769 770 return &ErrFieldNotFound{Field: field} 771 } 772 773 func (e *testEvent) GetFieldType(field Field) (reflect.Kind, error) { 774 switch field { 775 776 case "network.ip": 777 778 return reflect.Struct, nil 779 780 case "network.ips": 781 782 return reflect.Array, nil 783 784 case "network.cidr": 785 786 return reflect.Struct, nil 787 788 case "network.cidrs": 789 790 return reflect.Array, nil 791 792 case "process.name": 793 794 return reflect.String, nil 795 796 case "process.argv0": 797 798 return reflect.String, nil 799 800 case "process.uid": 801 802 return reflect.Int, nil 803 804 case "process.gid": 805 806 return reflect.Int, nil 807 808 case "process.pid": 809 810 return reflect.Int, nil 811 812 case "process.is_root": 813 814 return reflect.Bool, nil 815 816 case "process.list.key": 817 return reflect.Int, nil 818 819 case "process.list.value": 820 return reflect.Int, nil 821 822 case "process.list.flag": 823 return reflect.Bool, nil 824 825 case "process.array.key": 826 return reflect.Int, nil 827 828 case "process.array.value": 829 return reflect.String, nil 830 831 case "process.array.flag": 832 return reflect.Bool, nil 833 834 case "open.filename": 835 836 return reflect.String, nil 837 838 case "open.flags": 839 840 return reflect.Int, nil 841 842 case "open.mode": 843 844 return reflect.Int, nil 845 846 case "mkdir.filename": 847 848 return reflect.String, nil 849 850 case "mkdir.mode": 851 852 return reflect.Int, nil 853 854 } 855 856 return reflect.Invalid, &ErrFieldNotFound{Field: field} 857 } 858 859 var testConstants = map[string]interface{}{ 860 // boolean 861 "true": &BoolEvaluator{Value: true}, 862 "false": &BoolEvaluator{Value: false}, 863 864 // open flags 865 "O_RDONLY": &IntEvaluator{Value: syscall.O_RDONLY}, 866 "O_WRONLY": &IntEvaluator{Value: syscall.O_WRONLY}, 867 "O_RDWR": &IntEvaluator{Value: syscall.O_RDWR}, 868 "O_APPEND": &IntEvaluator{Value: syscall.O_APPEND}, 869 "O_CREAT": &IntEvaluator{Value: syscall.O_CREAT}, 870 "O_EXCL": &IntEvaluator{Value: syscall.O_EXCL}, 871 "O_SYNC": &IntEvaluator{Value: syscall.O_SYNC}, 872 "O_TRUNC": &IntEvaluator{Value: syscall.O_TRUNC}, 873 }