mbox series

[v3,net-next,0/2] bpfilter

Message ID 20180522022230.2492505-1-ast@kernel.org
Headers show
Series bpfilter | expand

Message

Alexei Starovoitov May 22, 2018, 2:22 a.m. UTC
Hi All,

v2->v3:
- followed Luis's suggestion and significantly simplied first patch
  with shmem_kernel_file_setup+kernel_write. Added kdoc for new helper
- fixed typos and race to access pipes with mutex
- tested with bpfilter being 'builtin'. CONFIG_BPFILTER_UMH=y|m both work.
  Interesting to see a usermode executable being embedded inside vmlinux.
- it doesn't hurt to enable bpfilter in .config.
  ip_setsockopt commands sent to usermode via pipes and -ENOPROTOOPT is
  returned from userspace, so kernel falls back to original iptables code

v1->v2:
this patch set is almost a full rewrite of the earlier umh modules approach
The v1 of patches and follow up discussion was covered by LWN:
https://lwn.net/Articles/749108/

I believe the v2 addresses all issues brought up by Andy and others.
Mainly there are zero changes to kernel/module.c
Instead of teaching module loading logic to recognize special
umh module, let normal kernel modules execute part of its own
.init.rodata as a new user space process (Andy's idea)
Patch 1 introduces this new helper:
int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
Input:
  data + len == executable file
Output:
  struct umh_info {
       struct file *pipe_to_umh;
       struct file *pipe_from_umh;
       pid_t pid;
  };

Advantages vs v1:
- the embedded user mode executable is stored as .init.rodata inside
  normal kernel module. These pages are freed when .ko finishes loading
- the elf file is copied into tmpfs file. The user mode process is swappable.
- the communication between user mode process and 'parent' kernel module
  is done via two unix pipes, hence protocol is not exposed to
  user space
- impossible to launch umh on its own (that was the main issue of v1)
  and impossible to be man-in-the-middle due to pipes
- bpfilter.ko consists of tiny kernel part that passes the data
  between kernel and umh via pipes and much bigger umh part that
  doing all the work
- 'lsmod' shows bpfilter.ko as usual.
  'rmmod bpfilter' removes kernel module and kills corresponding umh
- signed bpfilter.ko covers the whole image including umh code

Few issues:
- the user can still attach to the process and debug it with
  'gdb /proc/pid/exe pid', but 'gdb -p pid' doesn't work.
  (a bit worse comparing to v1)
- tinyconfig will notice a small increase in .text
  +766 | TEXT | 7c8b94806bec umh: introduce fork_usermode_blob() helper

Alexei Starovoitov (2):
  umh: introduce fork_usermode_blob() helper
  net: add skeleton of bpfilter kernel module

 fs/exec.c                     |  38 ++++++++++---
 include/linux/binfmts.h       |   1 +
 include/linux/bpfilter.h      |  15 +++++
 include/linux/umh.h           |  12 ++++
 include/uapi/linux/bpfilter.h |  21 +++++++
 kernel/umh.c                  | 125 +++++++++++++++++++++++++++++++++++++++++-
 net/Kconfig                   |   2 +
 net/Makefile                  |   1 +
 net/bpfilter/Kconfig          |  16 ++++++
 net/bpfilter/Makefile         |  30 ++++++++++
 net/bpfilter/bpfilter_kern.c  | 111 +++++++++++++++++++++++++++++++++++++
 net/bpfilter/main.c           |  63 +++++++++++++++++++++
 net/bpfilter/msgfmt.h         |  17 ++++++
 net/ipv4/Makefile             |   2 +
 net/ipv4/bpfilter/Makefile    |   2 +
 net/ipv4/bpfilter/sockopt.c   |  42 ++++++++++++++
 net/ipv4/ip_sockglue.c        |  17 ++++++
 17 files changed, 503 insertions(+), 12 deletions(-)
 create mode 100644 include/linux/bpfilter.h
 create mode 100644 include/uapi/linux/bpfilter.h
 create mode 100644 net/bpfilter/Kconfig
 create mode 100644 net/bpfilter/Makefile
 create mode 100644 net/bpfilter/bpfilter_kern.c
 create mode 100644 net/bpfilter/main.c
 create mode 100644 net/bpfilter/msgfmt.h
 create mode 100644 net/ipv4/bpfilter/Makefile
 create mode 100644 net/ipv4/bpfilter/sockopt.c

Comments

David Miller May 23, 2018, 5:26 p.m. UTC | #1
From: Alexei Starovoitov <ast@kernel.org>
Date: Mon, 21 May 2018 19:22:28 -0700

> v2->v3:
> - followed Luis's suggestion and significantly simplied first patch
>   with shmem_kernel_file_setup+kernel_write. Added kdoc for new helper
> - fixed typos and race to access pipes with mutex
> - tested with bpfilter being 'builtin'. CONFIG_BPFILTER_UMH=y|m both work.
>   Interesting to see a usermode executable being embedded inside vmlinux.
> - it doesn't hurt to enable bpfilter in .config.
>   ip_setsockopt commands sent to usermode via pipes and -ENOPROTOOPT is
>   returned from userspace, so kernel falls back to original iptables code
> 
> v1->v2:
> this patch set is almost a full rewrite of the earlier umh modules approach
> The v1 of patches and follow up discussion was covered by LWN:
> https://lwn.net/Articles/749108/
> 
> I believe the v2 addresses all issues brought up by Andy and others.
> Mainly there are zero changes to kernel/module.c
> Instead of teaching module loading logic to recognize special
> umh module, let normal kernel modules execute part of its own
> .init.rodata as a new user space process (Andy's idea)
> Patch 1 introduces this new helper:
> int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
> Input:
>   data + len == executable file
> Output:
>   struct umh_info {
>        struct file *pipe_to_umh;
>        struct file *pipe_from_umh;
>        pid_t pid;
>   };

Series applied, let the madness begin... :-)
Greg KH May 23, 2018, 5:33 p.m. UTC | #2
On Wed, May 23, 2018 at 01:26:48PM -0400, David Miller wrote:
> From: Alexei Starovoitov <ast@kernel.org>
> Date: Mon, 21 May 2018 19:22:28 -0700
> 
> > v2->v3:
> > - followed Luis's suggestion and significantly simplied first patch
> >   with shmem_kernel_file_setup+kernel_write. Added kdoc for new helper
> > - fixed typos and race to access pipes with mutex
> > - tested with bpfilter being 'builtin'. CONFIG_BPFILTER_UMH=y|m both work.
> >   Interesting to see a usermode executable being embedded inside vmlinux.
> > - it doesn't hurt to enable bpfilter in .config.
> >   ip_setsockopt commands sent to usermode via pipes and -ENOPROTOOPT is
> >   returned from userspace, so kernel falls back to original iptables code
> > 
> > v1->v2:
> > this patch set is almost a full rewrite of the earlier umh modules approach
> > The v1 of patches and follow up discussion was covered by LWN:
> > https://lwn.net/Articles/749108/
> > 
> > I believe the v2 addresses all issues brought up by Andy and others.
> > Mainly there are zero changes to kernel/module.c
> > Instead of teaching module loading logic to recognize special
> > umh module, let normal kernel modules execute part of its own
> > .init.rodata as a new user space process (Andy's idea)
> > Patch 1 introduces this new helper:
> > int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
> > Input:
> >   data + len == executable file
> > Output:
> >   struct umh_info {
> >        struct file *pipe_to_umh;
> >        struct file *pipe_from_umh;
> >        pid_t pid;
> >   };
> 
> Series applied, let the madness begin... :-)

Yeah, this is going to be fun :)
Jakub Kicinski May 24, 2018, 1:33 a.m. UTC | #3
Minor glitch with Ubuntu 18.04:

$ gcc --version
gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0

In file included from /usr/include/fcntl.h:290:0,
                 from ../net/bpfilter/main.c:7:
In function ‘open’,
    inlined from ‘main’ at ../net/bpfilter/main.c:58:13:
/usr/include/x86_64-linux-gnu/bits/fcntl2.h:50:4: error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT or O_TMPFILE in second argument needs 3 arguments
    __open_missing_mode ();
    ^~~~~~~~~~~~~~~~~~~~~~
scripts/Makefile.host:107: recipe for target 'net/bpfilter/main.o' failed
make[3]: *** [net/bpfilter/main.o] Error 1

I can't repro on Fedora 27 gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5),
perhaps the GCC is broken on that Ubuntu 18.04 box of mine.  The warning/
/error, however, looks potentially legit?
Jakub Kicinski May 24, 2018, 1:50 a.m. UTC | #4
On Wed, 23 May 2018 18:33:52 -0700, Jakub Kicinski wrote:
> Minor glitch with Ubuntu 18.04:
> 
> $ gcc --version
> gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0
> 
> In file included from /usr/include/fcntl.h:290:0,
>                  from ../net/bpfilter/main.c:7:
> In function ‘open’,
>     inlined from ‘main’ at ../net/bpfilter/main.c:58:13:
> /usr/include/x86_64-linux-gnu/bits/fcntl2.h:50:4: error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT or O_TMPFILE in second argument needs 3 arguments
>     __open_missing_mode ();
>     ^~~~~~~~~~~~~~~~~~~~~~
> scripts/Makefile.host:107: recipe for target 'net/bpfilter/main.o' failed
> make[3]: *** [net/bpfilter/main.o] Error 1
> 
> I can't repro on Fedora 27 gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5),
> perhaps the GCC is broken on that Ubuntu 18.04 box of mine.  The warning/
> /error, however, looks potentially legit?

More?

Kernel: arch/x86/boot/bzImage is ready  (#9)
  Building modules, stage 2.
  MODPOST 1620 modules
ERROR: "bpfilter_process_sockopt" [net/bpfilter/bpfilter.ko] undefined!
../scripts/Makefile.modpost:92: recipe for target '__modpost' failed
make[2]: *** [__modpost] Error 1
/home/jkicinski/devel/linux/Makefile:1274: recipe for target 'modules' failed
make[1]: *** [modules] Error 2
make[1]: Leaving directory '/home/jkicinski/devel/linux/build_randconfig'
Makefile:146: recipe for target 'sub-make' failed
make: *** [sub-make] Error 2
Alexei Starovoitov May 24, 2018, 2:09 a.m. UTC | #5
On 5/23/18 6:50 PM, Jakub Kicinski wrote:
> On Wed, 23 May 2018 18:33:52 -0700, Jakub Kicinski wrote:
>> Minor glitch with Ubuntu 18.04:
>>
>> $ gcc --version
>> gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0
>>
>> In file included from /usr/include/fcntl.h:290:0,
>>                  from ../net/bpfilter/main.c:7:
>> In function ‘open’,
>>     inlined from ‘main’ at ../net/bpfilter/main.c:58:13:
>> /usr/include/x86_64-linux-gnu/bits/fcntl2.h:50:4: error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT or O_TMPFILE in second argument needs 3 arguments
>>     __open_missing_mode ();
>>     ^~~~~~~~~~~~~~~~~~~~~~
>> scripts/Makefile.host:107: recipe for target 'net/bpfilter/main.o' failed
>> make[3]: *** [net/bpfilter/main.o] Error 1
>>
>> I can't repro on Fedora 27 gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5),
>> perhaps the GCC is broken on that Ubuntu 18.04 box of mine.  The warning/
>> /error, however, looks potentially legit?
>
> More?
>
> Kernel: arch/x86/boot/bzImage is ready  (#9)
>   Building modules, stage 2.
>   MODPOST 1620 modules
> ERROR: "bpfilter_process_sockopt" [net/bpfilter/bpfilter.ko] undefined!
> ../scripts/Makefile.modpost:92: recipe for target '__modpost' failed

hmm. how come buildbot didn't yell at me for any of these things.
will take a look soon.