1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2020 The Android Open Source Project 4*2f2c4c7aSAndroid Build Coastguard Worker# 5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*2f2c4c7aSAndroid Build Coastguard Worker# 9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*2f2c4c7aSAndroid Build Coastguard Worker# 11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License. 16*2f2c4c7aSAndroid Build Coastguard Worker 17*2f2c4c7aSAndroid Build Coastguard Worker"""Namespace related support code.""" 18*2f2c4c7aSAndroid Build Coastguard Worker 19*2f2c4c7aSAndroid Build Coastguard Workerimport ctypes 20*2f2c4c7aSAndroid Build Coastguard Workerimport ctypes.util 21*2f2c4c7aSAndroid Build Coastguard Workerimport os 22*2f2c4c7aSAndroid Build Coastguard Workerimport socket 23*2f2c4c7aSAndroid Build Coastguard Workerimport sys 24*2f2c4c7aSAndroid Build Coastguard Worker 25*2f2c4c7aSAndroid Build Coastguard Workerimport net_test 26*2f2c4c7aSAndroid Build Coastguard Workerimport sock_diag 27*2f2c4c7aSAndroid Build Coastguard Workerimport tcp_test 28*2f2c4c7aSAndroid Build Coastguard Worker 29*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=bad-whitespace 30*2f2c4c7aSAndroid Build Coastguard Worker 31*2f2c4c7aSAndroid Build Coastguard Worker# //include/linux/fs.h 32*2f2c4c7aSAndroid Build Coastguard WorkerMNT_FORCE = 1 # Attempt to forcibily umount 33*2f2c4c7aSAndroid Build Coastguard WorkerMNT_DETACH = 2 # Just detach from the tree 34*2f2c4c7aSAndroid Build Coastguard WorkerMNT_EXPIRE = 4 # Mark for expiry 35*2f2c4c7aSAndroid Build Coastguard WorkerUMOUNT_NOFOLLOW = 8 # Don't follow symlink on umount 36*2f2c4c7aSAndroid Build Coastguard Worker 37*2f2c4c7aSAndroid Build Coastguard Worker# //include/uapi/linux/fs.h 38*2f2c4c7aSAndroid Build Coastguard WorkerMS_RDONLY = 1 # Mount read-only 39*2f2c4c7aSAndroid Build Coastguard WorkerMS_NOSUID = 2 # Ignore suid and sgid bits 40*2f2c4c7aSAndroid Build Coastguard WorkerMS_NODEV = 4 # Disallow access to device special files 41*2f2c4c7aSAndroid Build Coastguard WorkerMS_NOEXEC = 8 # Disallow program execution 42*2f2c4c7aSAndroid Build Coastguard WorkerMS_SYNCHRONOUS = 16 # Writes are synced at once 43*2f2c4c7aSAndroid Build Coastguard WorkerMS_REMOUNT = 32 # Alter flags of a mounted FS 44*2f2c4c7aSAndroid Build Coastguard WorkerMS_MANDLOCK = 64 # Allow mandatory locks on an FS 45*2f2c4c7aSAndroid Build Coastguard WorkerMS_DIRSYNC = 128 # Directory modifications are synchronous 46*2f2c4c7aSAndroid Build Coastguard WorkerMS_NOATIME = 1024 # Do not update access times. 47*2f2c4c7aSAndroid Build Coastguard WorkerMS_NODIRATIME = 2048 # Do not update directory access times 48*2f2c4c7aSAndroid Build Coastguard WorkerMS_BIND = 4096 # 49*2f2c4c7aSAndroid Build Coastguard WorkerMS_MOVE = 8192 # 50*2f2c4c7aSAndroid Build Coastguard WorkerMS_REC = 16384 # 51*2f2c4c7aSAndroid Build Coastguard WorkerMS_SILENT = 32768 # 52*2f2c4c7aSAndroid Build Coastguard WorkerMS_POSIXACL = (1<<16) # VFS does not apply the umask 53*2f2c4c7aSAndroid Build Coastguard WorkerMS_UNBINDABLE = (1<<17) # change to unbindable 54*2f2c4c7aSAndroid Build Coastguard WorkerMS_PRIVATE = (1<<18) # change to private 55*2f2c4c7aSAndroid Build Coastguard WorkerMS_SLAVE = (1<<19) # change to slave 56*2f2c4c7aSAndroid Build Coastguard WorkerMS_SHARED = (1<<20) # change to shared 57*2f2c4c7aSAndroid Build Coastguard WorkerMS_RELATIME = (1<<21) # Update atime relative to mtime/ctime. 58*2f2c4c7aSAndroid Build Coastguard WorkerMS_STRICTATIME = (1<<24) # Always perform atime updates 59*2f2c4c7aSAndroid Build Coastguard WorkerMS_LAZYTIME = (1<<25) # Update the on-disk [acm]times lazily 60*2f2c4c7aSAndroid Build Coastguard Worker 61*2f2c4c7aSAndroid Build Coastguard Worker# //include/uapi/linux/sched.h 62*2f2c4c7aSAndroid Build Coastguard WorkerCLONE_NEWNS = 0x00020000 # New mount namespace group 63*2f2c4c7aSAndroid Build Coastguard WorkerCLONE_NEWCGROUP = 0x02000000 # New cgroup namespace 64*2f2c4c7aSAndroid Build Coastguard WorkerCLONE_NEWUTS = 0x04000000 # New utsname namespace 65*2f2c4c7aSAndroid Build Coastguard WorkerCLONE_NEWIPC = 0x08000000 # New ipc namespace 66*2f2c4c7aSAndroid Build Coastguard WorkerCLONE_NEWUSER = 0x10000000 # New user namespace 67*2f2c4c7aSAndroid Build Coastguard WorkerCLONE_NEWPID = 0x20000000 # New pid namespace 68*2f2c4c7aSAndroid Build Coastguard WorkerCLONE_NEWNET = 0x40000000 # New network namespace 69*2f2c4c7aSAndroid Build Coastguard Worker 70*2f2c4c7aSAndroid Build Coastguard Worker# pylint: enable=bad-whitespace 71*2f2c4c7aSAndroid Build Coastguard Worker 72*2f2c4c7aSAndroid Build Coastguard Workerlibc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) 73*2f2c4c7aSAndroid Build Coastguard Worker 74*2f2c4c7aSAndroid Build Coastguard Worker# See the relevant system call's man pages and: 75*2f2c4c7aSAndroid Build Coastguard Worker# https://docs.python.org/3/library/ctypes.html#fundamental-data-types 76*2f2c4c7aSAndroid Build Coastguard Workerlibc.mount.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, 77*2f2c4c7aSAndroid Build Coastguard Worker ctypes.c_ulong, ctypes.c_void_p) 78*2f2c4c7aSAndroid Build Coastguard Workerlibc.sethostname.argtypes = (ctypes.c_char_p, ctypes.c_size_t) 79*2f2c4c7aSAndroid Build Coastguard Workerlibc.umount2.argtypes = (ctypes.c_char_p, ctypes.c_int) 80*2f2c4c7aSAndroid Build Coastguard Workerlibc.unshare.argtypes = (ctypes.c_int,) 81*2f2c4c7aSAndroid Build Coastguard Worker 82*2f2c4c7aSAndroid Build Coastguard Worker 83*2f2c4c7aSAndroid Build Coastguard Workerdef Mount(src, tgt, fs, flags=MS_NODEV|MS_NOEXEC|MS_NOSUID|MS_RELATIME): 84*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.mount(src.encode(), tgt.encode(), fs.encode() if fs else None, 85*2f2c4c7aSAndroid Build Coastguard Worker flags, None) 86*2f2c4c7aSAndroid Build Coastguard Worker if ret < 0: 87*2f2c4c7aSAndroid Build Coastguard Worker err = ctypes.get_errno() 88*2f2c4c7aSAndroid Build Coastguard Worker raise OSError(err, '%s mounting %s on %s (fs=%s flags=0x%x)' 89*2f2c4c7aSAndroid Build Coastguard Worker % (os.strerror(err), src, tgt, fs, flags)) 90*2f2c4c7aSAndroid Build Coastguard Worker 91*2f2c4c7aSAndroid Build Coastguard Worker 92*2f2c4c7aSAndroid Build Coastguard Workerdef ReMountProc(): 93*2f2c4c7aSAndroid Build Coastguard Worker libc.umount2(b'/proc', MNT_DETACH) # Ignore failure: might not be mounted 94*2f2c4c7aSAndroid Build Coastguard Worker Mount('proc', '/proc', 'proc') 95*2f2c4c7aSAndroid Build Coastguard Worker 96*2f2c4c7aSAndroid Build Coastguard Worker 97*2f2c4c7aSAndroid Build Coastguard Workerdef ReMountSys(): 98*2f2c4c7aSAndroid Build Coastguard Worker libc.umount2(b'/sys/fs/cgroup', MNT_DETACH) # Ign. fail: might not be mounted 99*2f2c4c7aSAndroid Build Coastguard Worker libc.umount2(b'/sys/fs/bpf', MNT_DETACH) # Ignore fail: might not be mounted 100*2f2c4c7aSAndroid Build Coastguard Worker libc.umount2(b'/sys', MNT_DETACH) # Ignore fail: might not be mounted 101*2f2c4c7aSAndroid Build Coastguard Worker Mount('sysfs', '/sys', 'sysfs') 102*2f2c4c7aSAndroid Build Coastguard Worker Mount('bpf', '/sys/fs/bpf', 'bpf') 103*2f2c4c7aSAndroid Build Coastguard Worker Mount('cgroup2', '/sys/fs/cgroup', 'cgroup2') 104*2f2c4c7aSAndroid Build Coastguard Worker 105*2f2c4c7aSAndroid Build Coastguard Worker 106*2f2c4c7aSAndroid Build Coastguard Workerdef SetFileContents(f, s): 107*2f2c4c7aSAndroid Build Coastguard Worker with open(f, 'w') as set_file: 108*2f2c4c7aSAndroid Build Coastguard Worker set_file.write(s) 109*2f2c4c7aSAndroid Build Coastguard Worker 110*2f2c4c7aSAndroid Build Coastguard Worker 111*2f2c4c7aSAndroid Build Coastguard Workerdef SetHostname(s): 112*2f2c4c7aSAndroid Build Coastguard Worker hostname = s.encode() 113*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.sethostname(hostname, len(hostname)) 114*2f2c4c7aSAndroid Build Coastguard Worker if ret < 0: 115*2f2c4c7aSAndroid Build Coastguard Worker err = ctypes.get_errno() 116*2f2c4c7aSAndroid Build Coastguard Worker raise OSError(err, '%s while sethostname(%s)' % (os.strerror(err), s)) 117*2f2c4c7aSAndroid Build Coastguard Worker 118*2f2c4c7aSAndroid Build Coastguard Worker 119*2f2c4c7aSAndroid Build Coastguard Workerdef UnShare(flags): 120*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.unshare(flags) 121*2f2c4c7aSAndroid Build Coastguard Worker if ret < 0: 122*2f2c4c7aSAndroid Build Coastguard Worker err = ctypes.get_errno() 123*2f2c4c7aSAndroid Build Coastguard Worker raise OSError(err, '%s while unshare(0x%x)' % (os.strerror(err), flags)) 124*2f2c4c7aSAndroid Build Coastguard Worker 125*2f2c4c7aSAndroid Build Coastguard Worker 126*2f2c4c7aSAndroid Build Coastguard Workerdef DumpMounts(hdr): 127*2f2c4c7aSAndroid Build Coastguard Worker print('') 128*2f2c4c7aSAndroid Build Coastguard Worker print(hdr) 129*2f2c4c7aSAndroid Build Coastguard Worker with open('/proc/mounts', 'r') as mounts: 130*2f2c4c7aSAndroid Build Coastguard Worker sys.stdout.write(mounts.read()) 131*2f2c4c7aSAndroid Build Coastguard Worker print('---') 132*2f2c4c7aSAndroid Build Coastguard Worker 133*2f2c4c7aSAndroid Build Coastguard Worker 134*2f2c4c7aSAndroid Build Coastguard Worker# Requires at least kernel configuration options: 135*2f2c4c7aSAndroid Build Coastguard Worker# CONFIG_NAMESPACES=y 136*2f2c4c7aSAndroid Build Coastguard Worker# CONFIG_NET_NS=y 137*2f2c4c7aSAndroid Build Coastguard Worker# CONFIG_UTS_NS=y 138*2f2c4c7aSAndroid Build Coastguard Workerdef EnterNewNetworkNamespace(): 139*2f2c4c7aSAndroid Build Coastguard Worker """Instantiate and transition into a fresh new network namespace.""" 140*2f2c4c7aSAndroid Build Coastguard Worker 141*2f2c4c7aSAndroid Build Coastguard Worker try: 142*2f2c4c7aSAndroid Build Coastguard Worker UnShare(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWNET) 143*2f2c4c7aSAndroid Build Coastguard Worker except OSError as err: 144*2f2c4c7aSAndroid Build Coastguard Worker print('failed: %s (likely: no privs or lack of kernel support).' % err) 145*2f2c4c7aSAndroid Build Coastguard Worker raise 146*2f2c4c7aSAndroid Build Coastguard Worker 147*2f2c4c7aSAndroid Build Coastguard Worker try: 148*2f2c4c7aSAndroid Build Coastguard Worker # DumpMounts('Before:') 149*2f2c4c7aSAndroid Build Coastguard Worker Mount('none', '/', None, MS_REC|MS_PRIVATE) 150*2f2c4c7aSAndroid Build Coastguard Worker ReMountProc() 151*2f2c4c7aSAndroid Build Coastguard Worker ReMountSys() 152*2f2c4c7aSAndroid Build Coastguard Worker # DumpMounts('After:') 153*2f2c4c7aSAndroid Build Coastguard Worker SetHostname('netns') 154*2f2c4c7aSAndroid Build Coastguard Worker SetFileContents('/proc/sys/net/ipv4/ping_group_range', '0 2147483647') 155*2f2c4c7aSAndroid Build Coastguard Worker net_test.SetInterfaceUp('lo') 156*2f2c4c7aSAndroid Build Coastguard Worker except: 157*2f2c4c7aSAndroid Build Coastguard Worker print('failed.') 158*2f2c4c7aSAndroid Build Coastguard Worker # We've already transitioned into the new netns -- it's too late to recover. 159*2f2c4c7aSAndroid Build Coastguard Worker raise 160*2f2c4c7aSAndroid Build Coastguard Worker 161*2f2c4c7aSAndroid Build Coastguard Worker print('succeeded.') 162*2f2c4c7aSAndroid Build Coastguard Worker 163*2f2c4c7aSAndroid Build Coastguard Worker 164*2f2c4c7aSAndroid Build Coastguard Workerdef HasEstablishedTcpSessionOnPort(port): 165*2f2c4c7aSAndroid Build Coastguard Worker sd = sock_diag.SockDiag() 166*2f2c4c7aSAndroid Build Coastguard Worker 167*2f2c4c7aSAndroid Build Coastguard Worker sock_id = sd._EmptyInetDiagSockId() # pylint: disable=protected-access 168*2f2c4c7aSAndroid Build Coastguard Worker sock_id.sport = port 169*2f2c4c7aSAndroid Build Coastguard Worker 170*2f2c4c7aSAndroid Build Coastguard Worker states = 1 << tcp_test.TCP_ESTABLISHED 171*2f2c4c7aSAndroid Build Coastguard Worker 172*2f2c4c7aSAndroid Build Coastguard Worker matches = sd.DumpAllInetSockets(socket.IPPROTO_TCP, b'', 173*2f2c4c7aSAndroid Build Coastguard Worker sock_id=sock_id, states=states) 174*2f2c4c7aSAndroid Build Coastguard Worker 175*2f2c4c7aSAndroid Build Coastguard Worker return True if matches else False 176