append_syscall_to_bpf(): Check for unlikely case of too many sock_filters
Tento commit je obsažen v:
rodič
dbf8e87440
revize
66def7a28f
41
exile.c
41
exile.c
@ -1046,8 +1046,18 @@ static int drop_caps()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void assign_filter(struct sock_filter *left, struct sock_filter *right, struct sock_filter *endfilter)
|
||||||
|
{
|
||||||
|
if(left <= endfilter)
|
||||||
|
{
|
||||||
|
*left = *right;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EXILE_LOG_ERROR("Too many syscall filters installed! Aborting.\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
static void append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, struct sock_filter *filter, unsigned short int *start_index)
|
static struct sock_filter *append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, struct sock_filter *filter, struct sock_filter *endfilter)
|
||||||
{
|
{
|
||||||
unsigned int action = syscallpolicy->policy;
|
unsigned int action = syscallpolicy->policy;
|
||||||
if(action == EXILE_SYSCALL_ALLOW)
|
if(action == EXILE_SYSCALL_ALLOW)
|
||||||
@ -1065,7 +1075,9 @@ static void append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, st
|
|||||||
long syscall = syscallpolicy->syscall;
|
long syscall = syscallpolicy->syscall;
|
||||||
|
|
||||||
struct sock_filter syscall_load = BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr));
|
struct sock_filter syscall_load = BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr));
|
||||||
filter[(*start_index)++] = syscall_load;
|
assign_filter(filter, &syscall_load, endfilter);
|
||||||
|
++filter;
|
||||||
|
|
||||||
if(syscall != EXILE_SYSCALL_MATCH_ALL)
|
if(syscall != EXILE_SYSCALL_MATCH_ALL)
|
||||||
{
|
{
|
||||||
/* How many steps forward to jump when we don't match. This is either the last statement,
|
/* How many steps forward to jump when we don't match. This is either the last statement,
|
||||||
@ -1074,11 +1086,11 @@ static void append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, st
|
|||||||
if(__builtin_add_overflow(next_syscall_pc, syscallpolicy->argfilterscount, &next_syscall_pc))
|
if(__builtin_add_overflow(next_syscall_pc, syscallpolicy->argfilterscount, &next_syscall_pc))
|
||||||
{
|
{
|
||||||
EXILE_LOG_ERROR("Overflow while trying to calculate jump offset\n");
|
EXILE_LOG_ERROR("Overflow while trying to calculate jump offset\n");
|
||||||
/* TODO: Return error */
|
abort();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
struct sock_filter syscall_check = EXILE_BPF_CMP_EQ((unsigned int) syscall, 0, next_syscall_pc);
|
struct sock_filter syscall_check = EXILE_BPF_CMP_EQ((unsigned int) syscall, 0, next_syscall_pc);
|
||||||
filter[(*start_index)++] = syscall_check;
|
assign_filter(filter, &syscall_check, endfilter);
|
||||||
|
++filter;
|
||||||
--next_syscall_pc;
|
--next_syscall_pc;
|
||||||
|
|
||||||
struct sock_filter return_matching = EXILE_BPF_RETURN_MATCHING;
|
struct sock_filter return_matching = EXILE_BPF_RETURN_MATCHING;
|
||||||
@ -1086,8 +1098,8 @@ static void append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, st
|
|||||||
|
|
||||||
for(size_t i = 0; i < syscallpolicy->argfilterscount; i++)
|
for(size_t i = 0; i < syscallpolicy->argfilterscount; i++)
|
||||||
{
|
{
|
||||||
filter[*start_index] = syscallpolicy->argfilters[i];
|
assign_filter(filter, &syscallpolicy->argfilters[i], endfilter);
|
||||||
struct sock_filter *current = &filter[*start_index];
|
struct sock_filter *current = filter;
|
||||||
__u8 jump_count_next_syscall = next_syscall_pc;
|
__u8 jump_count_next_syscall = next_syscall_pc;
|
||||||
__u8 jump_count_return = jump_count_next_syscall - 1;
|
__u8 jump_count_return = jump_count_next_syscall - 1;
|
||||||
if(current->jt == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
if(current->jt == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
@ -1115,13 +1127,13 @@ static void append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, st
|
|||||||
current->k = jump_count_next_syscall;
|
current->k = jump_count_next_syscall;
|
||||||
}
|
}
|
||||||
--next_syscall_pc;
|
--next_syscall_pc;
|
||||||
++*start_index;
|
++filter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct sock_filter syscall_action = BPF_STMT(BPF_RET+BPF_K, action);
|
struct sock_filter syscall_action = BPF_STMT(BPF_RET+BPF_K, action);
|
||||||
/* TODO: we can do better than adding this below every jump */
|
/* TODO: we can do better than adding this below every jump */
|
||||||
filter[(*start_index)++] = syscall_action;
|
assign_filter(filter, &syscall_action, endfilter);
|
||||||
|
return ++filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_valid_syscall_policy(unsigned int policy)
|
static int is_valid_syscall_policy(unsigned int policy)
|
||||||
@ -1149,7 +1161,8 @@ int exile_enable_syscall_policy(struct exile_policy *policy)
|
|||||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS),
|
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS),
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned short int current_filter_index = 6;
|
struct sock_filter *current_target = &filter[6];
|
||||||
|
struct sock_filter *end = &filter[1023];
|
||||||
|
|
||||||
struct exile_syscall_policy *current_policy = policy->syscall_policies;
|
struct exile_syscall_policy *current_policy = policy->syscall_policies;
|
||||||
while(current_policy)
|
while(current_policy)
|
||||||
@ -1159,13 +1172,13 @@ int exile_enable_syscall_policy(struct exile_policy *policy)
|
|||||||
EXILE_LOG_ERROR("invalid syscall policy specified\n");
|
EXILE_LOG_ERROR("invalid syscall policy specified\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* TODO: reintroduce overflow checks */
|
current_target = append_syscall_to_bpf(current_policy, current_target, end);
|
||||||
append_syscall_to_bpf(current_policy, filter, ¤t_filter_index);
|
|
||||||
current_policy = current_policy->next;
|
current_policy = current_policy->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned short len = (current_target - &filter[0]);
|
||||||
struct sock_fprog prog = {
|
struct sock_fprog prog = {
|
||||||
.len = current_filter_index ,
|
.len = len ,
|
||||||
.filter = filter,
|
.filter = filter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Načítá se…
Odkázat v novém úkolu
Zablokovat Uživatele