aboutsummaryrefslogblamecommitdiffstats
path: root/main/openrc/modloop.initd
blob: fb7006c2a2b6a5c87dde413b25074a9a6fc67796 (plain) (tree)
1
2
3
4
5
6
7
8
                  



                                           
                       
                                                               
                             



                     
                                                       
                              
                                                   
                                                                     
                    


            

                                                                                

 








                                              
                                                                                     






                                                             

 

                             


                                                      













                                                                                        





                                                                 
         
                                                       
                 
 
                               
                                
                                           
                                                                  
                                                    
                                                         

                                                                                  

                          





                                                                         


                            
 
                                          
                          
                                  
                                                                                         














                                                             
 
                                                  




                                                                                      
                                                                



                                                                             
                                                                                                                                                            
                         



                                                                     





                                                                   


                                                            
          
                


        







                                                                       

 
#!/sbin/openrc-run

# script that will mount image with modules

depend() {
	after dev-mount
	before checkfs fsck hwdrivers modules hwclock dev sysfs
	keyword -vserver -lxc
}

# read kernel options
init_KOPT() {
	for opt in $(cat /proc/cmdline 2>/dev/null); do
	        case "$opt" in
			modloop=*|modloop_verify=*)
				eval "KOPT_${opt%%=*}='${opt#*=}'" ;;
		esac
	done
}

mountdirs() {
	awk '$2 !~ /^\/(sys|proc|dev|run)/ && $2 != "/" {print $2}' /proc/mounts
}

find_modloop() {
	local dir="$1"
	local kver=$(uname -r)
	local oifs="$IFS"
	IFS=$'\n'
	set -- $(blkid "$dir"/boot/* "$dir"/*)
	IFS="$oifs"
	for line; do
		img=${line%%:*}
		verify_modloop "$img" || eerror "Failed to verify signature of $img!"
		mount "$img" -o loop,ro /.modloop || continue
		if [ -d /.modloop/modules/$kver ]; then
			return 0
		fi
		umount /.modloop
	done
	return 1
}

verify_modloop() {
	local modloop=$1 key=
	if ! yesno "${KOPT_modloop_verify:=yes}"; then
		return 0
	fi
	for key in /etc/apk/keys/*.pub; do
		local sig=/var/cache/misc/${modloop##*/}.SIGN.RSA.${key##*/}
		if [ -f "$sig" ]; then
			if ! command -v openssl > /dev/null; then
				ewarn "Missing openssl. Modloop verification disabled!"
				return 0
			fi
			einfo "Verifying modloop"
			openssl dgst -sha1 -verify "$key" -signature "$sig" "$modloop" \
				>/dev/null 2>&1 || return 1
		fi
	done
}

find_backing_file() {
	local dir="$1"
	local dev=$(df -P "$dir" | tail -1 | awk '{print $1}')
	cat /sys/block/${dev#/dev/}/loop/backing_file 2>/dev/null
}

start() {
	local modloop= mount_opts= modloop_dldir="/lib"
	init_KOPT

	case "$KOPT_modloop" in
		none) return 0;;
		http://*|https://*|ftp://*)
			modloop=$modloop_dldir/${KOPT_modloop##*/}
			if [ ! -f "$modloop" ]; then
				mkdir -p "$modloop_dldir"
				wget -P "$modloop_dldir" "$KOPT_modloop" || eend 1
			fi
			;;
		*)
			for dir in $(mountdirs); do
				if [ -f "$dir"/$KOPT_modloop ]; then
					modloop="$dir/${KOPT_modloop##/}"
					alpine_mnt="$dir"
					break
				fi
			done
			;;
	esac

	ebegin "Mounting modloop $modloop"
	mkdir -p /.modloop
	if [ -n "$modloop" ]; then
		verify_modloop "$modloop" || eerror "Failed to verify signature of $img!"
		mount -o loop,ro $modloop /.modloop
		eend $? || return 1
	else
		for dir in $(mountdirs); do
			if find_modloop "$dir"; then
				alpine_mnt="$dir"
				break
			fi
		done
		if [ -d /.modloop/modules/$(uname -r) ]; then
			eend 0
		else
			eend 1 || return 1
		fi
	fi

	#use overlayfs if available and configured
	if grep -q -w "overlay$" /proc/filesystems && [ ! -z ${unionfs_size+x} ]; then
		ewarn "Use of unionfs_size is deprecated use overlay_size instead"
		overlay_size="$unionfs_size"
	fi
	if grep -q -w "overlay$" /proc/filesystems && [ -n "$overlay_size" ]; then
		ebegin "OverlayFS detected, mounting modloop rw"
		[ "$overlay_size" != 0 ] && mount_ops="-o size=$overlay_size"
		mkdir -p /.modoverlayfs /lib/modules
		mount -t tmpfs $mount_ops tmpfs /.modoverlayfs
		mkdir -p /.modoverlayfs/modules /.modoverlayfs/work
		mount -t overlay -o upperdir=/.modoverlayfs/modules,lowerdir=/lib/modules:/.modloop/modules,workdir=/.modoverlayfs/work overlay /lib/modules
		depmod -A
		eend $? || return 1
	else
		rm -rf /lib/modules && ln -sf /.modloop/modules /lib/
	fi

	# copy firmware if there are any
	if [ -d $alpine_mnt/firmware ]; then
	        ebegin "Copying firmware from $alpine_mnt/firmware"
	        cp -R -a $alpine_mnt/firmware /lib/
	        eend $?
	elif  [ -d /lib/modules/firmware ]; then
		rmdir /lib/firmware 2>/dev/null \
			&& ln -s /lib/modules/firmware /lib/
	fi
	return 0
}

stop() {
	local ret=0
	local mnt; for mnt in /lib/modules /.modoverlayfs /.modloop; do
		if mountinfo --quiet "$mnt"; then
			ebegin "Unmounting $mnt"
			umount -d "$mnt" || ret=1
		fi
	done
	eend $ret || return 1
}