Issue metadata
Sign in to add a comment
|
sslh seccomp policy blocks ssh to ChromeOS over link-local IPv6 addresses
Reported by
marc.her...@intel.corp-partner.google.com,
Oct 6 2017
|
||||||||||||||||||||||
Issue descriptionUserAgent: Mozilla/5.0 (X11; CrOS x86_64 9901.35.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.43 Safari/537.36 Steps to reproduce the problem: 1. Developer mode, enable debugging features 2. ssh to ChromeOS over IPv6, sshl receives SIGSYS and connection is refused 3. ssh to ChromeOS over IPv4, works fine. 4. Temporarily disable minijail in /etc/init/sshl.conf, can ssh again over IPv6 What is the expected behavior? can ssh over IPv6 What went wrong? Recent sslh seccomp policy blocks IPv6 https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/630381/5/chromeos-base/arc-sslh-init/files/sslh-seccomp-amd64.policy (formerly https://chrome-internal-review.googlesource.com/c/chromeos/overlays/project-cheets-private/+/326413) 2017-10-05T15:34:34.425323-07:00 ERR sslh-fork[11325]: libminijail[5]: blocked syscall: socket 2017-10-05T15:34:34.440861-07:00 WARNING crash_reporter[11327]: Could not load the device policy file. 2017-10-05T15:34:34.443526-07:00 WARNING crash_reporter[11327]: [user] Received crash notification for sslh-fork[11325] sig 31, user 200 (deve 2017-10-05T15:34:34.445910-07:00 INFO crash_reporter[11327]: State of crashed process [11325]: S (sleeping) PS: I'm using link local address; I doubt it matters. Did this work before? Yes Probably just before 326413 above got merged (April 12th) Chrome version: 63 Channel: dev OS Version: 10004.0.0 Flash Version: strace -f -p 4271 strace: Process 4271 attached accept(4, NULL, NULL) = 6 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x77576227d9d0) = 11 strace: Process 4568 attached [pid 4271] close(6) = 0 [pid 4271] accept(4, NULL, NULL <unfinished ...> [pid 4568] close(4) = 0 [pid 4568] select(7, [6], NULL, NULL, {tv_sec=2, tv_usec=0}) = 1 (in [6], left {tv_sec=1, tv_usec=999996}) [pid 4568] read(6, "SSH-2.0-OpenSSH_7.4\r\n", 8192) = 21 [pid 4568] getpeername(6, {sa_family=AF_INET6, sin6_port=htons(58318), inet_pton(AF_INET6, "fe80::1423:78e3:7b92:6094", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=if_nametoindex("eth1")}, [128->28]) = 0 [pid 4568] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 4 [pid 4568] connect(4, {sa_family=AF_INET, sin_port=htons(2222), sin_addr=inet_addr("127.0.0.1")}, 16) = 0 [pid 4568] getpeername(6, {sa_family=AF_INET6, sin6_port=htons(58318), inet_pton(AF_INET6, "fe80::1423:78e3:7b92:6094", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=if_nametoindex("eth1")}, [128->28]) = 0 [pid 4568] access("/proc/net", R_OK) = 0 [pid 4568] access("/proc/net/unix", R_OK) = 0 [pid 4568] syscall_18446744073709551615(0x1, 0x80002, 0, 0x7ffff591ff20, 0xfefefefefefefeff, 0xfefefeff77686d74) = 0x29 [pid 4568] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x775761df0167, si_syscall=__NR_socket, si_arch=AUDIT_ARCH_X86_64} --- [pid 4568] sendto(3, "<35>Oct 5 16:40:14 sslh-fork[1]"..., 74, MSG_NOSIGNAL, NULL, 0) = 74 [pid 4568] syscall_18446744073709551615(0x1, 0x7ffff591f030, 0, 0x8, 0x5b1545609930, 0) = 0xe [pid 4568] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x775761d2c0c0, si_syscall=__NR_rt_sigprocmask, si_arch=AUDIT_ARCH_X86_64} --- [pid 4568] +++ killed by SIGSYS (core dumped) +++ <... accept resumed> ) = ? ERESTARTSYS (To be restarted if SA_RESTART is set) --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_DUMPED, si_pid=11, si_uid=200, si_status=SIGSYS, si_utime=0, si_stime=0} --- accept(4, NULL, NULL^Cstrace: Process 4271 detached <detached ...> 4:41 PM Reply
,
Oct 6 2017
I'd be happy to spend some (limited) time experimenting with the config file and then report here. Could some 5min seccomp crash course somewhere help me do that?
,
Oct 6 2017
,
Oct 6 2017
,
Oct 6 2017
> Did this work before? Yes Probably just before 326413 above got merged (April 12th) I have been using ssh over IPv6 for months and months. I don't think the introduction of this policy in April caused a regression, but it is possible that changes in some other dependency did. Also, sslh was upgraded about a month ago: https://chromium-review.googlesource.com/643553 So this may be worth bisecting if it is broken in canary. I haven't noticed a problem, don't remember when I last synced (probably 2+ weeks ago). The current policy for socket() looks sane, and seems to match the usage in the sslh code: socket: arg0 == 10 && arg1 == 1 && arg2 == 0 || arg0 == 2 && arg1 == 1 && arg2 == 0 If changing it to "socket: 1" fixes the issue, maybe there is a bug in converting that expression into a BPF sequence. I don't know where these are coming from: [pid 4568] access("/proc/net", R_OK) = 0 [pid 4568] access("/proc/net/unix", R_OK) = 0 [pid 4568] syscall_18446744073709551615(0x1, 0x80002, 0, 0x7ffff591ff20, 0xfefefefefefefeff, 0xfefefeff77686d74) = 0x29 [pid 4568] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x775761df0167, si_syscall=__NR_socket, si_arch=AUDIT_ARCH_X86_64} --- Syscall 0xffffffffffffffff? Hmmmm.
,
Oct 6 2017
there is a known issue with minijail & syslog related to socket() due to sslh using -L that has been fixed via issue 769047 . the CL for updating minijail is in review now. but what i find interesting is this: [pid 4568] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_call_addr=0x775761d2c0c0, si_syscall=__NR_rt_sigprocmask, si_arch=AUDIT_ARCH_X86_64} --- where is that sigprocmask coming from ? minijail ?
,
Oct 7 2017
This is enough to make ssh over IPv6 work again: --- sslh-seccomp.policy.orig 2017-10-06 17:59:14.522996997 -0700 +++ sslh-seccomp.policy 2017-10-06 18:26:42.642002894 -0700 @@ -12,7 +12,8 @@ clone: 1 exit_group: 1 # We only want to allow AF_INET, AF_INET6, and SOCK_STREAM. -socket: arg0 == 10 && arg1 == 1 && arg2 == 0 || arg0 == 2 && arg1 == 1 && arg2 == 0 +socket: 1 +ioctl: 1 connect: 1 open: 1 stat: 1 > some 5min seccomp crash course This was useful: https://www.chromium.org/chromium-os/developer-guide/chromium-os-sandboxing > If changing it to "socket: 1" fixes the issue, As seen above it helped but wasn't enough. Without the ioctl line I was (surprise...) getting this: 2017-10-06T18:25:53.056173-07:00 ERR sslh-fork[3817]: libminijail[5]: blocked syscall: ioctl > Syscall 0xffffffffffffffff? Hmmmm. > [...] > but what i find interesting is this [...] where is that sigprocmask coming from ? Now I'm not so sure strace and seccomp play along well.
,
Oct 7 2017
> Now I'm not so sure strace and seccomp play along well. In my experience, they do not.
,
Oct 7 2017
Here's an strace of a *successful* connection over IPv6 thanks to the above policy change repeated here too.
Reminder this is a link-local address (poor man's IPv6)
-socket: arg0 == 10 && arg1 == 1 && arg2 == 0 || arg0 == 2 && arg1 == 1 && arg2 == 0
+socket: 1
+ioctl: 1
[pid 3335] read(6, "SSH-2.0-OpenSSH_7.4\r\n", 8192) = 21
[pid 3335] getpeername(6, {sa_family=AF_INET6, sin6_port=htons(60217), inet_pton(AF_INET6, "fe80::1423:78e3:7b92:6094", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=if_nametoindex("eth1")}, [128->28]) = 0
[pid 3335] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 4
[pid 3335] connect(4, {sa_family=AF_INET, sin_port=htons(2222), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
[pid 3335] getpeername(6, {sa_family=AF_INET6, sin6_port=htons(60217), inet_pton(AF_INET6, "fe80::1423:78e3:7b92:6094", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=if_nametoindex("eth1")}, [128->28]) = 0
[pid 3335] access("/proc/net", R_OK) = 0
[pid 3335] access("/proc/net/unix", R_OK) = 0
[pid 3335] socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 7
[pid 3335] ioctl(7, SIOCGIFNAME, {ifr_index=4, ifr_name="eth1"}) = 0
[pid 3335] close(7) = 0
[pid 3335] getsockname(6, {sa_family=AF_INET6, sin6_port=htons(22), inet_pton(AF_INET6, "fe80::20e:c6ff:fe88:ffa7", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=if_nametoindex("eth1")}, [128->28]) = 0
[pid 3335] socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 7
[pid 3335] ioctl(7, SIOCGIFNAME, {ifr_index=4, ifr_name="eth1"}) = 0
[pid 3335] close(7) = 0
[pid 3335] getpeername(4, {sa_family=AF_INET, sin_port=htons(2222), sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 0
[pid 3335] getsockname(4, {sa_family=AF_INET, sin_port=htons(43182), sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 0
[pid 3335] write(2, "ssh:connection from fe80::1423:7"..., 142) = 142
[pid 3335] write(4, "SSH-2.0-OpenSSH_7.4\r\n", 21) = 21
[pid 3335] select(7, [4 6], NULL, NULL, NULL) = 1 (in [4])
[pid 3335] read(4, "SSH-2.0-OpenSSH_7.5p1-hpn14v12\r\n", 8192) = 32
[pid 3335] write(6, "SSH-2.0-OpenSSH_7.5p1-hpn14v12\r\n", 32) = 32
[pid 3335] select(7, [4 6], NULL, NULL, NULL) = 1 (in [4])
[pid 3335] read(4, "\0\0\4$\n\24\274\345\342[\305'J\204\212\0\260\202_\201\234\267\0\0\1\2curve2"..., 8192) = 1064
,
Oct 7 2017
[pid 3335] socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 7
[pid 3335] ioctl(7, SIOCGIFNAME, {ifr_index=4, ifr_name="eth1"}) = 0
[pid 3335] close(7) = 0
This is translating the scope_id from an interface index to an interface name. I don't see anything in the sslh code that is doing this, so it could be from libc, or strace, or something else.
I'm guessing that this step would be skipped if scope_id was 0, so maybe the fact that you're using link-local addresses is relevant here. That isn't something that would normally be tested at Google, because workstations and test Chromebooks are never on the same LAN. If you switch to a ULA or public IPv6 address, does that hide the problem?
,
Oct 7 2017
yeah, sounds like it's due to the zone ids. we can whitelist those specific ioctl's (we don't want to whitelist all of them).
glibc/sysdeps/unix/sysv/linux/if_index.c:
char *
__if_indextoname (unsigned int ifindex, char *ifname)
{
/* We may be able to do the conversion directly, rather than searching a
list. This ioctl is not present in kernels before version 2.1.50. */
struct ifreq ifr;
int fd;
int status;
fd = __opensock ();
if (fd < 0)
return NULL;
ifr.ifr_ifindex = ifindex;
status = __ioctl (fd, SIOCGIFNAME, &ifr);
close_not_cancel_no_status (fd);
if (status < 0)
{
if (errno == ENODEV)
/* POSIX requires ENXIO. */
__set_errno (ENXIO);
return NULL;
}
else
return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
}
,
Oct 7 2017
Away from the system so can't make 100% sure, yet confident I found the other pieces: https://github.com/yrutschle/sslh/blob/0929d39a34a78e/common.c#L519 sslh/common.c#log_connection() sslh/common.c#sprintaddr() glibc/inet/getnameinfo.c#getnameinfo() if (IN6_IS_ADDR_LINKLOCAL(...)) { if_indextoname(..) > PS: I'm using link local address; I doubt it matters. :-( > we can whitelist those specific ioctl Thanks! I can help with at least testing.
,
Oct 7 2017
Makes sense; getnameinfo() can add the scope ID to the string. This prints "fe80::1%lo":
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netinet/ip6.h>
int main(int argc, char **argv)
{
struct sockaddr_in6 s = {0};
s.sin6_family = AF_INET6;
s.sin6_addr.s6_addr[0] = 0xfe;
s.sin6_addr.s6_addr[1] = 0x80;
s.sin6_addr.s6_addr[15] = 0x1;
s.sin6_scope_id = 1;
char host[256];
if (getnameinfo((void *)&s, sizeof(s), host, sizeof(host), NULL, 0,
NI_NUMERICHOST) < 0) {
printf("error: %d\n", errno);
} else {
puts(host);
}
return 0;
}
,
Oct 7 2017
,
Oct 9 2017
Just +1 Verified https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/706715 uploaded by Mike (thx). With strace -s 100: [pid 3348] write(2, "ssh:connection from fe80::1423:78e3:7b92:6094%eth1:62776 to fe80::20e:c6ff:fe88:ffa7%eth1:22 forward"..., 142) = 142
,
Oct 10 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/d24031bee8702e14fb53aa6e54141577b702c76b commit d24031bee8702e14fb53aa6e54141577b702c76b Author: Mike Frysinger <vapier@chromium.org> Date: Tue Oct 10 00:39:09 2017 arc-sslh-init: expand seccomp for IPv6 zone id lookups When using IPv6 with zone ids, glibc will look up interface details via SIOCGIFNAME on an AF_UNIX socket. Allow those in the seccomp filters. Sync/sort the filters too to cut down on diffs between them. BUG= chromium:772273 TEST=precq passes Change-Id: If6939854e63fcdc8ee3fceb849e50c5b412d7a1c Reviewed-on: https://chromium-review.googlesource.com/706715 Commit-Ready: Mike Frysinger <vapier@chromium.org> Tested-by: Marc Herbert <marc.herbert@intel.com> Tested-by: Mike Frysinger <vapier@chromium.org> Reviewed-by: Kevin Cernekee <cernekee@chromium.org> [rename] https://crrev.com/d24031bee8702e14fb53aa6e54141577b702c76b/chromeos-base/arc-sslh-init/arc-sslh-init-0.0.1-r2.ebuild [modify] https://crrev.com/d24031bee8702e14fb53aa6e54141577b702c76b/chromeos-base/arc-sslh-init/files/sslh-seccomp-arm.policy [modify] https://crrev.com/d24031bee8702e14fb53aa6e54141577b702c76b/chromeos-base/arc-sslh-init/files/sslh-seccomp-amd64.policy
,
Oct 10 2017
,
Jan 22 2018
,
Jan 23 2018
,
Sep 13
|
|||||||||||||||||||||||
►
Sign in to add a comment |
|||||||||||||||||||||||
Comment 1 by jorgelo@chromium.org
, Oct 6 2017