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 """ 60 The actual test. 61 """ 62 errors = set() 63 64 # Max procs, max threads, and file max are dependent upon total memory. 65 # The kernel uses a formula similar to: 66 # MemTotal-kb / 128 = max procs 67 # MemTotal-kb / 64 = max threads 68 # MemTotal-kb / 10 = file_max 69 # But note that MemTotal changes at the end of initialization. 70 # The values used below for these settings should give sufficient head 71 # room for usage and kernel allocation. 72 73 ref_min = {'file_max': 50000, 74 'kptr_restrict': 1, 75 'max_open': 1024, 76 'max_procs': 3000, 77 'max_threads': 7000, 78 'ngroups_max': 65536, 79 'nr_open': 1048576, 80 'pid_max': 32768, 81 'mmap_min_addr': 32768, 82 } 83 84 ref_equal = {'leases': 1, 85 'panic': -1, 86 'protected_hardlinks': 1, 87 'protected_symlinks': 1, 88 'ptrace_scope': 1, 89 'randomize_va_space': 2, 90 'sched_rt_period_us': 1000000, 91 'sched_rt_runtime_us': 800000, 92 'sysrq': 1, 93 'suid-dump': 2, 94 'tcp_syncookies': 1, 95 } 96 97 refpath = {'file_max': '/proc/sys/fs/file-max', 98 'leases': '/proc/sys/fs/leases-enable', 99 'max_open': '/proc/self/limits', 100 'max_procs': '/proc/self/limits', 101 'max_threads': '/proc/sys/kernel/threads-max', 102 'mmap_min_addr': '/proc/sys/vm/mmap_min_addr', 103 'kptr_restrict': '/proc/sys/kernel/kptr_restrict', 104 'ngroups_max': '/proc/sys/kernel/ngroups_max', 105 'nr_open': '/proc/sys/fs/nr_open', 106 'panic': '/proc/sys/kernel/panic', 107 'pid_max': '/proc/sys/kernel/pid_max', 108 'protected_hardlinks': '/proc/sys/fs/protected_hardlinks', 109 'protected_symlinks': '/proc/sys/fs/protected_symlinks', 110 'ptrace_scope': '/proc/sys/kernel/yama/ptrace_scope', 111 'randomize_va_space': '/proc/sys/kernel/randomize_va_space', 112 'sched_rt_period_us': '/proc/sys/kernel/sched_rt_period_us', 113 'sched_rt_runtime_us': '/proc/sys/kernel/sched_rt_runtime_us', 114 'suid-dump': '/proc/sys/fs/suid_dumpable', 115 'sysrq': '/proc/sys/kernel/sysrq', 116 'tcp_syncookies': '/proc/sys/net/ipv4/tcp_syncookies', 117 } 118 119 # Adjust version-specific details. 120 kernel_ver = os.uname()[2] 121 if utils.compare_versions(kernel_ver, "3.6") < 0: 122 # Prior to kernel version 3.6, Yama handled link restrictions. 123 refpath['protected_hardlinks'] = \ 124 '/proc/sys/kernel/yama/protected_nonaccess_hardlinks' 125 refpath['protected_symlinks'] = \ 126 '/proc/sys/kernel/yama/protected_sticky_symlinks' 127 128 # Create osvalue dictionary with the same keys as refpath. 129 osvalue = {} 130 for key in refpath: 131 osvalue[key] = None 132 133 for key in ref_min: 134 osvalue[key] = self.get_limit(key, refpath[key]) 135 if osvalue[key] < ref_min[key]: 136 logging.warning('%s is %d', refpath[key], osvalue[key]) 137 logging.warning('%s should be at least %d', refpath[key], 138 ref_min[key]) 139 errors.add(key) 140 else: 141 logging.info('%s is %d >= %d', refpath[key], osvalue[key], 142 ref_min[key]) 143 144 for key in ref_equal: 145 osvalue[key] = self.get_limit(key, refpath[key]) 146 if osvalue[key] != ref_equal[key]: 147 logging.warning('%s is set to %d', refpath[key], osvalue[key]) 148 logging.warning('Expected %d', ref_equal[key]) 149 errors.add(key) 150 else: 151 logging.info('%s is %d', refpath[key], osvalue[key]) 152 153 # Look for anything from refpath that wasn't checked yet: 154 for key in osvalue: 155 if osvalue[key] == None: 156 logging.warning('%s was never checked', key) 157 errors.add(key) 158 159 # If self.error is not zero, there were errors. 160 if len(errors) > 0: 161 raise error.TestFail('Found incorrect values: %s' % 162 ', '.join(errors)) 163