[CRIU] [PATCH 3/7] seccomp: add support for SECCOMP_MODE_FILTER

Tycho Andersen tycho.andersen at canonical.com
Fri Nov 13 13:58:18 PST 2015


On Thu, Nov 12, 2015 at 10:58:22AM +0300, Pavel Emelyanov wrote:
> 
> >>> +			continue;
> >>> +		}
> >>> +
> >>> +		info = xmalloc(sizeof(*info));
> >>> +		if (!info)
> >>> +			goto out;
> >>> +		seccomp_filter__init(&info->filter);
> >>> +
> >>> +		info->filter.filter.len = len * sizeof(struct sock_filter);
> >>> +		info->filter.filter.data = xmalloc(info->filter.filter.len);
> >>> +		if (!info->filter.filter.data)
> >>> +			goto out;
> >>> +
> >>> +		memcpy(info->filter.filter.data, buf, info->filter.filter.len);
> >>> +
> >>> +		info->prev = infos;
> >>> +		infos = info;
> >>> +	}
> >>> +
> >>> +save_infos:
> >>> +	info_count = i;
> >>> +
> >>> +	m = xrealloc(filters, sizeof(*filters) * (next_filter_id + info_count));
> >>
> >> Why do we allocate that many memory? Part of the filters where "inherited".
> >> Can you describe what kind of data structure is built behind the filters
> >> pointer? It's some tree, but I don't get how it exactly looks and how pstree
> >> items point inside it.
> > 
> > Yeah, this is a little strange. There are two sets of pointers to the
> > filters. The first is the "tree" style from pstree, used for resolving
> > inheritance relationships. The second set is this one, which is just a
> > big array with everything. This is used for dumping (and freeing) the
> > actual filters.
> > 
> > We could ditch the tree style ones from pstree and just use the big
> > array (and keep array ids in pstree), but it seemed a little nicer to
> > me this way. But I could be convinced otherwise :)
> 
> No no, keeping the tree relations inside the filters image and data structures
> is nice. But as far as the "big array" thing is concerned --
> 
> > --- /dev/null
> > +++ b/protobuf/seccomp.proto
> > @@ -0,0 +1,8 @@
> > +message seccomp_filter {
> > +	required bytes		filter			= 1;
> > +	optional uint32		prev			= 2;
> > +}
> > +
> > +message seccomp_entry {
> > +	repeated seccomp_filter		seccomp_filters	= 1;
> > +}
> 
> why do we need the seccomp_entry? Why not just put seccomp_filter entries
> into the image file one by one like it's done with pstree_entry-s?

You're right that we don't, I can rework it to get rid of that. We
still need the "big array" just to be able to free things (since
multiple pstrees can point to the same seccomp_filter and there is no
way of marking them "freed").

> >>> +int seccomp_filters_get_rst_pos(CoreEntry *core, int *count, unsigned long *pos)
> >>> +{
> >>> +	SeccompFilter *sf = NULL;
> >>> +	struct sock_fprog *arr = NULL;
> >>> +	int ret = -1, i;
> >>> +
> >>> +	if (!core->tc->has_seccomp_filter) {
> >>> +		*count = 0;
> >>> +		return 0;
> >>> +	}
> >>> +
> >>> +	*count = 0;
> >>> +	*pos = rst_mem_cpos(RM_PRIVATE);
> >>> +
> >>> +	BUG_ON(core->tc->seccomp_filter > se->n_seccomp_filters);
> >>> +	sf = se->seccomp_filters[core->tc->seccomp_filter];
> >>> +
> >>> +	while (1) {
> >>> +		(*count)++;
> >>> +
> >>> +		if (!sf->has_prev)
> >>> +			break;
> >>> +
> >>> +		sf = se->seccomp_filters[sf->prev];
> >>> +	}
> >>> +
> >>> +	arr = rst_mem_alloc(sizeof(*arr) * (*count), RM_PRIVATE);
> >>> +	if (!arr)
> >>> +		goto out;
> >>> +
> >>> +	sf = se->seccomp_filters[core->tc->seccomp_filter];
> >>> +	for (i = 0; i < *count; i++) {
> >>> +		struct sock_fprog *fprog = &arr[i];
> >>> +		// XXX: this is a bit fugly; is there a better way?
> >>
> >> I didn't get a better way for what you were looking for :)
> > 
> > The problem here is that we want to send a struct sock_fprog to the
> > restorer blob, which itself has a pointer to the actual instruction
> > array. So we want to pass a double pointer to the restorer blob. I
> > could do something like pack the second array onto the end of the
> > struct sock_fprog,
> 
> But you do it already, don't you? After you've allocated the arr thing
> in which sock_fprog-s are stored, you allocate more memory to the
> fprog->filter and put the fprog there.
> 
> > but it is nice to be able to refer to the first
> > array without having to do math by hand.
> > 
> > The solution here is to just save the rst_mem_alloc value into the
> > struct where the second level pointer goes, and then remap the result
> > after we remap the struct. That feels sort of broken, though :). But
> > maybe not.
> 
> Ah I see :) I can only one thing that comes to my mind, as you told above,
> in the seccomp_filters_get_rst_pos in fprog->filter you can save offset
> to fprog, omit the loop with remap_ptr-s in sigreturn_restore() and do
> the "math by hand" in pie's restore_seccomp. This would save us one for()
> loop and would keep all the logic in less code.

Less code here, but more code in the restorer blob where we have to do
a bunch of pointer math to figure out where things live. I could be
convinced that the extra pointer math was worth it, but I like this a
little better. Anyway, up to you :)

Tycho


More information about the CRIU mailing list