Bug 2590 - Seccomp filter for missing architectures
Summary: Seccomp filter for missing architectures
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: sshd (show other bugs)
Version: 7.2p1
Hardware: Other Linux
: P5 enhancement
Assignee: Assigned to nobody
URL:
Keywords: patch
Depends on:
Blocks: V_7_7
  Show dependency treegraph
 
Reported: 2016-06-17 21:47 AEST by Jakub Jelen
Modified: 2021-04-23 14:53 AEST (History)
3 users (show)

See Also:


Attachments
whitelist PPC64*, S390* and MIPS architectures for seccomp filter (818 bytes, patch)
2016-06-17 21:47 AEST, Jakub Jelen
no flags Details | Diff
add mips gnuabin32 targets. (494 bytes, patch)
2016-08-18 12:04 AEST, Darren Tucker
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelen 2016-06-17 21:47:17 AEST
Created attachment 2840 [details]
whitelist PPC64*, S390* and MIPS architectures for seccomp filter

I am posting follow up the the bug #2361 about aarch64 problems with seccomp filter. Since then we managed to test the seccomp filter on PPC64, PPC64LE, S390, S390X and MIPS* architectures (still tracked in Red Hat bugzilla [1]).

The testing went smooth and there were no more problems or missing syscalls detected. The only thing needed is to whitelist these architectures in configure since it is perfectly reasonable to use seccomp when it is supported.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1195065
Comment 1 Damien Miller 2016-07-08 14:00:46 AEST
Patch applied - thank-you very much for doing the testing for these. This will be in the openssh-7.3 release.
Comment 2 Damien Miller 2016-08-02 10:41:14 AEST
Close all resolved bugs after 7.3p1 release
Comment 3 Joshua Kinard 2016-08-16 22:45:20 AEST
(In reply to Damien Miller from comment #1)
> Patch applied - thank-you very much for doing the testing for these.
> This will be in the openssh-7.3 release.

I hate to reopen, but I found a corner case for MIPS broken by the MIPS whitelist.  Specifically, the proposed whitelist does not account for MIPS N32 ABI (under mips64).

Specifically:
+	mips64-*)
+		seccomp_audit_arch=AUDIT_ARCH_MIPS64

There needs to be another hook to somehow detect N32 and then set either AUDIT_ARCH_MIPS64 (big-endian) or AUDIT_ARCH_MIPSEL64N32 (little-endian).

I believe there's a known/defined CHOST tuple to specify an N32 userland, but it's not common, so CHOST seems to be unreliable to detect this.  I am not sure of another reasonable way to do so right now.

Without this fix, on mips64/N32 platforms, "UsePrivilegeSeparation sandbox" will fail and not allow a client to connect.  Per strace:

[pid  1883] prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) = 0
[pid  1883] prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=57, filter=0x565f3920}) = 0
[pid  1883] write(3, "\0\0\3|\10\24\270\256hb<\257-\30\216\214L\301\35\230\10\233\0\0\0\324curve2"..., 896 <unfinished ...>
[pid  1883] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=NULL, si_syscall=__NR_write, si_arch=AUDIT_ARCH_MIPS64N32} ---
[pid  1883] <... write resumed> )       = -1 ERRNO_6001 (Unknown error 6001)
[pid  1883] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=NULL, si_syscall=__NR_write, si_arch=AUDIT_ARCH_MIPS64N32} ---
[pid  1882] <... poll resumed> )        = 2 ([{fd=6, revents=POLLIN|POLLHUP}, {fd=7, revents=POLLHUP}])
[pid  1883] +++ killed by SIGSYS +++
[pid  1882] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=1883, si_uid=22, si_status=SIGSYS, si_utime=0, si_stime=0} ---
[pid  1882] read(7, "", 4)              = 0
[pid  1882] close(7)                    = 0
[pid  1882] poll([{fd=6, events=POLLIN}], 1, -1) = 1 ([{fd=6, revents=POLLIN|POLLHUP}])
[pid  1882] read(6, "", 4)              = 0
[pid  1882] kill(1883, SIGKILL)         = 0
[pid  1882] exit_group(255)             = ?
[pid  1882] +++ exited with 255 +++

Switching to "UsePrivilegeSeparation yes" is a workaround, but seems suboptimal.
Comment 4 Joshua Kinard 2016-08-16 22:46:42 AEST
(In reply to Joshua Kinard from comment #3)

> There needs to be another hook to somehow detect N32 and then set
> either AUDIT_ARCH_MIPS64 (big-endian) or AUDIT_ARCH_MIPSEL64N32
> (little-endian).
> 

copy-pasted too fast,  The mips64/big-endian case needs to use AUDIT_ARCH_MIPS64N32.
Comment 5 Darren Tucker 2016-08-17 10:36:39 AEST
(In reply to Joshua Kinard from comment #3)
> 
> I hate to reopen, but I found a corner case for MIPS broken by the
> MIPS whitelist.  Specifically, the proposed whitelist does not
> account for MIPS N32 ABI (under mips64).
> 
> Specifically:
> +	mips64-*)
> +		seccomp_audit_arch=AUDIT_ARCH_MIPS64
> 
> There needs to be another hook to somehow detect N32 and then set
> either AUDIT_ARCH_MIPS64 (big-endian) or AUDIT_ARCH_MIPSEL64N32
> (little-endian).

what does configure.guess report on such systems?  If that's not a reliable indicator, what is?  mips64-* && AC_CHECK_SIZEOF([int], [4]) ?
Comment 6 Joshua Kinard 2016-08-17 15:50:14 AEST
(In reply to Darren Tucker from comment #5)
> (In reply to Joshua Kinard from comment #3)
> > 
> > I hate to reopen, but I found a corner case for MIPS broken by the
> > MIPS whitelist.  Specifically, the proposed whitelist does not
> > account for MIPS N32 ABI (under mips64).
> > 
> > Specifically:
> > +	mips64-*)
> > +		seccomp_audit_arch=AUDIT_ARCH_MIPS64
> > 
> > There needs to be another hook to somehow detect N32 and then set
> > either AUDIT_ARCH_MIPS64 (big-endian) or AUDIT_ARCH_MIPSEL64N32
> > (little-endian).
> 
> what does configure.guess report on such systems?  If that's not a
> reliable indicator, what is?  mips64-* && AC_CHECK_SIZEOF([int],
> [4]) ?

config.guess reports back "mips64-unknown-linux-gnu", which is my system CHOST value (Gentoo, SGI Octane).  It does the same in an O32 chroot, so this might be unreliable.  O32 Linux userlands require a CHOST of "mips-unknown-linux-gnu", even when run under a mips64 kernel.

Per the MIPS N32 handbook, you can tell O32/N32 apart from N64 (full 64-bit) by checking the size of a pointer, which should be 8 bytes on N64.  But it'll be 4 bytes under both O32/N32, so this approach won't work either.

Is it possible to have configure compile a test binary using the provided C compiler and flags, then check the file magic of the output binary?  That's a definitive way to differ between all three ABI's (and may even be applicable for multilib setups).  I scanned briefly through the autoconf manual, but I don't see a built-in check for this.

O32 /bin/cat:
/bin/cat: ELF 32-bit MSB executable, MIPS, MIPS-IV version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.6.32, stripped

N32 /bin/cat:
/bin/cat: ELF 32-bit MSB executable, MIPS, N32 MIPS-IV version 1 (SYSV), dynamically linked, interpreter /lib32/ld.so.1, for GNU/Linux 2.6.32, stripped

So a check for the presence of "N32" in file's output would be enough to detect between O32 and N32.

Should you ever get around to supporting X32 on the Intel/AMD platforms, this same situation is bound to come up again.  X32 either copies, or was inspired by, N32 and so they aim to achieve similar goals.
Comment 7 Darren Tucker 2016-08-18 10:12:44 AEST
(In reply to Joshua Kinard from comment #3)
> I believe there's a known/defined CHOST tuple to specify an N32

Debian seems to document "mips64-linux-gnuabin32":
https://wiki.debian.org/Multiarch/Tuples

(In reply to Joshua Kinard from comment #6)
[...]
> Per the MIPS N32 handbook, you can tell O32/N32 apart from N64 (full
> 64-bit) by checking the size of a pointer, which should be 8 bytes
> on N64.  But it'll be 4 bytes under both O32/N32, so this approach
> won't work either.

I know nothing about this other than what I've read in the last few minutes, but isn't O32 for purely 32 bit machines?  ie isn't config.guess is going to say "mips-"?  or can you run O32 userspace even on a 64 bit kernel?

> Is it possible to have configure compile a test binary using the
> provided C compiler and flags, then check the file magic of the
> output binary?

It's possible but seems pretty icky.

I think the first thing to do is fix the case statement which will allow you to at least specify the right thing via configure --target.
Comment 8 Darren Tucker 2016-08-18 12:04:01 AEST
Created attachment 2861 [details]
add mips gnuabin32 targets.

how about this?  it should make ./configure --host=mips64-linux-gnuabin32 do what you want.

I guess the next thing to do is get config.guess to guess this configuration when appropriate.
Comment 9 Joshua Kinard 2016-08-19 01:19:55 AEST
(In reply to Darren Tucker from comment #8)
> Created attachment 2861 [details]
> add mips gnuabin32 targets.
> 
> how about this?  it should make ./configure
> --host=mips64-linux-gnuabin32 do what you want.
> 
> I guess the next thing to do is get config.guess to guess this
> configuration when appropriate.

I think the problem with overriding --host like that is it might work for binary distros, but not Gentoo or other source-based distros.  My system's CHOST is "mips64-unknown-linux-gnu", and I believe that will be passed to --host instead, as well as --build.  If --build and --host differ, I believe GNU autoconf treats it as a cross-compile instead of a normal compile.

Equally, that CHOST tuple is only valid for glibc-based systems.  I don't think there is an equivalent like "mips64-unknown-linux-uclibcn32" for uClibc-based systems or other libc's that might happen to support ABIs other than O32.  So I don't think relying on the CHOST will work 100% here (especially for multilib instances where multiple ABIs coexist on the same root).
Comment 10 Darren Tucker 2018-02-10 11:18:43 AEDT
There's a github pull request (https://github.com/openssh/openssh-portable/pull/71) that looks like it might fix this.  Can you confirm?

Thanks.
Comment 11 Darren Tucker 2018-03-08 13:00:22 AEDT
(In reply to Darren Tucker from comment #10)
> There's a github pull request
> (https://github.com/openssh/openssh-portable/pull/71) that looks
> like it might fix this.  Can you confirm?

Merged that pull request, if that doesn't fix it please reopen.

Thanks.
Comment 12 Damien Miller 2021-04-23 14:53:10 AEST
closing resolved bugs as of 8.6p1 release