Skip to content

Instantly share code, notes, and snippets.

@marcov
Last active November 29, 2019 10:35
Show Gist options
  • Save marcov/e929ada1ac65e7ec1ceb4552b9754dbd to your computer and use it in GitHub Desktop.
Save marcov/e929ada1ac65e7ec1ceb4552b9754dbd to your computer and use it in GitHub Desktop.
Why runc seccomp filtering for the chmod syscall does not work on aarch64?

Why runc seccomp filtering for the chmod syscall does not work on aarch64?

TLDR, because the chmod syscall does not exist for aarch64, and you should use fchmodat.


When using libseccomp with runc, there's no easy way to detect that the specified syscall does not exist for a given arch.

Disassemble chmod

On x86_64:

000000000043c340 <__chmod>:
 59927   43c340:»··b8 5a 00 00 00       »··mov    $0x5a,%eax                                                           
 59928   43c345:»··0f 05                »··syscall 
 59929   43c347:»··48 3d 01 f0 ff ff    »··cmp    $0xfffffffffffff001,%rax

Syscall number is 0x5a

On aarch64:

   0x000000000041672c <__chmod+8>:      60 0c 80 92     mov     x0, #0xffffffffffffff9c         // #-100
   0x0000000000416730 <__chmod+12>:     e1 03 03 aa     mov     x1, x3                                                
   0x0000000000416734 <__chmod+16>:     e2 03 02 2a     mov     w2, w2                                                
=> 0x0000000000416738 <__chmod+20>:     a8 06 80 d2     mov     x8, #0x35                       // #53
   0x000000000041673c <__chmod+24>:     01 00 00 d4     svc     #0x0
   0x0000000000416740 <__chmod+28>:     1f 04 40 b1     cmn     x0, #0x1, lsl #12
   0x0000000000416744 <__chmod+32>:     48 00 00 54     b.hi    0x41674c <__chmod+40>  // b.pmore            

Syscall number is 0x35.

Does that match what's defined in libseccomp?

Check chmod syscall number in libseccomp

For x86, src/arch-x86_64-syscalls.c:

const struct arch_syscall_def x86_64_syscall_table[] = { \
/* CUT */                                                                                        
	{ "chmod", 90 },

It matches!

For arm, src/arch-aarch64-syscalls.c:

const struct arch_syscall_def aarch64_syscall_table[] = { \
/* CUT */                                                                                        
	{ "chmod", __PNR_chmod },
/* CUT */                                                                                        
	{ "fchmodat", 53 },

Gulp, there's a PNR... But, the syscall number of fchmodat matches what we found in the disassembled code :-)

What's PNR? Checking in the code documentation...

Docs of seccomp_syscall_resolve_name()

RETURN VALUE         top
       In the case of seccomp_syscall_resolve_name(),
       seccomp_syscall_resolve_name_arch(), and
       seccomp_syscall_resolve_name_rewrite() the associated syscall number
       is returned, with the negative pseudo syscall number being returned
       in cases where the given syscall does not exist for the architecture.

So, basically PNR is a negative pseudo syscall number when the syscall does not exist for the specified architecture...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment