github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/script/check-config.sh (about) 1 #!/usr/bin/env bash 2 set -e -u 3 4 [ -t 1 ] || NO_COLOR=1 5 6 # bits of this were adapted from check_config.sh in docker 7 # see also https://github.com/docker/docker/blob/master/contrib/check-config.sh 8 9 possibleConfigs=( 10 '/proc/config.gz' 11 "/boot/config-$(uname -r)" 12 "/usr/src/linux-$(uname -r)/.config" 13 '/usr/src/linux/.config' 14 ) 15 possibleConfigFiles=( 16 'config.gz' 17 "config-$(uname -r)" 18 '.config' 19 ) 20 21 if ! command -v zgrep &>/dev/null; then 22 zgrep() { 23 zcat "$2" | grep "$1" 24 } 25 fi 26 27 kernelVersion="$(uname -r)" 28 kernelMajor="${kernelVersion%%.*}" 29 kernelMinor="${kernelVersion#"$kernelMajor".}" 30 kernelMinor="${kernelMinor%%.*}" 31 32 # Usage: to check if kernel version is < 4.8, use 33 # kernel_lt 4 8 34 # (here "lt" stands for "less than"). 35 kernel_lt() { 36 [ "$kernelMajor" -lt "$1" ] && return 37 [ "$kernelMajor" -eq "$1" ] && [ "$kernelMinor" -lt "$2" ] 38 } 39 40 # Usage: to check if kernel version is >= 6.1, use 41 # kernel_ge 6 1 42 # (here "ge" stands for "greater or equal"). 43 kernel_ge() { 44 ! kernel_lt "$1" "$2" 45 } 46 47 is_set() { 48 zgrep "CONFIG_$1=[y|m]" "$CONFIG" >/dev/null 49 } 50 is_set_in_kernel() { 51 zgrep "CONFIG_$1=y" "$CONFIG" >/dev/null 52 } 53 is_set_as_module() { 54 zgrep "CONFIG_$1=m" "$CONFIG" >/dev/null 55 } 56 57 color() { 58 [ -n "${NO_COLOR:-}" ] && return 59 60 local codes=() 61 if [ "$1" = 'bold' ]; then 62 codes=("${codes[@]-}" '1') 63 shift 64 fi 65 if [ "$#" -gt 0 ]; then 66 local code='' 67 case "$1" in 68 # see https://en.wikipedia.org/wiki/ANSI_escape_code#Colors 69 black) code=30 ;; 70 red) code=31 ;; 71 green) code=32 ;; 72 yellow) code=33 ;; 73 blue) code=34 ;; 74 magenta) code=35 ;; 75 cyan) code=36 ;; 76 white) code=37 ;; 77 esac 78 if [ "$code" ]; then 79 codes=("${codes[@]-}" "$code") 80 fi 81 fi 82 local IFS=';' 83 echo -en '\033['"${codes[*]-}"'m' 84 } 85 wrap_color() { 86 text="$1" 87 shift 88 color "$@" 89 echo -n "$text" 90 color reset 91 echo 92 } 93 94 wrap_good() { 95 local name="$1" 96 shift 97 local val="$1" 98 shift 99 echo "$(wrap_color "$name" white): $(wrap_color "$val" green)" "$@" 100 } 101 102 wrap_bad() { 103 local name="$1" 104 shift 105 local val="$1" 106 shift 107 echo "$(wrap_color "$name" bold): $(wrap_color "$val" bold red)" "$@" 108 } 109 wrap_warning() { 110 wrap_color >&2 "$*" red 111 } 112 113 check_flag() { 114 if is_set_in_kernel "$1"; then 115 wrap_good "CONFIG_$1" 'enabled' 116 elif is_set_as_module "$1"; then 117 wrap_good "CONFIG_$1" 'enabled (as module)' 118 else 119 wrap_bad "CONFIG_$1" 'missing' 120 fi 121 } 122 123 check_flags() { 124 for flag in "$@"; do 125 echo "- $(check_flag "$flag")" 126 done 127 } 128 129 check_distro_userns() { 130 [ -r /etc/os-release ] || return 0 131 # shellcheck source=/dev/null 132 . /etc/os-release 2>/dev/null || return 0 133 if [[ "${ID}" =~ ^(centos|rhel)$ && "${VERSION_ID}" =~ ^7 ]]; then 134 # this is a CentOS7 or RHEL7 system 135 grep -q "user_namespace.enable=1" /proc/cmdline || { 136 # no user namespace support enabled 137 wrap_bad " (RHEL7/CentOS7" "User namespaces disabled; add 'user_namespace.enable=1' to boot command line)" 138 } 139 fi 140 } 141 142 is_config() { 143 local config="$1" 144 145 # Todo: more check 146 [[ -f "$config" ]] && return 0 147 return 1 148 } 149 150 search_config() { 151 local target_dir=("${1:-${possibleConfigs[@]}}") 152 153 local tryConfig 154 for tryConfig in "${target_dir[@]}"; do 155 is_config "$tryConfig" && { 156 CONFIG="$tryConfig" 157 return 158 } 159 [[ -d "$tryConfig" ]] && { 160 for tryFile in "${possibleConfigFiles[@]}"; do 161 is_config "$tryConfig/$tryFile" && { 162 CONFIG="$tryConfig/$tryFile" 163 return 164 } 165 done 166 } 167 done 168 169 wrap_warning "error: cannot find kernel config" 170 wrap_warning " try running this script again, specifying the kernel config:" 171 wrap_warning " CONFIG=/path/to/kernel/.config $0 or $0 /path/to/kernel/.config" 172 exit 1 173 } 174 175 CONFIG="${1:-}" 176 177 is_config "$CONFIG" || { 178 if [[ ! "$CONFIG" ]]; then 179 wrap_color "info: no config specified, searching for kernel config ..." white 180 search_config 181 elif [[ -d "$CONFIG" ]]; then 182 wrap_color "info: input is a directory, searching for kernel config in this directory..." white 183 search_config "$CONFIG" 184 else 185 wrap_warning "warning: $CONFIG seems not a kernel config, searching other paths for kernel config ..." 186 search_config 187 fi 188 } 189 190 wrap_color "info: reading kernel config from $CONFIG ..." white 191 echo 192 193 echo 'Generally Necessary:' 194 195 cgroup="" 196 echo -n '- ' 197 if [ "$(stat -f -c %t /sys/fs/cgroup 2>/dev/null)" = "63677270" ]; then 198 wrap_good 'cgroup hierarchy' 'cgroupv2' 199 cgroup="v2" 200 else 201 cgroupSubsystemDir="$(awk '/[, ](cpu|cpuacct|cpuset|devices|freezer|memory)[, ]/ && $3 == "cgroup" { print $2 }' /proc/mounts | head -n1)" 202 cgroupDir="$(dirname "$cgroupSubsystemDir")" 203 if [ -d "$cgroupDir/cpu" ] || [ -d "$cgroupDir/cpuacct" ] || [ -d "$cgroupDir/cpuset" ] || [ -d "$cgroupDir/devices" ] || [ -d "$cgroupDir/freezer" ] || [ -d "$cgroupDir/memory" ]; then 204 wrap_good 'cgroup hierarchy' 'properly mounted' "[$cgroupDir]" 205 cgroup="v1" 206 else 207 if [ "$cgroupSubsystemDir" ]; then 208 wrap_bad 'cgroup hierarchy' 'single mountpoint!' "[$cgroupSubsystemDir]" 209 else 210 wrap_bad 'cgroup hierarchy' 'nonexistent??' 211 fi 212 wrap_color ' (see https://github.com/tianon/cgroupfs-mount)' yellow 213 fi 214 fi 215 216 if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = 'Y' ]; then 217 echo -n '- ' 218 if command -v apparmor_parser &>/dev/null; then 219 wrap_good 'apparmor' 'enabled and tools installed' 220 else 221 wrap_bad 'apparmor' 'enabled, but apparmor_parser missing' 222 echo -n ' ' 223 if command -v apt-get &>/dev/null; then 224 wrap_color '(use "apt-get install apparmor" to fix this)' yellow 225 elif command -v yum &>/dev/null; then 226 wrap_color '(your best bet is "yum install apparmor-parser")' yellow 227 else 228 wrap_color '(look for an "apparmor" package for your distribution)' yellow 229 fi 230 fi 231 fi 232 233 flags=( 234 NAMESPACES {NET,PID,IPC,UTS}_NS 235 CGROUPS CGROUP_CPUACCT CGROUP_DEVICE CGROUP_FREEZER CGROUP_SCHED CPUSETS MEMCG 236 KEYS 237 VETH BRIDGE BRIDGE_NETFILTER 238 IP_NF_FILTER IP_NF_TARGET_MASQUERADE 239 NETFILTER_XT_MATCH_{ADDRTYPE,COMMENT,CONNTRACK,IPVS} 240 IP_NF_NAT NF_NAT 241 242 # required for bind-mounting /dev/mqueue into containers 243 POSIX_MQUEUE 244 ) 245 check_flags "${flags[@]}" 246 247 # Linux kernel commit 3007098494be. 248 if kernel_ge 4 10 && [ $cgroup = "v2" ]; then 249 check_flags CGROUP_BPF 250 fi 251 252 # Linux kernel commit 3bf195ae6037. 253 if kernel_lt 5 1; then 254 check_flags NF_NAT_IPV4 255 fi 256 257 # Linux kernel commit 4806e975729f99c7. 258 if kernel_lt 5 2; then 259 check_flags NF_NAT_NEEDED 260 fi 261 262 echo 263 264 echo 'Optional Features:' 265 { 266 check_flags USER_NS 267 check_distro_userns 268 269 check_flags SECCOMP 270 check_flags SECCOMP_FILTER 271 check_flags CGROUP_PIDS 272 273 # Linux kernel commit e55b9f96860f. 274 if kernel_lt 6 1; then 275 check_flags MEMCG_SWAP 276 fi 277 # Linux kernel commit 2d1c498072de. 278 if kernel_lt 5 8; then 279 check_flags MEMCG_SWAP_ENABLED 280 if is_set MEMCG_SWAP && ! is_set MEMCG_SWAP_ENABLED; then 281 wrap_color ' (note that cgroup swap accounting is not enabled in your kernel config, you can enable it by setting boot option "swapaccount=1")' bold black 282 fi 283 fi 284 } 285 286 # Linux kernel commit d886f4e483ce. 287 if kernel_lt 4 5; then 288 check_flags MEMCG_KMEM 289 fi 290 291 # Linux kernel commit 5b1efc027c0b. 292 if kernel_lt 3 19; then 293 check_flags RESOURCE_COUNTERS 294 fi 295 296 # Linux kernel commit 86f8515f9721. 297 if kernel_lt 3 14; then 298 netprio=NETPRIO_CGROUP 299 else 300 netprio=CGROUP_NET_PRIO 301 fi 302 303 # Linux kernel commit f382fb0bcef4. 304 if kernel_lt 5 0; then 305 check_flags IOSCHED_CFQ CFQ_GROUP_IOSCHED 306 fi 307 308 # Linux kernel commit 7caa47151ab2. 309 if kernel_ge 5 4; then 310 check_flags BLK_CGROUP_IOCOST 311 fi 312 313 flags=( 314 BLK_CGROUP BLK_DEV_THROTTLING 315 CGROUP_PERF 316 CGROUP_HUGETLB 317 NET_CLS_CGROUP "$netprio" 318 CFS_BANDWIDTH FAIR_GROUP_SCHED RT_GROUP_SCHED 319 IP_NF_TARGET_REDIRECT 320 IP_VS 321 IP_VS_NFCT 322 IP_VS_PROTO_TCP 323 IP_VS_PROTO_UDP 324 IP_VS_RR 325 SECURITY_SELINUX 326 SECURITY_APPARMOR 327 CHECKPOINT_RESTORE 328 ) 329 check_flags "${flags[@]}"