diff mbox series

[v4] fixfiles: Unmount temporary bind mounts on SIGINT

Message ID 20221007134600.137812-1-plautrba@redhat.com (mailing list archive)
State Superseded
Headers show
Series [v4] fixfiles: Unmount temporary bind mounts on SIGINT | expand

Commit Message

Petr Lautrbach Oct. 7, 2022, 1:46 p.m. UTC
`fixfiles -M relabel` temporary bind mounts filestems before relabeling
but it leaves a directory mounted in /tmp/tmp.XXXX when a user hits
CTRL-C. It means that if the user run `fixfiles -M relabel` again and
answered Y to clean out /tmp directory, it would remove all data from
mounted fs.

This patch changes the location where `fixfiles` mounts fs to /run, uses
private mount namespace via unshare and adds a handler for exit signals
which tries to umount fs mounted by `fixfiles`.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2125355

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
v2:

- set trap on EXIT instead of SIGINT

v3:

- use /run instead of /tmp for mountpoints

v4:

- use mount namespace as suggested by Christian Göttsche <cgzones@googlemail.com> (September 16) (inbox)


 policycoreutils/scripts/fixfiles | 36 +++++++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 8 deletions(-)

Comments

Petr Lautrbach Nov. 4, 2022, 10:41 a.m. UTC | #1
Petr Lautrbach <plautrba@redhat.com> writes:

> `fixfiles -M relabel` temporary bind mounts filestems before relabeling
> but it leaves a directory mounted in /tmp/tmp.XXXX when a user hits
> CTRL-C. It means that if the user run `fixfiles -M relabel` again and
> answered Y to clean out /tmp directory, it would remove all data from
> mounted fs.
>
> This patch changes the location where `fixfiles` mounts fs to /run, uses
> private mount namespace via unshare and adds a handler for exit signals
> which tries to umount fs mounted by `fixfiles`.
>
> Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2125355
>
> Signed-off-by: Petr Lautrbach <plautrba@redhat.com>


Is there anyone who objects?

Petr


> ---
> v2:
>
> - set trap on EXIT instead of SIGINT
>
> v3:
>
> - use /run instead of /tmp for mountpoints
>
> v4:
>
> - use mount namespace as suggested by Christian Göttsche <cgzones@googlemail.com> (September 16) (inbox)
>
>
>  policycoreutils/scripts/fixfiles | 36 +++++++++++++++++++++++++-------
>  1 file changed, 28 insertions(+), 8 deletions(-)
>
> diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
> index c72ca0eb9d61..af64a5a567a6 100755
> --- a/policycoreutils/scripts/fixfiles
> +++ b/policycoreutils/scripts/fixfiles
> @@ -207,6 +207,25 @@ rpm -q --qf '[%{FILESTATES} %{FILENAMES}\n]' "$1" | grep '^0 ' | cut -f2- -d ' '
>  [ ${PIPESTATUS[0]} != 0 ] && echo "$1 not found" >/dev/stderr
>  }
>  
> +# unmount tmp bind mount before exit
> +umount_TMP_MOUNT() {
> +	if [ -n "$TMP_MOUNT" ]; then
> +	     umount "${TMP_MOUNT}${m}" || exit 130
> +	     rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
> +	fi
> +	exit 130
> +}
> +
> +fix_labels_on_mountpoint() {
> +	test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
> +	mkdir -p "${TMP_MOUNT}${m}" || exit 1
> +	mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
> +	${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
> +	umount "${TMP_MOUNT}${m}" || exit 1
> +	rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
> +}
> +export -f fix_labels_on_mountpoint
> +
>  #
>  # restore
>  # if called with -n will only check file context
> @@ -252,14 +271,15 @@ case "$RESTORE_MODE" in
>  	        # we bind mount so we can fix the labels of files that have already been
>  	        # mounted over
>  	        for m in `echo $FILESYSTEMSRW`; do
> -	            TMP_MOUNT="$(mktemp -d)"
> -	            test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
> -
> -	            mkdir -p "${TMP_MOUNT}${m}" || exit 1
> -	            mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
> -	            ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
> -	            umount "${TMP_MOUNT}${m}" || exit 1
> -	            rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
> +	          	TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"
> +	            export SETFILES VERBOSE EXCLUDEDIRS FORCEFLAG THREADS FC TMP_MOUNT m
> +	            if type unshare &> /dev/null; then
> +	                unshare -m bash -x -c "fix_labels_on_mountpoint" $* || exit $?
> +	            else
> +	                trap umount_TMP_MOUNT EXIT
> +	                fix_labels_on_mountpoint $*
> +	                trap EXIT
> +	            fi
>  	        done;
>  	    fi
>  	else
> -- 
> 2.37.3
Christian Göttsche Nov. 4, 2022, 11:20 a.m. UTC | #2
On Fri, 4 Nov 2022 at 11:42, Petr Lautrbach <plautrba@redhat.com> wrote:
>
> Petr Lautrbach <plautrba@redhat.com> writes:
>
> > `fixfiles -M relabel` temporary bind mounts filestems before relabeling
> > but it leaves a directory mounted in /tmp/tmp.XXXX when a user hits
> > CTRL-C. It means that if the user run `fixfiles -M relabel` again and
> > answered Y to clean out /tmp directory, it would remove all data from
> > mounted fs.
> >
> > This patch changes the location where `fixfiles` mounts fs to /run, uses
> > private mount namespace via unshare and adds a handler for exit signals
> > which tries to umount fs mounted by `fixfiles`.
> >
> > Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2125355
> >
> > Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
>
>
> Is there anyone who objects?
>
> Petr
>
>
> > ---
> > v2:
> >
> > - set trap on EXIT instead of SIGINT
> >
> > v3:
> >
> > - use /run instead of /tmp for mountpoints
> >
> > v4:
> >
> > - use mount namespace as suggested by Christian Göttsche <cgzones@googlemail.com> (September 16) (inbox)
> >
> >
> >  policycoreutils/scripts/fixfiles | 36 +++++++++++++++++++++++++-------
> >  1 file changed, 28 insertions(+), 8 deletions(-)
> >
> > diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
> > index c72ca0eb9d61..af64a5a567a6 100755
> > --- a/policycoreutils/scripts/fixfiles
> > +++ b/policycoreutils/scripts/fixfiles
> > @@ -207,6 +207,25 @@ rpm -q --qf '[%{FILESTATES} %{FILENAMES}\n]' "$1" | grep '^0 ' | cut -f2- -d ' '
> >  [ ${PIPESTATUS[0]} != 0 ] && echo "$1 not found" >/dev/stderr
> >  }
> >
> > +# unmount tmp bind mount before exit
> > +umount_TMP_MOUNT() {
> > +     if [ -n "$TMP_MOUNT" ]; then
> > +          umount "${TMP_MOUNT}${m}" || exit 130
> > +          rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
> > +     fi
> > +     exit 130
> > +}
> > +
> > +fix_labels_on_mountpoint() {
> > +     test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
> > +     mkdir -p "${TMP_MOUNT}${m}" || exit 1
> > +     mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
> > +     ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
> > +     umount "${TMP_MOUNT}${m}" || exit 1
> > +     rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
> > +}
> > +export -f fix_labels_on_mountpoint
> > +
> >  #
> >  # restore
> >  # if called with -n will only check file context
> > @@ -252,14 +271,15 @@ case "$RESTORE_MODE" in
> >               # we bind mount so we can fix the labels of files that have already been
> >               # mounted over
> >               for m in `echo $FILESYSTEMSRW`; do
> > -                 TMP_MOUNT="$(mktemp -d)"
> > -                 test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
> > -
> > -                 mkdir -p "${TMP_MOUNT}${m}" || exit 1
> > -                 mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
> > -                 ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
> > -                 umount "${TMP_MOUNT}${m}" || exit 1
> > -                 rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
> > +                     TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"

Whitespace issue:

git apply ~/Downloads/v4-fixfiles-Unmount-temporary-bind-mounts-on-SIGINT.patch
/home/christian/Downloads/v4-fixfiles-Unmount-temporary-bind-mounts-on-SIGINT.patch:137:
space before tab in indent.
                        TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"
warning: 1 line adds whitespace errors.

> > +                 export SETFILES VERBOSE EXCLUDEDIRS FORCEFLAG THREADS FC TMP_MOUNT m
> > +                 if type unshare &> /dev/null; then
> > +                     unshare -m bash -x -c "fix_labels_on_mountpoint" $* || exit $?

Two issues:

I.
The `-x` flag make the output unreadable (especially for check/verify).

II.
The option (e.g. `-n` for check/verify) is not passed, should be `-c
"fix_labels_on_mountpoint $*"`.

> > +                 else
> > +                     trap umount_TMP_MOUNT EXIT
> > +                     fix_labels_on_mountpoint $*
> > +                     trap EXIT
> > +                 fi
> >               done;
> >           fi
> >       else
> > --
> > 2.37.3
>
Petr Lautrbach Nov. 4, 2022, 11:41 a.m. UTC | #3
Christian Göttsche <cgzones@googlemail.com> writes:

> On Fri, 4 Nov 2022 at 11:42, Petr Lautrbach <plautrba@redhat.com> wrote:
>>
>> Petr Lautrbach <plautrba@redhat.com> writes:
>>
>> > `fixfiles -M relabel` temporary bind mounts filestems before relabeling
>> > but it leaves a directory mounted in /tmp/tmp.XXXX when a user hits
>> > CTRL-C. It means that if the user run `fixfiles -M relabel` again and
>> > answered Y to clean out /tmp directory, it would remove all data from
>> > mounted fs.
>> >
>> > This patch changes the location where `fixfiles` mounts fs to /run, uses
>> > private mount namespace via unshare and adds a handler for exit signals
>> > which tries to umount fs mounted by `fixfiles`.
>> >
>> > Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2125355
>> >
>> > Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
>>
>>
>> Is there anyone who objects?
>>
>> Petr
>>
>>
>> > ---
>> > v2:
>> >
>> > - set trap on EXIT instead of SIGINT
>> >
>> > v3:
>> >
>> > - use /run instead of /tmp for mountpoints
>> >
>> > v4:
>> >
>> > - use mount namespace as suggested by Christian Göttsche <cgzones@googlemail.com> (September 16) (inbox)
>> >
>> >
>> >  policycoreutils/scripts/fixfiles | 36 +++++++++++++++++++++++++-------
>> >  1 file changed, 28 insertions(+), 8 deletions(-)
>> >
>> > diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
>> > index c72ca0eb9d61..af64a5a567a6 100755
>> > --- a/policycoreutils/scripts/fixfiles
>> > +++ b/policycoreutils/scripts/fixfiles
>> > @@ -207,6 +207,25 @@ rpm -q --qf '[%{FILESTATES} %{FILENAMES}\n]' "$1" | grep '^0 ' | cut -f2- -d ' '
>> >  [ ${PIPESTATUS[0]} != 0 ] && echo "$1 not found" >/dev/stderr
>> >  }
>> >
>> > +# unmount tmp bind mount before exit
>> > +umount_TMP_MOUNT() {
>> > +     if [ -n "$TMP_MOUNT" ]; then
>> > +          umount "${TMP_MOUNT}${m}" || exit 130
>> > +          rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
>> > +     fi
>> > +     exit 130
>> > +}
>> > +
>> > +fix_labels_on_mountpoint() {
>> > +     test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
>> > +     mkdir -p "${TMP_MOUNT}${m}" || exit 1
>> > +     mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
>> > +     ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
>> > +     umount "${TMP_MOUNT}${m}" || exit 1
>> > +     rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
>> > +}
>> > +export -f fix_labels_on_mountpoint
>> > +
>> >  #
>> >  # restore
>> >  # if called with -n will only check file context
>> > @@ -252,14 +271,15 @@ case "$RESTORE_MODE" in
>> >               # we bind mount so we can fix the labels of files that have already been
>> >               # mounted over
>> >               for m in `echo $FILESYSTEMSRW`; do
>> > -                 TMP_MOUNT="$(mktemp -d)"
>> > -                 test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
>> > -
>> > -                 mkdir -p "${TMP_MOUNT}${m}" || exit 1
>> > -                 mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
>> > -                 ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
>> > -                 umount "${TMP_MOUNT}${m}" || exit 1
>> > -                 rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
>> > +                     TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"
>
> Whitespace issue:
>
> git apply ~/Downloads/v4-fixfiles-Unmount-temporary-bind-mounts-on-SIGINT.patch
> /home/christian/Downloads/v4-fixfiles-Unmount-temporary-bind-mounts-on-SIGINT.patch:137:
> space before tab in indent.
>                         TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"
> warning: 1 line adds whitespace errors.
>
>> > +                 export SETFILES VERBOSE EXCLUDEDIRS FORCEFLAG THREADS FC TMP_MOUNT m
>> > +                 if type unshare &> /dev/null; then
>> > +                     unshare -m bash -x -c "fix_labels_on_mountpoint" $* || exit $?
>
> Two issues:
>
> I.
> The `-x` flag make the output unreadable (especially for check/verify).


This is leftover from my debugging. It is not supposed to be there.


> II.
> The option (e.g. `-n` for check/verify) is not passed, should be `-c
> "fix_labels_on_mountpoint $*"`.

I'll fix it.


Thanks!


>> > +                 else
>> > +                     trap umount_TMP_MOUNT EXIT
>> > +                     fix_labels_on_mountpoint $*
>> > +                     trap EXIT
>> > +                 fi
>> >               done;
>> >           fi
>> >       else
>> > --
>> > 2.37.3
>>
Dominick Grift Nov. 5, 2022, 9:24 a.m. UTC | #4
On 2022-11-04 12:41, Petr Lautrbach wrote:
> Christian Göttsche <cgzones@googlemail.com> writes:
> 
>> On Fri, 4 Nov 2022 at 11:42, Petr Lautrbach <plautrba@redhat.com> 
>> wrote:
>>> 
>>> Petr Lautrbach <plautrba@redhat.com> writes:
>>> 
>>> > `fixfiles -M relabel` temporary bind mounts filestems before relabeling
>>> > but it leaves a directory mounted in /tmp/tmp.XXXX when a user hits
>>> > CTRL-C. It means that if the user run `fixfiles -M relabel` again and
>>> > answered Y to clean out /tmp directory, it would remove all data from
>>> > mounted fs.
>>> >
>>> > This patch changes the location where `fixfiles` mounts fs to /run, uses
>>> > private mount namespace via unshare and adds a handler for exit signals
>>> > which tries to umount fs mounted by `fixfiles`.
>>> >
>>> > Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2125355
>>> >
>>> > Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
>>> 
>>> 
>>> Is there anyone who objects?

Unrelated but thought i'd mention it here:

Since at least Fedora uses btrfs by default on Workstation it might be 
worth it to look into adding support for btrfs (subvolumes) to fixfiles.

>>> 
>>> Petr
>>> 
>>> 
>>> > ---
>>> > v2:
>>> >
>>> > - set trap on EXIT instead of SIGINT
>>> >
>>> > v3:
>>> >
>>> > - use /run instead of /tmp for mountpoints
>>> >
>>> > v4:
>>> >
>>> > - use mount namespace as suggested by Christian Göttsche <cgzones@googlemail.com> (September 16) (inbox)
>>> >
>>> >
>>> >  policycoreutils/scripts/fixfiles | 36 +++++++++++++++++++++++++-------
>>> >  1 file changed, 28 insertions(+), 8 deletions(-)
>>> >
>>> > diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
>>> > index c72ca0eb9d61..af64a5a567a6 100755
>>> > --- a/policycoreutils/scripts/fixfiles
>>> > +++ b/policycoreutils/scripts/fixfiles
>>> > @@ -207,6 +207,25 @@ rpm -q --qf '[%{FILESTATES} %{FILENAMES}\n]' "$1" | grep '^0 ' | cut -f2- -d ' '
>>> >  [ ${PIPESTATUS[0]} != 0 ] && echo "$1 not found" >/dev/stderr
>>> >  }
>>> >
>>> > +# unmount tmp bind mount before exit
>>> > +umount_TMP_MOUNT() {
>>> > +     if [ -n "$TMP_MOUNT" ]; then
>>> > +          umount "${TMP_MOUNT}${m}" || exit 130
>>> > +          rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
>>> > +     fi
>>> > +     exit 130
>>> > +}
>>> > +
>>> > +fix_labels_on_mountpoint() {
>>> > +     test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
>>> > +     mkdir -p "${TMP_MOUNT}${m}" || exit 1
>>> > +     mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
>>> > +     ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
>>> > +     umount "${TMP_MOUNT}${m}" || exit 1
>>> > +     rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
>>> > +}
>>> > +export -f fix_labels_on_mountpoint
>>> > +
>>> >  #
>>> >  # restore
>>> >  # if called with -n will only check file context
>>> > @@ -252,14 +271,15 @@ case "$RESTORE_MODE" in
>>> >               # we bind mount so we can fix the labels of files that have already been
>>> >               # mounted over
>>> >               for m in `echo $FILESYSTEMSRW`; do
>>> > -                 TMP_MOUNT="$(mktemp -d)"
>>> > -                 test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
>>> > -
>>> > -                 mkdir -p "${TMP_MOUNT}${m}" || exit 1
>>> > -                 mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
>>> > -                 ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
>>> > -                 umount "${TMP_MOUNT}${m}" || exit 1
>>> > -                 rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
>>> > +                     TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"
>> 
>> Whitespace issue:
>> 
>> git apply 
>> ~/Downloads/v4-fixfiles-Unmount-temporary-bind-mounts-on-SIGINT.patch
>> /home/christian/Downloads/v4-fixfiles-Unmount-temporary-bind-mounts-on-SIGINT.patch:137:
>> space before tab in indent.
>>                         TMP_MOUNT="$(mktemp -p /run -d 
>> fixfiles.XXXXXXXXXX)"
>> warning: 1 line adds whitespace errors.
>> 
>>> > +                 export SETFILES VERBOSE EXCLUDEDIRS FORCEFLAG THREADS FC TMP_MOUNT m
>>> > +                 if type unshare &> /dev/null; then
>>> > +                     unshare -m bash -x -c "fix_labels_on_mountpoint" $* || exit $?
>> 
>> Two issues:
>> 
>> I.
>> The `-x` flag make the output unreadable (especially for 
>> check/verify).
> 
> 
> This is leftover from my debugging. It is not supposed to be there.
> 
> 
>> II.
>> The option (e.g. `-n` for check/verify) is not passed, should be `-c
>> "fix_labels_on_mountpoint $*"`.
> 
> I'll fix it.
> 
> 
> Thanks!
> 
> 
>>> > +                 else
>>> > +                     trap umount_TMP_MOUNT EXIT
>>> > +                     fix_labels_on_mountpoint $*
>>> > +                     trap EXIT
>>> > +                 fi
>>> >               done;
>>> >           fi
>>> >       else
>>> > --
>>> > 2.37.3
>>>
diff mbox series

Patch

diff --git a/policycoreutils/scripts/fixfiles b/policycoreutils/scripts/fixfiles
index c72ca0eb9d61..af64a5a567a6 100755
--- a/policycoreutils/scripts/fixfiles
+++ b/policycoreutils/scripts/fixfiles
@@ -207,6 +207,25 @@  rpm -q --qf '[%{FILESTATES} %{FILENAMES}\n]' "$1" | grep '^0 ' | cut -f2- -d ' '
 [ ${PIPESTATUS[0]} != 0 ] && echo "$1 not found" >/dev/stderr
 }
 
+# unmount tmp bind mount before exit
+umount_TMP_MOUNT() {
+	if [ -n "$TMP_MOUNT" ]; then
+	     umount "${TMP_MOUNT}${m}" || exit 130
+	     rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
+	fi
+	exit 130
+}
+
+fix_labels_on_mountpoint() {
+	test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
+	mkdir -p "${TMP_MOUNT}${m}" || exit 1
+	mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
+	${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
+	umount "${TMP_MOUNT}${m}" || exit 1
+	rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
+}
+export -f fix_labels_on_mountpoint
+
 #
 # restore
 # if called with -n will only check file context
@@ -252,14 +271,15 @@  case "$RESTORE_MODE" in
 	        # we bind mount so we can fix the labels of files that have already been
 	        # mounted over
 	        for m in `echo $FILESYSTEMSRW`; do
-	            TMP_MOUNT="$(mktemp -d)"
-	            test -z ${TMP_MOUNT+x} && echo "Unable to find temporary directory!" && exit 1
-
-	            mkdir -p "${TMP_MOUNT}${m}" || exit 1
-	            mount --bind "${m}" "${TMP_MOUNT}${m}" || exit 1
-	            ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} ${FORCEFLAG} ${THREADS} $* -q ${FC} -r "${TMP_MOUNT}" "${TMP_MOUNT}${m}"
-	            umount "${TMP_MOUNT}${m}" || exit 1
-	            rm -rf "${TMP_MOUNT}" || echo "Error cleaning up."
+	          	TMP_MOUNT="$(mktemp -p /run -d fixfiles.XXXXXXXXXX)"
+	            export SETFILES VERBOSE EXCLUDEDIRS FORCEFLAG THREADS FC TMP_MOUNT m
+	            if type unshare &> /dev/null; then
+	                unshare -m bash -x -c "fix_labels_on_mountpoint" $* || exit $?
+	            else
+	                trap umount_TMP_MOUNT EXIT
+	                fix_labels_on_mountpoint $*
+	                trap EXIT
+	            fi
 	        done;
 	    fi
 	else