blob: e7d79438b8f1d58bb73f9b54e00b953685fed45e (
plain)
1 #!/usr/bin/env bash
2 #
3 # Mkinitramfs creates a basic init ram fs with encryption support.
4 # Copyright (C) 2016 Aaron Ball <nullspoon@oper.io>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #
19
20
21 # Hash of fully-qualified binaries
22 declare -a fqbins
23
24
25 #
26 # Searches PATH for all binaries listed as function arguments. Each found
27 # binary is then put into the global "bins" array.
28 #
29 # This function also serves to ensure all specified binaries are present and
30 # in PATH. It will exit code 1 with an error message if any binaries are not
31 # found.
32 #
33 # Note: To use this function, insert "declare -a fqbins" at top of script).
34 #
35 # @param bins All function arguments are the names of binaries to locate.
36 #
37 function resolve_bins {
38 local args=${@}
39
40 for i in ${args[@]}; do
41 local path=$(which ${i} 2>/dev/null)
42
43 if [[ $? -gt 0 ]]; then
44 echo "Could not find binary ${i}. Is it installed?"
45 exit 1
46 fi
47
48 echo "Located ${i} at ${path}"
49 fqbins+=("${path}")
50 done
51 }
52
53
54 #
55 # Gets first path locatable in a string
56 #
57 function get_first_path {
58 local str=${1}
59
60 local out=''
61 local cursor=''
62
63 for ((i=0; i<${#str}; i++)); do
64 if [[ ${str:$i:1} == '/' ]]; then
65 cursor=${i}
66 break
67 fi
68 done
69
70 # Exit if no path found
71 [[ ${cursor} == '' ]] && return
72
73 while [[ ${str:$cursor:1} != ' ' ]] && [[ ${cursor} -lt ${#str} ]]; do
74 out="${out}${str:$cursor:1}"
75 cursor=$((${cursor} + 1))
76 done
77
78 echo "${out}"
79 }
80
81
82 function get_deps {
83 local bin=${1}
84
85 for dep in $(ldd ${bin}); do
86 get_first_path "${dep}"
87 done
88 }
89
90
91 #
92 # Creates cpio file for specified initrd cache directory.
93 # Outputs to /boot/initrd-${version}.
94 #
95 # @param cache Path to the uncompressed source directory to be archived
96 # @param version Version of initrd archive
97 #
98 function mkcpio {
99 [[ -z ${1} ]] && echo "Initramfs cache path required." && exit 1
100 [[ -z ${2} ]] && echo "Kernel version required." && exit 1
101
102 local cache=${1}
103 local version=${2}
104
105 cd ${cache}
106 fspath="/boot/initrd-${version}"
107
108 # Notify user of initrd overwriting
109 [[ -f ${fspath} ]] && echo -e "\n\n${fspath} exists. Overwriting.\n"
110
111 # Create the initrd
112 find . -print0 | cpio --null -ov --format=newc | xz -C crc32 -v -9 -c > ${fspath}
113 }
114
115
116 #
117 # Sets up cache dir for later writing to an archive (via cpio).
118 # Performs simple operations like creating a basic directory structure,
119 #
120 # @param cache Path to the cache directory. Will be created if not exists
121 #
122 function cache_dir_setup {
123 [[ -z ${1} ]] && echo "Please specify a cache dir." && exit 1
124 local cache=${1}
125
126 # Clean the cache so we start fresh
127 rm -rf ${cache} && mkdir ${cache}
128
129 local dirs=(
130 bin
131 dev
132 dev/disk
133 dev/disk/by-uuid
134 etc
135 lib
136 lib32
137 lib64
138 mnt/root
139 proc
140 root
141 run
142 sbin
143 sys
144 usr/lib
145 usr/lib64
146 usr/lib32
147 usr/bin
148 usr/sbin
149 )
150
151 # Create the temporary directory structure
152 for i in ${dirs[*]}; do
153 mkdir -p ${cache}/${i}
154 done
155 }
156
157
158 #
159 # Checks installed kernel modules for the specified version to see if the
160 # corresponding kernel has encryption support statically compiled in.
161 #
162 # @param version Version of kernel modules to check
163 #
164 function check_crypto_support {
165 [[ -z ${1} ]] && echo "Kernel version required." && exit 1
166 local version=${1}
167
168 builtinpath=/lib/modules/${version}/modules.builtin
169
170 # Check for encryption support
171 if [[ ! $(grep dm-crypt ${builtinpath}) ]]; then
172 echo -e "\n\nWarning: Static encryption support not found."
173 echo " Module dm-crypt not found in modules.builtin."
174 echo "Press enter to continue, or Ctrl+c to exit and resolve."
175 read
176 fi
177 }
178
179
180 #
181 # Checks to see if kernel modules for the specified version have been
182 # installed.
183 #
184 # @param version Version to check for installation status
185 #
186 function check_kernel_version {
187 [[ -z ${1} ]] && echo "Kernel version required." && exit 1
188 local version=${1}
189
190 modulespath=/lib/modules/${version}
191 if [[ ! -d ${modulespath} ]]; then
192 echo "Error: Could not find ${modulespath}."
193 echo "Has kernel version ${version} been comiled?"
194 exit 1
195 fi
196 }
197
198
199 function main {
200 [[ -z ${1} ]] && echo "Please specify a kernel version" && exit 1
201
202 local version=${1}
203
204 check_kernel_version ${version}
205
206 local cache='/tmp/initrd'
207 local res_path=/usr/share/mkinitramfs/
208
209 # List of binaries to exist in the new initramfs
210 resolve_bins \
211 bash cat echo ls cryptsetup chmod chown mount sleep umount clear cut \
212 grep less tr which blkid shutdown switch_root
213
214
215 # Set up the archive source dir.
216 cache_dir_setup ${cache}
217
218 # Ensure static crypto support exists in kernel
219 check_crypto_support ${version}
220
221 # Copy binary and dependencies to cache dir
222 for bin in ${fqbins[@]}; do
223 bindirname=$(dirname ${bin})
224 # Copy the binary of interest
225 cp -u ${bin} "${cache}/${bindirname}/"
226
227 deps=$(get_deps ${bin})
228 # Copy each of the binary's deps
229 for dep in ${deps[@]}; do
230 local depdirname=$(dirname ${dep})
231 cp -u ${dep} "${cache}/${depdirname}/"
232 if [[ $? -gt 0 ]]; then
233 echo "Error: Problem copying ${dep} into ${cache}."
234 exit 1
235 fi
236 done
237 done
238
239 # Copy in init script and add execute
240 cp ${res_path}/init ${cache}/init && chmod +x ${cache}/init
241 # Copy in message file
242 cp ${res_path}/msg ${cache}/etc/msg
243
244 # Create archive image
245 mkcpio ${cache} ${version}
246 }
247
248
249 main ${@}
|