AUDIT_ARCH_ and __NR_syscall constants for seccomp filters

Thomas Weißschuh linux at weissschuh.net
Mon Jun 28 17:58:52 UTC 2021


Hi again!

On Mo, 2021-06-28T13:34-0400, Paul Moore wrote:
> On Mon, Jun 28, 2021 at 1:13 PM Thomas Weißschuh <linux at weissschuh.net> wrote:
> > On Mo, 2021-06-28T12:59-0400, Paul Moore wrote:
> > > On Mon, Jun 28, 2021 at 9:25 AM Thomas Weißschuh <linux at weissschuh.net> wrote:
> > > >
> > > > Hi everyone,
> > > >
> > > > there does not seem to be a way to access the AUDIT_ARCH_ constant that matches
> > > > the currently visible syscall numbers (__NR_...) from the kernel uapi headers.
> > >
> > > Looking at Linus' current tree I see the AUDIT_ARCH_* defines in
> > > include/uapi/linux/audit.h; looking on my system right now I see the
> > > defines in /usr/include/linux/audit.h.  What kernel repository and
> > > distribution are you using?
> >
> > I am using ArchLinux and also have all these defines.
> >
> > > > Questions:
> > > >
> > > > Is it really necessary to validate the arch value when syscall numbers are
> > > > already target-specific?
> > > > (If not, should this be added to the docs?)
> > >
> > > Checking the arch/ABI value is important so that you can ensure that
> > > you are using the syscall number in the proper context.  For example,
> > > look at the access(2) syscall: it is undefined on some ABIs and can
> > > take either a value of 20, 21, or 33 depending on the arch/ABI.
> > > Unfortunately this is rather common.
> >
> > But when if I am not hardcoding the syscall numbers but use the
> > __NR_access kernel define then I should always get the correct number for the
> > ABI I am compiling for (or an error if the syscall does not exist), no?
> 
> Remember that seccomp filters are inherited across forks, so if your
> application loads an ABI specific filter and then fork()/exec()'s an
> application with a different ABI you could be in trouble.  We saw this
> some years ago when people started running containers with ABIs other
> than the native system; if the container orchestrator didn't load a
> filter that knew about these non-native ABIs Bad Things happened.

My application will not be able to spawn any new processes.
It is limited to write() and exit().
Also this is a low-level system application so it should always be compiled for
the native ABI.
So this should not be an issue.

> I'm sure you are already aware of libseccomp, but if not you may want
> to consider it for your application.  Not only does it provide a safe
> and easy way to handle multiple ABIs in a single filter, it handles
> other seccomp problem areas like build/runtime system differences in
> the syscall tables/defines as well as the oddball nature of
> direct-call and multiplexed socket related syscalls, i.e. socketcall()
> vs socket(), etc.

For a larger application this would be indeed my choice.
But for a small application like mine I don't think it is worth it.
libseccomp for example does provide a way to get the native audit arch:
`uint32_t seccomp_arch_native(void);`. It is implemented by ifdef-ing on
various compiler defines to detect the ABI compiled for.

I'd like the kernel to provide this out-of-the box, so I don't have to have the
same ifdefs in my application(s) and keep them up to date.

I found that the kernel internally already has a definition for my usecase:
SECCOMP_ARCH_NATIVE.
It is just not exported to userspace.

> > > Checking the arch/ABI value is also handy if you want to quickly
> > > disallow certain ABIs on a system that supports multiple ABI, e.g.
> > > disabling 32-bit x86 on a 64-bit x86_64 system.
> > >
> > > > Would it make sense to expose the audit arch matching the syscall numbers in
> > > > the uapi headers?
> > >
> > > Yes, which is why the existing headers do so ;)  If you don't see the
> > > header files I mentioned above, it may be worth checking your kernel
> > > source repository and your distribution's installed kernel header
> > > files.
> >
> > I do see constants for all the possible ABIs but not one constant that always
> > represents the one I am currently compiling for.
> > The same way the syscall number defines always give me the syscall number for
> > the currently targeted ABI.
> 
> I'm sorry, but I don't quite understand what you are looking for in
> the header files ... ?  It might help if you could provide a concrete
> example of what you would like to see in the header files?

I want to do something like the follwing inside my program to assemble a
seccomp filter that will be loaded before the error-prone parts of the
application will begin.

1: BPF_STMT(BPF_LD | BPF_W | BPF_ABS, syscall_arch),
2: BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SECCOMP_ARCH_NATIVE, 0, $KILL)
3: BPF_STMT(BPF_LD | BPF_W | BPF_ABS, syscall_nr),
4: BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_write, $ALLOW, $KILL),

In line 4 I can already have the kernel headers provide me the correct syscall
number for the ABI my application is compiled for.

For line 2 however I need to define AUDIT_ARCH_CURRENT on my own instead of
having a kernel header provide the correct value.

Thomas





More information about the Linux-audit mailing list