summaryrefslogtreecommitdiffstats
path: root/mod-denylist.sh
blob: 6127d145fca98e11be2b63907b48be6031e60c92 (plain)
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
#! /bin/bash
# shellcheck disable=SC2164

RpmDir=$1
ModDir=$2
Dir="$1/$2"
# Note the list filename must have the format mod-[PACKAGE].list, for example,
# mod-internal.list or mod-extra.list.  The PACKAGE is used to create a
# override directory for the modules.
List=$3
Dest="$4"

blacklist()
{
	cat > "$RpmDir/etc/modprobe.d/$1-blacklist.conf" <<-__EOF__
	# This kernel module can be automatically loaded by non-root users. To
	# enhance system security, the module is blacklisted by default to ensure
	# system administrators make the module available for use as needed.
	# See https://access.redhat.com/articles/3760101 for more details.
	#
	# Remove the blacklist by adding a comment # at the start of the line.
	blacklist $1
__EOF__
}

check_blacklist()
{
	mod=$(find "$RpmDir/$ModDir" -name "$1")
	[ ! "$mod" ] && return 0
	if modinfo "$mod" | grep -q '^alias:\s\+net-'; then
		mod="${1##*/}"
		mod="${mod%.ko*}"
		echo "$mod has an alias that allows auto-loading. Blacklisting."
		blacklist "$mod"
	fi
}

find_depends()
{
	dep=$1
	depends=$(modinfo "$dep" | sed -n -e "/^depends/ s/^depends:[ \t]*//p")
	[ -z "$depends" ] && exit
	for mod in ${depends//,/ }
	do
		match=$(grep "^$mod.ko" "$ListName")
		[ -z "$match" ] && continue
		# check if the module we are looking at is in mod-* too.
		# if so we do not need to mark the dep as required.
		mod2=${dep##*/}  # same as $(basename $dep), but faster
		match2=$(grep "^$mod2" "$ListName")
		if [ -n "$match2" ]
		then
			#echo $mod2 >> notreq.list
			continue
		fi
		echo "$mod".ko >> req.list
	done
}

foreachp()
{
	P=$(nproc)
	bgcount=0
	while read -r mod; do
		$1 "$mod" &

		bgcount=$((bgcount + 1))
		if [ $bgcount -eq "$P" ]; then
			wait -n
			bgcount=$((bgcount - 1))
		fi
	done

	wait
}

# Destination was specified on the command line
test -n "$4" && echo "$0: Override Destination $Dest has been specified."

pushd "$Dir"

OverrideDir=$(basename "$List")
OverrideDir=${OverrideDir%.*}
OverrideDir=${OverrideDir#*-}
mkdir -p "$OverrideDir"

rm -rf modnames
find . -name "*.ko" -type f > modnames
# Look through all of the modules, and throw any that have a dependency in
# our list into the list as well.
rm -rf dep.list dep2.list
rm -rf req.list req2.list
touch dep.list req.list
cp "$List" .

# This variable needs to be exported because it is used in sub-script
# executed by xargs
ListName=$(basename "$List")
export ListName

foreachp find_depends < modnames

sort -u req.list > req2.list
sort -u "$ListName" > modules2.list
join -v 1 modules2.list req2.list > modules3.list

while IFS= read -r mod
do
    # get the path for the module
    modpath=$(grep /"$mod" modnames)
    [ -z "$modpath" ] && continue
    echo "$modpath" >> dep.list
done < modules3.list

sort -u dep.list > dep2.list

if [ -n "$Dest" ]; then
    # now move the modules into the $Dest directory
    while IFS= read -r mod
    do
	newpath=$(dirname "$mod" | sed -e "s/kernel\\//$Dest\//")
	mkdir -p "$newpath"
	mv "$mod" "$newpath"
	echo "$mod" | sed -e "s/kernel\\//$Dest\//" | sed -e "s|^.|${ModDir}|g" >> "$RpmDir"/"$ListName"
    done < dep2.list
fi

popd

# If we're signing modules, we can't leave the .mod files for the .ko files
# we've moved in .tmp_versions/.  Remove them so the Kbuild 'modules_sign'
# target doesn't try to sign a non-existent file.  This is kinda ugly, but
# so are the modules-* packages.

while IFS= read -r mod
do
  modfile=$(basename "$mod" | sed -e 's/.ko/.mod/')
  rm .tmp_versions/"$modfile"
done < "$Dir"/dep2.list

if [ -z "$Dest" ]; then
	sed -e "s|^.|${ModDir}|g" "$Dir"/dep2.list > "$RpmDir/$ListName"
	echo "./$RpmDir/$ListName created."
	[ -d "$RpmDir/etc/modprobe.d/" ] || mkdir -p "$RpmDir/etc/modprobe.d/"
	foreachp check_blacklist < "$List"
fi

# Many BIOS-es export a PNP-id which causes the floppy driver to autoload
# even though most modern systems don't have a 3.5" floppy driver anymore
# this replaces the old die_floppy_die.patch which removed the PNP-id from
# the module

floppylist=("$RpmDir"/"$ModDir"/kernel/drivers/block/floppy.ko*)
if [[ -n ${floppylist[0]} && -f ${floppylist[0]} ]]; then
     blacklist "floppy"
fi

# avoid an empty kernel-extra package
echo "$ModDir/$OverrideDir" >> "$RpmDir/$ListName"

pushd "$Dir"
rm modnames dep.list dep2.list req.list req2.list
rm "$ListName" modules2.list modules3.list
popd