1 #!/usr/bin/python 2 # 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 __author__ = 'kdlucas (at] chromium.org (Kelly Lucas)' 8 9 import logging 10 import os 11 12 from autotest_lib.client.bin import utils, test 13 from autotest_lib.client.common_lib import error 14 15 16 class platform_OSLimits(test.test): 17 """ 18 Verify os limitations are set to correct levels. 19 """ 20 version = 1 21 22 def get_limit(self, key, path): 23 """ 24 Find and return values held in path. 25 26 Args: 27 key: dictionary key of os limit. 28 path: pathname of file with current value. 29 Returns: 30 value found in path. If it's a number we'll convert to integer. 31 """ 32 33 value = None 34 # Most files have only one value, but if there are multiple values we 35 # will handle it differently. Determine this from the key. 36 37 multivals = ['max_open', 'max_procs'] 38 limits = {'max_open': 'Max open files', 39 'max_procs': 'Max processes', 40 } 41 42 if key in multivals: 43 output = utils.read_file(path) 44 lines = output.splitlines() 45 for line in lines: 46 if limits[key] in line: 47 fields = line.split(limits[key]) 48 vals = fields[1].split() 49 value = (vals[0]) 50 else: 51 value = (utils.read_one_line(path)) 52 53 if value == 'unlimited': 54 return value 55 else: 56 return int(value) 57 58 def run_once(self): 59 errors = set() 60 61 # Max procs, max threads, and file max are dependent upon total memory. 62 # The kernel uses a formula similar to: 63 # MemTotal-kb / 128 = max procs 64 # MemTotal-kb / 64 = max threads 65 # MemTotal-kb / 10 = file_max 66 # But note that MemTotal changes at the end of initialization. 67 # The values used below for these settings should give sufficient head 68 # room for usage and kernel allocation. 69 70 ref_min = {'file_max': 50000, 71 'kptr_restrict': 1, 72 'max_open': 1024, 73 'max_procs': 3000, 74 'max_threads': 7000, 75 'ngroups_max': 65536, 76 'nr_open': 1048576, 77 'pid_max': 32768, 78 'mmap_min_addr': 65536, 79 } 80 81 ref_equal = {'leases': 1, 82 'panic': -1, 83 'protected_hardlinks': 1, 84 'protected_symlinks': 1, 85 'ptrace_scope': 1, 86 'randomize_va_space': 2, 87 'sched_rt_period_us': 1000000, 88 'sched_rt_runtime_us': 800000, 89 'sysrq': 1, 90 'suid-dump': 2, 91 'tcp_syncookies': 1, 92 } 93 94 refpath = {'file_max': '/proc/sys/fs/file-max', 95 'leases': '/proc/sys/fs/leases-enable', 96 'max_open': '/proc/self/limits', 97 'max_procs': '/proc/self/limits', 98 'max_threads': '/proc/sys/kernel/threads-max', 99 'mmap_min_addr': '/proc/sys/vm/mmap_min_addr', 100 'kptr_restrict': '/proc/sys/kernel/kptr_restrict', 101 'ngroups_max': '/proc/sys/kernel/ngroups_max', 102 'nr_open': '/proc/sys/fs/nr_open', 103 'panic': '/proc/sys/kernel/panic', 104 'pid_max': '/proc/sys/kernel/pid_max', 105 'protected_hardlinks': '/proc/sys/fs/protected_hardlinks', 106 'protected_symlinks': '/proc/sys/fs/protected_symlinks', 107 'ptrace_scope': '/proc/sys/kernel/yama/ptrace_scope', 108 'randomize_va_space': '/proc/sys/kernel/randomize_va_space', 109 'sched_rt_period_us': '/proc/sys/kernel/sched_rt_period_us', 110 'sched_rt_runtime_us': '/proc/sys/kernel/sched_rt_runtime_us', 111 'suid-dump': '/proc/sys/fs/suid_dumpable', 112 'sysrq': '/proc/sys/kernel/sysrq', 113 'tcp_syncookies': '/proc/sys/net/ipv4/tcp_syncookies', 114 } 115 116 # Adjust arch-specific values. 117 if utils.get_arch().startswith('arm'): 118 ref_min['mmap_min_addr'] = 32768 119 120 if utils.get_arch().startswith('aarch64'): 121 ref_min['mmap_min_addr'] = 32768 122 123 # ARM-compatible limit on x86 if ARC++ is present (b/30146997) 124 if utils.is_arc_available(): 125 ref_min['mmap_min_addr'] = 32768 126 127 # Adjust version-specific details. 128 kernel_ver = os.uname()[2] 129 if utils.compare_versions(kernel_ver, "3.6") < 0: 130 # Prior to kernel version 3.6, Yama handled link restrictions. 131 refpath['protected_hardlinks'] = \ 132 '/proc/sys/kernel/yama/protected_nonaccess_hardlinks' 133 refpath['protected_symlinks'] = \ 134 '/proc/sys/kernel/yama/protected_sticky_symlinks' 135 136 # Create osvalue dictionary with the same keys as refpath. 137 osvalue = {} 138 for key in refpath: 139 osvalue[key] = None 140 141 for key in ref_min: 142 osvalue[key] = self.get_limit(key, refpath[key]) 143 if osvalue[key] < ref_min[key]: 144 logging.warning('%s is %d', refpath[key], osvalue[key]) 145 logging.warning('%s should be at least %d', refpath[key], 146 ref_min[key]) 147 errors.add(key) 148 else: 149 logging.info('%s is %d >= %d', refpath[key], osvalue[key], 150 ref_min[key]) 151 152 for key in ref_equal: 153 osvalue[key] = self.get_limit(key, refpath[key]) 154 if osvalue[key] != ref_equal[key]: 155 logging.warning('%s is set to %d', refpath[key], osvalue[key]) 156 logging.warning('Expected %d', ref_equal[key]) 157 errors.add(key) 158 else: 159 logging.info('%s is %d', refpath[key], osvalue[key]) 160 161 # Look for anything from refpath that wasn't checked yet: 162 for key in osvalue: 163 if osvalue[key] == None: 164 logging.warning('%s was never checked', key) 165 errors.add(key) 166 167 # If self.error is not zero, there were errors. 168 if len(errors) > 0: 169 raise error.TestFail('Found incorrect values: %s' % 170 ', '.join(errors)) 171