1 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import logging 6 import socket 7 8 from autotest_lib.client.bin import test, utils 9 from autotest_lib.client.common_lib import error 10 11 12 # From <bits/socket.h> on Linux 3.2, EGLIBC 2.15. 13 PROTOCOL_FAMILIES_STR = """ 14 #define PF_UNSPEC 0 /* Unspecified. */ 15 #define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ 16 #define PF_UNIX 1 /* POSIX name for PF_LOCAL. */ 17 #define PF_FILE 1 /* Another non-standard name for PF_LOCAL. */ 18 #define PF_INET 2 /* IP protocol family. */ 19 #define PF_AX25 3 /* Amateur Radio AX.25. */ 20 #define PF_IPX 4 /* Novell Internet Protocol. */ 21 #define PF_APPLETALK 5 /* Appletalk DDP. */ 22 #define PF_NETROM 6 /* Amateur radio NetROM. */ 23 #define PF_BRIDGE 7 /* Multiprotocol bridge. */ 24 #define PF_ATMPVC 8 /* ATM PVCs. */ 25 #define PF_X25 9 /* Reserved for X.25 project. */ 26 #define PF_INET6 10 /* IP version 6. */ 27 #define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ 28 #define PF_DECnet 12 /* Reserved for DECnet project. */ 29 #define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ 30 #define PF_SECURITY 14 /* Security callback pseudo AF. */ 31 #define PF_KEY 15 /* PF_KEY key management API. */ 32 #define PF_NETLINK 16 33 #define PF_ROUTE 16 /* Alias to emulate 4.4BSD. */ 34 #define PF_PACKET 17 /* Packet family. */ 35 #define PF_ASH 18 /* Ash. */ 36 #define PF_ECONET 19 /* Acorn Econet. */ 37 #define PF_ATMSVC 20 /* ATM SVCs. */ 38 #define PF_RDS 21 /* RDS sockets. */ 39 #define PF_SNA 22 /* Linux SNA Project */ 40 #define PF_IRDA 23 /* IRDA sockets. */ 41 #define PF_PPPOX 24 /* PPPoX sockets. */ 42 #define PF_WANPIPE 25 /* Wanpipe API sockets. */ 43 #define PF_LLC 26 /* Linux LLC. */ 44 #define PF_CAN 29 /* Controller Area Network. */ 45 #define PF_TIPC 30 /* TIPC sockets. */ 46 #define PF_BLUETOOTH 31 /* Bluetooth sockets. */ 47 #define PF_IUCV 32 /* IUCV sockets. */ 48 #define PF_RXRPC 33 /* RxRPC sockets. */ 49 #define PF_ISDN 34 /* mISDN sockets. */ 50 #define PF_PHONET 35 /* Phonet sockets. */ 51 #define PF_IEEE802154 36 /* IEEE 802.15.4 sockets. */ 52 #define PF_CAIF 37 /* CAIF sockets. */ 53 #define PF_ALG 38 /* Algorithm sockets. */ 54 #define PF_NFC 39 /* NFC sockets. */ 55 #define PF_MAX 40 /* For now... */ 56 """ 57 58 PROTOCOL_FAMILIES = dict([(int(line.split()[2]), line.split()[1]) 59 for line 60 in PROTOCOL_FAMILIES_STR.strip().splitlines()]) 61 62 SOCKET_TYPES = [socket.SOCK_STREAM, socket.SOCK_DGRAM, socket.SOCK_RAW, 63 socket.SOCK_RDM, socket.SOCK_SEQPACKET] 64 65 66 class security_ProtocolFamilies(test.test): 67 version = 1 68 PF_BASELINE = ["PF_FILE", "PF_PACKET", "PF_INET", "PF_INET6", "PF_ROUTE", 69 "PF_LOCAL", "PF_NETLINK", "PF_UNIX", "PF_BLUETOOTH", "PF_ALG"] 70 PER_BOARD = {} 71 72 73 def pf_name(self, pfn): 74 protocol_family = "" 75 76 if pfn in PROTOCOL_FAMILIES: 77 protocol_family = PROTOCOL_FAMILIES[pfn] 78 else: 79 protocol_family = "PF %d (unknown)" % pfn 80 81 return protocol_family 82 83 84 def is_protocol_family_available(self, pfn): 85 """Tries to create a socket with protocol family number |pfn| 86 and every possible socket type. 87 Returns |True| if any socket can be created, |False| otherwise. 88 """ 89 90 available = False 91 92 for socket_type in SOCKET_TYPES: 93 try: 94 socket.socket(pfn, socket_type) 95 available = True 96 logging.info("%s available with socket type %d" % 97 (self.pf_name(pfn), socket_type)) 98 break 99 except socket.error: 100 pass 101 102 return available 103 104 105 def run_once(self): 106 """Tries to create a socket with every possible combination of 107 protocol family and socket type. 108 Fails if it can create a socket for one or more protocol families 109 not in the baseline. 110 """ 111 112 unexpected_protocol_families = [] 113 114 # Protocol families currently go up to 40, but this way we make sure 115 # to catch new families that might get added to the kernel. 116 for pfn in range(256): 117 pf_available = self.is_protocol_family_available(pfn) 118 protocol_family = self.pf_name(pfn) 119 120 if pf_available: 121 # If PF is in baseline, continue. 122 if protocol_family in self.PF_BASELINE: 123 continue 124 125 # Check the board-specific whitelist. 126 current_board = utils.get_current_board() 127 board_pfs = self.PER_BOARD.get(current_board, None) 128 if not board_pfs or protocol_family not in board_pfs: 129 unexpected_protocol_families.append(protocol_family) 130 131 if len(unexpected_protocol_families) > 0: 132 failure_string = "Unexpected protocol families available: " 133 failure_string += ", ".join(unexpected_protocol_families) 134 logging.error(failure_string) 135 raise error.TestFail(failure_string) 136