Hi all,
Here's a re-worked set for c/r of seccomp filters which keeps around the
original bpf program passed to the kernel instead of trying to dump the
ebpf version. There are various comments/questions in the individual patch
notes.
I'm not sure this needs to go via net-next any more, as the impact in net/
is fairly minimal, and it seems more seccomp heavy. As such, this set is
based on seccomp/tip.
Thoughts welcome,
Tycho
P.S. Man page patches to come once we agree on the API :)
In order to implement checkpoint of seccomp filters, we need to keep track
of the original filter as the user gave it to us. Since we're doing this,
we need to also use bpf_prog_destroy to free the struct bpf_brogs so we
don't leak this memory.
Signed-off-by: Tycho Andersen <redacted>
CC: Kees Cook <redacted>
CC: Will Drewry <wad@chromium.org>
CC: Oleg Nesterov <oleg@redhat.com>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Pavel Emelyanov <redacted>
CC: Serge E. Hallyn <redacted>
CC: Alexei Starovoitov <ast@kernel.org>
CC: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/filter.h | 2 ++
kernel/seccomp.c | 24 ++++++++++++++++--------
net/core/filter.c | 4 ++--
3 files changed, 20 insertions(+), 10 deletions(-)
In some cases (e.g. seccomp) the program result might be translated from
the original program the user supplied. If we're saving the result for
checkpoint/restore, we should save exactly the program the user initially
supplied.
This causes problems when the translations seccomp makes are not allowed by
bpf_check_classic.
Signed-off-by: Tycho Andersen <redacted>
CC: Kees Cook <redacted>
CC: Will Drewry <wad@chromium.org>
CC: Oleg Nesterov <oleg@redhat.com>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Pavel Emelyanov <redacted>
CC: Serge E. Hallyn <redacted>
CC: Alexei Starovoitov <ast@kernel.org>
CC: Daniel Borkmann <daniel@iogearbox.net>
---
net/core/filter.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
Signed-off-by: Tycho Andersen <redacted>
CC: Kees Cook <redacted>
CC: Will Drewry <wad@chromium.org>
CC: Oleg Nesterov <oleg@redhat.com>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Pavel Emelyanov <redacted>
CC: Serge E. Hallyn <redacted>
CC: Alexei Starovoitov <ast@kernel.org>
CC: Daniel Borkmann <daniel@iogearbox.net>
---
include/uapi/linux/kcmp.h | 1 +
kernel/kcmp.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
I just picked 40 for the constant out of thin air, but there may be a more
appropriate value for this. Also, we return EINVAL when there is no filter
for the index the user requested, but ptrace also returns EINVAL for
invalid commands, making it slightly awkward to test whether or not the
kernel supports this feature. It can still be done via,
if (is_in_mode_filter(pid)) {
int fd;
fd = ptrace(PTRACE_SECCOMP_GET_FILTER_FD, pid, NULL, 0);
if (fd < 0 && errno == -EINVAL)
/* not supported */
...
}
since being in SECCOMP_MODE_FILTER implies that there is at least one
filter. If there is a more appropriate errno (ESRCH collides as well with
ptrace) to give here that may be better.
Signed-off-by: Tycho Andersen <redacted>
CC: Kees Cook <redacted>
CC: Will Drewry <wad@chromium.org>
CC: Oleg Nesterov <oleg@redhat.com>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Pavel Emelyanov <redacted>
CC: Serge E. Hallyn <redacted>
CC: Alexei Starovoitov <ast@kernel.org>
CC: Daniel Borkmann <daniel@iogearbox.net>
---
include/linux/seccomp.h | 9 +++++++++
include/uapi/linux/ptrace.h | 2 ++
kernel/ptrace.c | 4 ++++
kernel/seccomp.c | 28 ++++++++++++++++++++++++++++
4 files changed, 43 insertions(+)
@@ -1016,6 +1016,10 @@ int ptrace_request(struct task_struct *child, long request,break;}#endif++casePTRACE_SECCOMP_GET_FILTER_FD:+returnseccomp_get_filter_fd(child,data);+default:break;}
@@ -1058,3 +1058,31 @@ long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)/* prctl interface doesn't have flags, so they are always zero. */returndo_seccomp(op,0,uargs);}++#if defined(CONFIG_CHECKPOINT_RESTORE) && defined(CONFIG_SECCOMP_FILTER)+longseccomp_get_filter_fd(structtask_struct*task,longn)+{+structseccomp_filter*filter;+longfd;++if(task->seccomp.mode!=SECCOMP_MODE_FILTER)+return-EINVAL;++filter=task->seccomp.filter;+while(n>0&&filter){+filter=filter->prev;+n--;+}++if(!filter)+return-EINVAL;++atomic_inc(&filter->usage);+fd=anon_inode_getfd("seccomp",&seccomp_fops,filter,+O_RDONLY|O_CLOEXEC);+if(fd<0)+seccomp_filter_decref(filter);++returnfd;+}+#endif
This patch introduces the concept of a seccomp fd, with a similar interface
and usage to ebpf fds. Initially, one is allowed to create, install, and
dump these fds. Any manipulation of seccomp fds requires users to be root
in their own user namespace, matching the checks done for
SECCOMP_SET_MODE_FILTER.
Installing a filterfd has some gotchas, though. Andy mentioned previously
that we should restrict installation to filter fds whose parent is already
in the filter tree. This doesn't quite work in the case of created seccomp
fds, since once you install a filter fd, you can't install any other filter
fd since it has no parent and there is no way to "pre-chain" filters before
installing them. To work around this, we allow installing filters who have
no parent. If the filter has a parent, we require the current filter try to
be an ancestor of it.
I'm not quite sure that the ancestor restriction is correct, since it can
still allow for "re-parenting" of filters, potentially introducing new
filters to a task. However, since these operations are limited to root in
the user ns, perhaps it is ok. There is also some potentially racy
behavior where a task re-parents a filter that another task has installed.
One option to work around this is to keep a bit on struct seccomp_filter to
allow each filter to have its parent set exactly once. (This would still
allow you to install a filter multiple times, as long as the parent was the
same in each case.)
Signed-off-by: Tycho Andersen <redacted>
CC: Kees Cook <redacted>
CC: Will Drewry <wad@chromium.org>
CC: Oleg Nesterov <oleg@redhat.com>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Pavel Emelyanov <redacted>
CC: Serge E. Hallyn <redacted>
CC: Alexei Starovoitov <ast@kernel.org>
CC: Daniel Borkmann <daniel@iogearbox.net>
---
include/uapi/linux/seccomp.h | 24 ++++++
kernel/seccomp.c | 189 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 210 insertions(+), 3 deletions(-)
@@ -58,6 +60,7 @@ struct seccomp_filter {atomic_tusage;structseccomp_filter*prev;structbpf_prog*prog;+spinlock_tprev_lock;};/* Limit any path through the tree to 256KB worth of instructions. */
@@ -441,6 +445,7 @@ static long seccomp_attach_filter(unsigned int flags,structseccomp_filter*walker;assert_spin_locked(¤t->sighand->siglock);+assert_spin_locked(&filter->prev_lock);/* Validate resulting filter length. */total_insns=filter->prog->len;
@@ -482,10 +487,8 @@ void get_seccomp_filter(struct task_struct *tsk)atomic_inc(&orig->usage);}-/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */-voidput_seccomp_filter(structtask_struct*tsk)+staticvoidseccomp_filter_decref(structseccomp_filter*orig){-structseccomp_filter*orig=tsk->seccomp.filter;/* Clean up single-reference branches iteratively. */while(orig&&atomic_dec_and_test(&orig->usage)){structseccomp_filter*freeme=orig;
@@ -494,6 +497,12 @@ void put_seccomp_filter(struct task_struct *tsk)}}+/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */+voidput_seccomp_filter(structtask_struct*tsk)+{+seccomp_filter_decref(tsk->seccomp.filter);+}+/***seccomp_send_sigsys-signalsthetasktoallowin-processsyscallemulation*@syscall:syscallnumbertosendtouserland
@@ -797,7 +806,9 @@ static long seccomp_set_mode_filter(unsigned int flags,if(!seccomp_may_assign_mode(seccomp_mode))gotoout;+spin_lock_irq(&prepared->prev_lock);ret=seccomp_attach_filter(flags,prepared);+spin_unlock_irq(&prepared->prev_lock);if(ret)gotoout;/* Do not free the successfully attached filter. */
@@ -812,12 +823,182 @@ out_free:seccomp_filter_free(prepared);returnret;}++intseccomp_fd_release(structinode*ino,structfile*f)+{+seccomp_filter_decref(f->private_data);+return0;+}++staticconststructfile_operationsseccomp_fops={+.release=seccomp_fd_release,+};++staticlongseccomp_fd_new(structseccomp_fd*seccomp_fd)+{+structseccomp_filter*filter;+longfd;+char__user*prog=(char__user*)seccomp_fd->new_prog;++filter=seccomp_prepare_user_filter(prog);+if(IS_ERR(filter))+returnPTR_ERR(filter);++fd=anon_inode_getfd("seccomp",&seccomp_fops,filter,+O_RDONLY|O_CLOEXEC);+if(fd<0)+seccomp_filter_decref(filter);++returnfd;+}++staticstructseccomp_filter*seccomp_filter_get(structfdf)+{+structseccomp_filter*filter;++if(!f.file)+returnERR_PTR(-EBADF);++if(f.file->f_op!=&seccomp_fops){+fdput(f);+returnERR_PTR(-EINVAL);+}++filter=f.file->private_data;++returnfilter;+}++staticlongseccomp_fd_install(structseccomp_fd*seccomp_fd)+{+structfdf;+structseccomp_filter*filter;+intret=-EINVAL;++f=fdget(seccomp_fd->install_fd);+filter=seccomp_filter_get(f);+if(IS_ERR(filter))+returnPTR_ERR(filter);+atomic_inc(&filter->usage);+fdput(f);++spin_lock_irq(¤t->sighand->siglock);+if(!seccomp_may_assign_mode(SECCOMP_MODE_FILTER))+gotoout_sigunlock;++spin_lock_irq(&filter->prev_lock);+if(filter->prev&&!is_ancestor(current->seccomp.filter,filter))+gotoout_prev_unlock;++ret=seccomp_attach_filter(0,filter);+/* This may be the first filter installed, so let's set mode */+if(ret>=0)+seccomp_assign_mode(current,SECCOMP_MODE_FILTER);++out_prev_unlock:+spin_unlock_irq(&filter->prev_lock);++out_sigunlock:+spin_unlock_irq(¤t->sighand->siglock);++/* If the filter failed to install, let's decref it */+if(ret<0)+seccomp_filter_decref(filter);+returnret;+}++staticlongseccomp_fd_dump(structseccomp_fd*seccomp_fd)+{+structfdf;+intlen;+structsock_fprog_kern*orig;+structseccomp_filter*filter;++f=fdget(seccomp_fd->dump_fd);+filter=seccomp_filter_get(f);+if(IS_ERR(filter))+returnPTR_ERR(filter);++orig=filter->prog->orig_prog;+len=bpf_classic_proglen(orig);++/* Allow asking how long the filter is by passing a null buffer. */+if(seccomp_fd->insns&&+copy_to_user(seccomp_fd->insns,orig->filter,len))+len=-EFAULT;++fdput(f);+returnlen;+}++staticlongseccomp_filter_fd(unsignedintcmd,+constchar__user*ulayer)+{+longret;+u32size;+structseccomp_fdseccomp_fd;+structseccomp_fd__user*useccomp_fd=+(structseccomp_fd__user*)ulayer;++/* As above, we restrict access to seccomp fds to processes who are+*rootintheirownuserns.+*/+if(!task_no_new_privs(current)&&+security_capable_noaudit(current_cred(),current_user_ns(),+CAP_SYS_ADMIN)!=0)+return-EACCES;++if(get_user(size,&useccomp_fd->size))+return-EFAULT;++if(size>sizeof(seccomp_fd)){+unsignedchar__user*addr;+unsignedchar__user*end;+unsignedcharval;++addr=(void__user*)useccomp_fd+sizeof(seccomp_fd);+end=(void__user*)useccomp_fd+size;++for(;addr<end;addr++){+if(get_user(val,addr))+return-EFAULT;+if(val)+return-E2BIG;+}+size=sizeof(seccomp_fd);+}++if(copy_from_user(&seccomp_fd,useccomp_fd,size))+return-EFAULT;++switch(cmd){+caseSECCOMP_FD_NEW:+ret=seccomp_fd_new(&seccomp_fd);+break;+caseSECCOMP_FD_INSTALL:+ret=seccomp_fd_install(&seccomp_fd);+break;+caseSECCOMP_FD_DUMP:+ret=seccomp_fd_dump(&seccomp_fd);+break;+default:+ret=-EINVAL;+}++returnret;+}#elsestaticinlinelongseccomp_set_mode_filter(unsignedintflags,constchar__user*filter){return-EINVAL;}++staticinlinelongseccomp_filter_fd(unsignedintflags+constchar__user*filter)+{+return-EINVAL;+}#endif/* Common entry point for both prctl and syscall. */
@@ -831,6 +1012,8 @@ static long do_seccomp(unsigned int op, unsigned int flags,returnseccomp_set_mode_strict();caseSECCOMP_SET_MODE_FILTER:returnseccomp_set_mode_filter(flags,uargs);+caseSECCOMP_FILTER_FD:+returnseccomp_filter_fd(flags,uargs);default:return-EINVAL;}
From: Andy Lutomirski <luto@amacapital.net> Date: 2015-09-30 18:26:23
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
--Andy
From: Andy Lutomirski <luto@amacapital.net> Date: 2015-09-30 18:27:58
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
This patch introduces the concept of a seccomp fd, with a similar interface
and usage to ebpf fds. Initially, one is allowed to create, install, and
dump these fds. Any manipulation of seccomp fds requires users to be root
in their own user namespace, matching the checks done for
SECCOMP_SET_MODE_FILTER.
Installing a filterfd has some gotchas, though. Andy mentioned previously
that we should restrict installation to filter fds whose parent is already
in the filter tree. This doesn't quite work in the case of created seccomp
fds, since once you install a filter fd, you can't install any other filter
fd since it has no parent and there is no way to "pre-chain" filters before
installing them.
ISTM, if we like the seccomp fd approach, we should have them be
created with a parent already set. IOW the default should be that
their parent is the creator's seccomp fd and, if needed, creators
could specify a different parent.
--Andy
From: kbuild test robot <hidden> Date: 2015-09-30 18:29:24
Hi Tycho,
[auto build test results on v4.3-rc3 -- if it's inappropriate base, please ignore]
config: i386-alldefconfig (attached as .config)
reproduce:
git checkout 9613ae6bf5f111701614acb3eda3123d21a59239
# save the attached .config to linux build tree
make ARCH=i386
All error/warnings (new ones prefixed by >>):
quoted
kernel/seccomp.c:998:10: error: expected ';', ',' or ')' before 'const'
const char __user *filter)
^
kernel/seccomp.c: In function 'do_seccomp':
quoted
kernel/seccomp.c:1016:10: error: implicit declaration of function 'seccomp_filter_fd' [-Werror=implicit-function-declaration]
return seccomp_filter_fd(flags, uargs);
^
cc1: some warnings being treated as errors
vim +998 kernel/seccomp.c
992 const char __user *filter)
993 {
994 return -EINVAL;
995 }
996
997 static inline long seccomp_filter_fd(unsigned int flags
> 998 const char __user *filter)
999 {
1000 return -EINVAL;
1001 }
1002 #endif
1003
1004 /* Common entry point for both prctl and syscall. */
1005 static long do_seccomp(unsigned int op, unsigned int flags,
1006 const char __user *uargs)
1007 {
1008 switch (op) {
1009 case SECCOMP_SET_MODE_STRICT:
1010 if (flags != 0 || uargs != NULL)
1011 return -EINVAL;
1012 return seccomp_set_mode_strict();
1013 case SECCOMP_SET_MODE_FILTER:
1014 return seccomp_set_mode_filter(flags, uargs);
1015 case SECCOMP_FILTER_FD:
1016 return seccomp_filter_fd(flags, uargs);
1017 default:
1018 return -EINVAL;
1019 }
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Wed, Sep 30, 2015 at 11:27:34AM -0700, Andy Lutomirski wrote:
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This patch introduces the concept of a seccomp fd, with a similar interface
and usage to ebpf fds. Initially, one is allowed to create, install, and
dump these fds. Any manipulation of seccomp fds requires users to be root
in their own user namespace, matching the checks done for
SECCOMP_SET_MODE_FILTER.
Installing a filterfd has some gotchas, though. Andy mentioned previously
that we should restrict installation to filter fds whose parent is already
in the filter tree. This doesn't quite work in the case of created seccomp
fds, since once you install a filter fd, you can't install any other filter
fd since it has no parent and there is no way to "pre-chain" filters before
installing them.
ISTM, if we like the seccomp fd approach, we should have them be
created with a parent already set. IOW the default should be that
their parent is the creator's seccomp fd and, if needed, creators
could specify a different parent.
Allowing people doing SECCOMP_FD_NEW to specify a parent fd would
work. Then we can disallow installing a seccomp fd if its parent is
not the current filter, and get rid of the whole mess with prev
locking and all that.
Tycho
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
Tycho
From: Andy Lutomirski <luto@amacapital.net> Date: 2015-09-30 18:47:32
On Wed, Sep 30, 2015 at 11:41 AM, Tycho Andersen
[off-list ref] wrote:
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
I don't care about the GUID. I think we should name it
KCMP_SECCOMP_FD and make it only work on seccomp fds.
Alternatively, we could figure out why KCMP_FILE doesn't do the trick
and consider fixing it. IMO it's really too bad that struct file is
so heavyweight that we can't really just embed one in all kinds of
structures.
--Andy
From: Andy Lutomirski <luto@amacapital.net> Date: 2015-09-30 18:47:51
On Wed, Sep 30, 2015 at 11:36 AM, Tycho Andersen
[off-list ref] wrote:
On Wed, Sep 30, 2015 at 11:27:34AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This patch introduces the concept of a seccomp fd, with a similar interface
and usage to ebpf fds. Initially, one is allowed to create, install, and
dump these fds. Any manipulation of seccomp fds requires users to be root
in their own user namespace, matching the checks done for
SECCOMP_SET_MODE_FILTER.
Installing a filterfd has some gotchas, though. Andy mentioned previously
that we should restrict installation to filter fds whose parent is already
in the filter tree. This doesn't quite work in the case of created seccomp
fds, since once you install a filter fd, you can't install any other filter
fd since it has no parent and there is no way to "pre-chain" filters before
installing them.
ISTM, if we like the seccomp fd approach, we should have them be
created with a parent already set. IOW the default should be that
their parent is the creator's seccomp fd and, if needed, creators
could specify a different parent.
Allowing people doing SECCOMP_FD_NEW to specify a parent fd would
work. Then we can disallow installing a seccomp fd if its parent is
not the current filter, and get rid of the whole mess with prev
locking and all that.
On Wed, Sep 30, 2015 at 11:47:05AM -0700, Andy Lutomirski wrote:
On Wed, Sep 30, 2015 at 11:41 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
I don't care about the GUID. I think we should name it
KCMP_SECCOMP_FD and make it only work on seccomp fds.
Ok, I can do that.
Alternatively, we could figure out why KCMP_FILE doesn't do the trick
and consider fixing it. IMO it's really too bad that struct file is
so heavyweight that we can't really just embed one in all kinds of
structures.
The problem is that KCMP_FILE compares the file objects themselves,
instead of the underlying data. If I ask for a seccomp fd for filter 0
twice, I'll have two different file objects and they won't be equal. I
suppose we could add some special logic inside KCMP_FILE to compare
the underlying data in special cases (seccomp, ebpf, others?), but it
seems cleaner to have a separate command as you described above.
Tycho
From: Andy Lutomirski <luto@amacapital.net> Date: 2015-09-30 18:56:48
On Wed, Sep 30, 2015 at 11:55 AM, Tycho Andersen
[off-list ref] wrote:
On Wed, Sep 30, 2015 at 11:47:05AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:41 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
I don't care about the GUID. I think we should name it
KCMP_SECCOMP_FD and make it only work on seccomp fds.
Ok, I can do that.
quoted
Alternatively, we could figure out why KCMP_FILE doesn't do the trick
and consider fixing it. IMO it's really too bad that struct file is
so heavyweight that we can't really just embed one in all kinds of
structures.
The problem is that KCMP_FILE compares the file objects themselves,
instead of the underlying data. If I ask for a seccomp fd for filter 0
twice, I'll have two different file objects and they won't be equal. I
suppose we could add some special logic inside KCMP_FILE to compare
the underlying data in special cases (seccomp, ebpf, others?), but it
seems cleaner to have a separate command as you described above.
What I meant was that maybe we could get the two requests to actually
produce the same struct file. But that could get very messy
memory-wise.
--Andy
On Wed, Sep 30, 2015 at 11:56:25AM -0700, Andy Lutomirski wrote:
On Wed, Sep 30, 2015 at 11:55 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:47:05AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:41 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
I don't care about the GUID. I think we should name it
KCMP_SECCOMP_FD and make it only work on seccomp fds.
Ok, I can do that.
quoted
Alternatively, we could figure out why KCMP_FILE doesn't do the trick
and consider fixing it. IMO it's really too bad that struct file is
so heavyweight that we can't really just embed one in all kinds of
structures.
The problem is that KCMP_FILE compares the file objects themselves,
instead of the underlying data. If I ask for a seccomp fd for filter 0
twice, I'll have two different file objects and they won't be equal. I
suppose we could add some special logic inside KCMP_FILE to compare
the underlying data in special cases (seccomp, ebpf, others?), but it
seems cleaner to have a separate command as you described above.
What I meant was that maybe we could get the two requests to actually
produce the same struct file. But that could get very messy
memory-wise.
I see. The attached patch seems to work with KCMP_FILE and doesn't
look too bad if you don't mind the circular references. What do you
think?
Tycho
From: Andy Lutomirski <luto@amacapital.net> Date: 2015-09-30 21:49:10
On Wed, Sep 30, 2015 at 2:39 PM, Tycho Andersen
[off-list ref] wrote:
On Wed, Sep 30, 2015 at 11:56:25AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:55 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:47:05AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:41 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
I don't care about the GUID. I think we should name it
KCMP_SECCOMP_FD and make it only work on seccomp fds.
Ok, I can do that.
quoted
Alternatively, we could figure out why KCMP_FILE doesn't do the trick
and consider fixing it. IMO it's really too bad that struct file is
so heavyweight that we can't really just embed one in all kinds of
structures.
The problem is that KCMP_FILE compares the file objects themselves,
instead of the underlying data. If I ask for a seccomp fd for filter 0
twice, I'll have two different file objects and they won't be equal. I
suppose we could add some special logic inside KCMP_FILE to compare
the underlying data in special cases (seccomp, ebpf, others?), but it
seems cleaner to have a separate command as you described above.
What I meant was that maybe we could get the two requests to actually
produce the same struct file. But that could get very messy
memory-wise.
I see. The attached patch seems to work with KCMP_FILE and doesn't
look too bad if you don't mind the circular references. What do you
think?
Could be reasonable. I'm not that well versed on what fd_release
does. Are we guaranteed that it's called when the last fd goes away
even if the struct file is pinned by the struct seccomp filter but is
otherwise unreferenced?
Kees?
How many of you will be at KS?
--Andy
On Wed, Sep 30, 2015 at 02:48:47PM -0700, Andy Lutomirski wrote:
On Wed, Sep 30, 2015 at 2:39 PM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:56:25AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:55 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:47:05AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:41 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
I don't care about the GUID. I think we should name it
KCMP_SECCOMP_FD and make it only work on seccomp fds.
Ok, I can do that.
quoted
Alternatively, we could figure out why KCMP_FILE doesn't do the trick
and consider fixing it. IMO it's really too bad that struct file is
so heavyweight that we can't really just embed one in all kinds of
structures.
The problem is that KCMP_FILE compares the file objects themselves,
instead of the underlying data. If I ask for a seccomp fd for filter 0
twice, I'll have two different file objects and they won't be equal. I
suppose we could add some special logic inside KCMP_FILE to compare
the underlying data in special cases (seccomp, ebpf, others?), but it
seems cleaner to have a separate command as you described above.
What I meant was that maybe we could get the two requests to actually
produce the same struct file. But that could get very messy
memory-wise.
I see. The attached patch seems to work with KCMP_FILE and doesn't
look too bad if you don't mind the circular references. What do you
think?
Could be reasonable. I'm not that well versed on what fd_release
does. Are we guaranteed that it's called when the last fd goes away
even if the struct file is pinned by the struct seccomp filter but is
otherwise unreferenced?
I think so; my understanding is that the vfs doesn't know anything
about the seccomp_filter reference, so when the last fd referring to
the struct file is closed that's when release is called.
On Wed, Sep 30, 2015 at 02:48:47PM -0700, Andy Lutomirski wrote:
On Wed, Sep 30, 2015 at 2:39 PM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:56:25AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:55 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:47:05AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:41 AM, Tycho Andersen
[off-list ref] wrote:
quoted
On Wed, Sep 30, 2015 at 11:25:41AM -0700, Andy Lutomirski wrote:
quoted
On Wed, Sep 30, 2015 at 11:13 AM, Tycho Andersen
[off-list ref] wrote:
quoted
This command allows comparing the underling private data of two fds. This
is useful e.g. to find out if a seccomp filter is inherited, since struct
seccomp_filter are unique across tasks and are the private_data seccomp
fds.
This is very implementation-specific and may have nasty ABI
consequences far outside seccomp. Let's do something specific to
seccomp and/or eBPF.
We could change the name to a less generic KCMP_SECCOMP_FD or
something, but without some sort of GUID on each struct
seccomp_filter, the implementation would be effectively the same as it
is today. Is that enough, or do we need a GUID?
I don't care about the GUID. I think we should name it
KCMP_SECCOMP_FD and make it only work on seccomp fds.
Ok, I can do that.
quoted
Alternatively, we could figure out why KCMP_FILE doesn't do the trick
and consider fixing it. IMO it's really too bad that struct file is
so heavyweight that we can't really just embed one in all kinds of
structures.
The problem is that KCMP_FILE compares the file objects themselves,
instead of the underlying data. If I ask for a seccomp fd for filter 0
twice, I'll have two different file objects and they won't be equal. I
suppose we could add some special logic inside KCMP_FILE to compare
the underlying data in special cases (seccomp, ebpf, others?), but it
seems cleaner to have a separate command as you described above.
What I meant was that maybe we could get the two requests to actually
produce the same struct file. But that could get very messy
memory-wise.
I see. The attached patch seems to work with KCMP_FILE and doesn't
look too bad if you don't mind the circular references. What do you
think?
Could be reasonable. I'm not that well versed on what fd_release
does. Are we guaranteed that it's called when the last fd goes away
even if the struct file is pinned by the struct seccomp filter but is
otherwise unreferenced?
After thinking about the patch a bit more, I think it's not safe.
There is a race where the last referenced is closed at the same time
someone else asks for the strcut file via ptrace(). I thought the lock
would fix this, but it doesn't. I'll see if I can find another way.
Tycho