xref: /aosp_15_r20/kernel/tests/net/test/namespace.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
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