26
26
#include <stddef.h>
27
27
#include <stdint.h>
28
28
#include <stdlib.h>
29
+ #include <string.h>
29
30
#include <sys/queue.h>
30
31
31
32
#include "common.h"
@@ -113,6 +114,14 @@ struct codegen_ctxt {
113
114
size_t max_stack_ptr ;
114
115
};
115
116
117
+ void free_sock_program (struct sock_fprog * prog ) {
118
+ ASSERT (prog );
119
+
120
+ if (prog -> filter ) free (prog -> filter );
121
+ prog -> filter = NULL ;
122
+ prog -> len = 0 ;
123
+ }
124
+
116
125
static struct codegen_ctxt * context_create (void ) {
117
126
struct codegen_ctxt * ctxt = calloc (1 , sizeof (* ctxt ));
118
127
ctxt -> buffer .capacity = CODEGEN_INITAL_BUFFER_SIZE ;
@@ -288,6 +297,8 @@ static int add_jump_set(struct codegen_ctxt *ctxt, __u32 what, int tloc,
288
297
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr))
289
298
#define BPF_LOAD_ARG_WORD (arg , high ) \
290
299
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, ARG_WORD(arg, high))
300
+ #define BPF_NEXT_ARCH_MARKER \
301
+ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 0x12345678)
291
302
292
303
static bool is_const_value (struct expr_tree * expr , int word ) {
293
304
return word == HIGH_WORD ? expr -> high .is_const : expr -> low .is_const ;
@@ -615,15 +626,23 @@ int compile_policy(struct kafel_ctxt *kafel_ctxt, struct sock_fprog *prog) {
615
626
normalize_rules (rules , kafel_ctxt -> default_action );
616
627
int begin = CURRENT_LOC ;
617
628
int next = generate_rules (ctxt , rules -> data , rules -> len );
629
+ int next2 = 0 ;
618
630
range_rules_destroy (& rules );
619
631
if (next > begin ) {
620
632
begin = next = ADD_INSTR (BPF_LOAD_SYSCALL );
633
+ if (!kafel_ctxt -> use_companion_arch ) {
634
+ next2 = ADD_INSTR (BPF_NEXT_ARCH_MARKER );
635
+ } else {
636
+ next2 = next ;
637
+ }
621
638
} else {
622
- next = - kafel_ctxt -> default_action ;
639
+ next2 = next = - kafel_ctxt -> default_action ;
623
640
}
624
- next = add_jump (ctxt , BPF_JEQ , kafel_ctxt -> target_arch , next , - ACTION_KILL );
625
- if (next > begin ) {
626
- begin = next = ADD_INSTR (BPF_LOAD_ARCH );
641
+ if (!kafel_ctxt -> use_companion_arch ) {
642
+ next = add_jump (ctxt , BPF_JEQ , kafel_ctxt -> target_arch , next , next2 );
643
+ if (next > begin ) {
644
+ begin = next = ADD_INSTR (BPF_LOAD_ARCH );
645
+ }
627
646
}
628
647
if (next < 0 ) {
629
648
resolve_location (ctxt , next );
@@ -639,3 +658,89 @@ int compile_policy(struct kafel_ctxt *kafel_ctxt, struct sock_fprog *prog) {
639
658
context_destroy (& ctxt );
640
659
return rv ;
641
660
}
661
+
662
+ int knit_policy (struct kafel_ctxt * kafel_ctxt ,
663
+ struct sock_fprog * target_programs ,
664
+ struct sock_fprog * companion_programs ,
665
+ int default_action ,
666
+ struct sock_fprog * prog )
667
+ {
668
+ unsigned char i = 0 ;
669
+ uint32_t j = 0 ;
670
+ uint32_t k = 0 ;
671
+ uint32_t cur_target_policy_start = 0 ;
672
+ uint32_t total_count = 1 ;
673
+
674
+ for (i = 0 ; i < MAX_TARGET_ARCHS ; i ++ ) {
675
+ if (!target_programs [i ].len ) continue ;
676
+ total_count += target_programs [i ].len ;
677
+ if (!companion_programs [i ].len ) continue ;
678
+ total_count += companion_programs [i ].len ;
679
+ }
680
+
681
+ struct sock_filter * filters = calloc (total_count , sizeof (struct sock_filter ));
682
+ if (!filters ) {
683
+ append_error (kafel_ctxt , "Cannot allocate %d bytes of memory" ,
684
+ total_count * sizeof (struct sock_filter ));
685
+
686
+ for (i = 0 ; i < MAX_TARGET_ARCHS ; i ++ ) {
687
+ free_sock_program (& target_programs [i ]);
688
+ free_sock_program (& companion_programs [i ]);
689
+ }
690
+
691
+ return -1 ;
692
+ }
693
+
694
+ for (i = 0 ; i < MAX_TARGET_ARCHS ; i ++ ) {
695
+ if (!target_programs [i ].len ) continue ;
696
+
697
+ cur_target_policy_start = k ;
698
+
699
+ memcpy (& filters [k ], target_programs [i ].filter ,
700
+ target_programs [i ].len * sizeof (struct sock_filter ));
701
+ k += target_programs [i ].len ;
702
+
703
+ if (companion_programs [i ].len ) {
704
+ // In parent policy replace default action with JA
705
+ // to start of companion policy
706
+
707
+ for (j = k - 1 ; j > (k - target_programs [i ].len ); j -- ) {
708
+ if (filters [j ].code == (BPF_RET | BPF_K ) &&
709
+ filters [j ].jt == 0 &&
710
+ filters [j ].jf == 0 &&
711
+ filters [j ].k == ACTION_TO_BPF (default_action )) {
712
+ filters [j ].code = BPF_JMP | BPF_JA ;
713
+ filters [j ].k = k - j - 1 ;
714
+ break ;
715
+ }
716
+ }
717
+
718
+ memcpy (& filters [k ], companion_programs [i ].filter ,
719
+ companion_programs [i ].len * sizeof (struct sock_filter ));
720
+ k += companion_programs [i ].len ;
721
+ }
722
+
723
+ // Replace marker JA to next parent policy
724
+
725
+ for (j = cur_target_policy_start ; j < k ; j ++ ) {
726
+ if (filters [j ].code == (BPF_LD + BPF_W + BPF_ABS ) &&
727
+ filters [j ].jt == 0 &&
728
+ filters [j ].jf == 0 &&
729
+ filters [j ].k == 0x12345678 ) {
730
+ filters [j ].code = BPF_JMP | BPF_JA ;
731
+ filters [j ].k = k - j - 1 ;
732
+ break ;
733
+ }
734
+ }
735
+ }
736
+
737
+ // Finally, add one KILL statement to complete jumps
738
+
739
+ filters [total_count - 1 ].code = BPF_RET | BPF_K ;
740
+ filters [total_count - 1 ].k = SECCOMP_RET_KILL ;
741
+
742
+ prog -> len = total_count ;
743
+ prog -> filter = filters ;
744
+
745
+ return 0 ;
746
+ }
0 commit comments