File: check-config.sh

package info (click to toggle)
runc 1.0.0~rc93%2Bds1-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 3,172 kB
  • sloc: sh: 1,679; ansic: 1,039; makefile: 139
file content (274 lines) | stat: -rwxr-xr-x 6,832 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#!/usr/bin/env bash
set -e

# bits of this were adapted from check_config.sh in docker
# see also https://github.com/docker/docker/blob/master/contrib/check-config.sh

possibleConfigs=(
	'/proc/config.gz'
	"/boot/config-$(uname -r)"
	"/usr/src/linux-$(uname -r)/.config"
	'/usr/src/linux/.config'
)
possibleConfigFiles=(
	'config.gz'
	"config-$(uname -r)"
	'.config'
)

if ! command -v zgrep &>/dev/null; then
	zgrep() {
		zcat "$2" | grep "$1"
	}
fi

kernelVersion="$(uname -r)"
kernelMajor="${kernelVersion%%.*}"
kernelMinor="${kernelVersion#$kernelMajor.}"
kernelMinor="${kernelMinor%%.*}"

is_set() {
	zgrep "CONFIG_$1=[y|m]" "$CONFIG" >/dev/null
}
is_set_in_kernel() {
	zgrep "CONFIG_$1=y" "$CONFIG" >/dev/null
}
is_set_as_module() {
	zgrep "CONFIG_$1=m" "$CONFIG" >/dev/null
}

color() {
	local codes=()
	if [ "$1" = 'bold' ]; then
		codes=("${codes[@]}" '1')
		shift
	fi
	if [ "$#" -gt 0 ]; then
		local code
		case "$1" in
		# see https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
		black) code=30 ;;
		red) code=31 ;;
		green) code=32 ;;
		yellow) code=33 ;;
		blue) code=34 ;;
		magenta) code=35 ;;
		cyan) code=36 ;;
		white) code=37 ;;
		esac
		if [ "$code" ]; then
			codes=("${codes[@]}" "$code")
		fi
	fi
	local IFS=';'
	echo -en '\033['"${codes[*]}"'m'
}
wrap_color() {
	text="$1"
	shift
	color "$@"
	echo -n "$text"
	color reset
	echo
}

wrap_good() {
	echo "$(wrap_color "$1" white): $(wrap_color "$2" green)"
}
wrap_bad() {
	echo "$(wrap_color "$1" bold): $(wrap_color "$2" bold red)"
}
wrap_warning() {
	wrap_color >&2 "$*" red
}

check_flag() {
	if is_set_in_kernel "$1"; then
		wrap_good "CONFIG_$1" 'enabled'
	elif is_set_as_module "$1"; then
		wrap_good "CONFIG_$1" 'enabled (as module)'
	else
		wrap_bad "CONFIG_$1" 'missing'
	fi
}

check_flags() {
	for flag in "$@"; do
		echo "- $(check_flag "$flag")"
	done
}

check_distro_userns() {
	source /etc/os-release 2>/dev/null || /bin/true
	if [[ "${ID}" =~ ^(centos|rhel)$ && "${VERSION_ID}" =~ ^7 ]]; then
		# this is a CentOS7 or RHEL7 system
		grep -q "user_namespace.enable=1" /proc/cmdline || {
			# no user namespace support enabled
			wrap_bad "  (RHEL7/CentOS7" "User namespaces disabled; add 'user_namespace.enable=1' to boot command line)"
		}
	fi
}

is_config() {
	local config="$1"

	# Todo: more check
	[[ -f "$config" ]] && return 0
	return 1
}

search_config() {
	local target_dir="$1"
	[[ "$target_dir" ]] || target_dir=("${possibleConfigs[@]}")

	local tryConfig
	for tryConfig in "${target_dir[@]}"; do
		is_config "$tryConfig" && {
			CONFIG="$tryConfig"
			return
		}
		[[ -d "$tryConfig" ]] && {
			for tryFile in "${possibleConfigFiles[@]}"; do
				is_config "$tryConfig/$tryFile" && {
					CONFIG="$tryConfig/$tryFile"
					return
				}
			done
		}
	done

	wrap_warning "error: cannot find kernel config"
	wrap_warning "  try running this script again, specifying the kernel config:"
	wrap_warning "    CONFIG=/path/to/kernel/.config $0 or $0 /path/to/kernel/.config"
	exit 1
}

CONFIG="$1"

is_config "$CONFIG" || {
	if [[ ! "$CONFIG" ]]; then
		wrap_color "info: no config specified, searching for kernel config ..." white
		search_config
	elif [[ -d "$CONFIG" ]]; then
		wrap_color "info: input is a directory, searching for kernel config in this directory..." white
		search_config "$CONFIG"
	else
		wrap_warning "warning: $CONFIG seems not a kernel config, searching other paths for kernel config ..."
		search_config
	fi
}

wrap_color "info: reading kernel config from $CONFIG ..." white
echo

echo 'Generally Necessary:'

echo -n '- '
if [ "$(stat -f -c %t /sys/fs/cgroup 2>/dev/null)" = "63677270" ]; then
	echo "$(wrap_good 'cgroup hierarchy' 'cgroupv2')"
else
	cgroupSubsystemDir="$(awk '/[, ](cpu|cpuacct|cpuset|devices|freezer|memory)[, ]/ && $3 == "cgroup" { print $2 }' /proc/mounts | head -n1)"
	cgroupDir="$(dirname "$cgroupSubsystemDir")"
	if [ -d "$cgroupDir/cpu" -o -d "$cgroupDir/cpuacct" -o -d "$cgroupDir/cpuset" -o -d "$cgroupDir/devices" -o -d "$cgroupDir/freezer" -o -d "$cgroupDir/memory" ]; then
		echo "$(wrap_good 'cgroup hierarchy' 'properly mounted') [$cgroupDir]"
	else
		if [ "$cgroupSubsystemDir" ]; then
			echo "$(wrap_bad 'cgroup hierarchy' 'single mountpoint!') [$cgroupSubsystemDir]"
		else
			echo "$(wrap_bad 'cgroup hierarchy' 'nonexistent??')"
		fi
		echo "    $(wrap_color '(see https://github.com/tianon/cgroupfs-mount)' yellow)"
	fi
fi

if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = 'Y' ]; then
	echo -n '- '
	if command -v apparmor_parser &>/dev/null; then
		echo "$(wrap_good 'apparmor' 'enabled and tools installed')"
	else
		echo "$(wrap_bad 'apparmor' 'enabled, but apparmor_parser missing')"
		echo -n '    '
		if command -v apt-get &>/dev/null; then
			echo "$(wrap_color '(use "apt-get install apparmor" to fix this)')"
		elif command -v yum &>/dev/null; then
			echo "$(wrap_color '(your best bet is "yum install apparmor-parser")')"
		else
			echo "$(wrap_color '(look for an "apparmor" package for your distribution)')"
		fi
	fi
fi

flags=(
	NAMESPACES {NET,PID,IPC,UTS}_NS
	CGROUPS CGROUP_CPUACCT CGROUP_DEVICE CGROUP_FREEZER CGROUP_SCHED CPUSETS MEMCG
	KEYS
	VETH BRIDGE BRIDGE_NETFILTER
	IP_NF_FILTER IP_NF_TARGET_MASQUERADE
	NETFILTER_XT_MATCH_{ADDRTYPE,CONNTRACK,IPVS}
	IP_NF_NAT NF_NAT

	# required for bind-mounting /dev/mqueue into containers
	POSIX_MQUEUE
)
check_flags "${flags[@]}"

if [ "$kernelMajor" -lt 5 ] || [ "$kernelMajor" -eq 5 -a "$kernelMinor" -le 1 ]; then
	check_flags NF_NAT_IPV4
fi

if [ "$kernelMajor" -lt 5 ] || [ "$kernelMajor" -eq 5 -a "$kernelMinor" -le 2 ]; then
	check_flags NF_NAT_NEEDED
fi

echo

echo 'Optional Features:'
{
	check_flags USER_NS
	check_distro_userns

	check_flags SECCOMP
	check_flags CGROUP_PIDS

	check_flags MEMCG_SWAP

	if [ "$kernelMajor" -lt 5 ] || [ "$kernelMajor" -eq 5 -a "$kernelMinor" -le 8 ]; then
		check_flags MEMCG_SWAP_ENABLED
		if is_set MEMCG_SWAP && ! is_set MEMCG_SWAP_ENABLED; then
			echo "    $(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)"
		fi
	fi
}

if [ "$kernelMajor" -lt 4 ] || [ "$kernelMajor" -eq 4 -a "$kernelMinor" -le 5 ]; then
	check_flags MEMCG_KMEM
fi

if [ "$kernelMajor" -lt 3 ] || [ "$kernelMajor" -eq 3 -a "$kernelMinor" -le 18 ]; then
	check_flags RESOURCE_COUNTERS
fi

if [ "$kernelMajor" -lt 3 ] || [ "$kernelMajor" -eq 3 -a "$kernelMinor" -le 13 ]; then
	netprio=NETPRIO_CGROUP
else
	netprio=CGROUP_NET_PRIO
fi

if [ "$kernelMajor" -lt 5 ]; then
	check_flags IOSCHED_CFQ CFQ_GROUP_IOSCHED
fi

flags=(
	BLK_CGROUP BLK_DEV_THROTTLING
	CGROUP_PERF
	CGROUP_HUGETLB
	NET_CLS_CGROUP $netprio
	CFS_BANDWIDTH FAIR_GROUP_SCHED RT_GROUP_SCHED
	IP_NF_TARGET_REDIRECT
	IP_VS
	IP_VS_NFCT
	IP_VS_PROTO_TCP
	IP_VS_PROTO_UDP
	IP_VS_RR
)
check_flags "${flags[@]}"