diff mbox series

[v4,8/10] qemu-binfmt-conf.sh: add option --clear

Message ID 20190311103106.GG16@765644dd90e5 (mailing list archive)
State New, archived
Headers show
Series qemu-binfmt-conf.sh | expand

Commit Message

Unai Martinez Corral March 11, 2019, 10:31 a.m. UTC
This is a partial implementation.

Allows to remove a single or a list of already registered binfmt
interpreters. Valid values are those in qemu_target_list.
If TARGETS is empty, all the existing 'qemu-*' interpreters are
removed.

This is partial because 'debian' and 'systemd' configurations are not
supported. The script will exit with error 'option clear not
implemented for this mode yet'.

Removal is done by printing '-1' as explained at:
https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst

Signed-off-by: Unai Martinez-Corral <unai.martinezcorral@ehu.eus>
---
 scripts/qemu-binfmt-conf.sh | 41 ++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

--
2.21.0

Comments

Laurent Vivier March 11, 2019, 11:04 a.m. UTC | #1
On 11/03/2019 11:31, Unai Martinez-Corral wrote:
> This is a partial implementation.
> 
> Allows to remove a single or a list of already registered binfmt
> interpreters. Valid values are those in qemu_target_list.
> If TARGETS is empty, all the existing 'qemu-*' interpreters are
> removed.
> 
> This is partial because 'debian' and 'systemd' configurations are not
> supported. The script will exit with error 'option clear not
> implemented for this mode yet'.
> 
> Removal is done by printing '-1' as explained at:
> https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst
> 
> Signed-off-by: Unai Martinez-Corral <unai.martinezcorral@ehu.eus>
> ---
>  scripts/qemu-binfmt-conf.sh | 41 ++++++++++++++++++++++++++++++++++---
>  1 file changed, 38 insertions(+), 3 deletions(-)
> 
> diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
> index fde78517ff..07d1ee1f04 100755
> --- a/scripts/qemu-binfmt-conf.sh
> +++ b/scripts/qemu-binfmt-conf.sh
> @@ -196,7 +196,7 @@ Options and associated environment variables:
> 
>  Argument             Env-variable     Description
>  TARGETS              QEMU_TARGETS     A single arch name or a list of them (see all names below);
> -                                      if empty, configure all known targets;
> +                                      if empty, configure/clear all known targets;
>                                        if 'NONE', no interpreter is configured.
>  -h|--help                             display this usage
>  -Q|--path PATH:      QEMU_PATH        set path to qemu interpreter(s)
> @@ -206,9 +206,10 @@ TARGETS              QEMU_TARGETS     A single arch name or a list of them (see
>                                        systemd-binfmt.service; environment variable HOST_ARCH
>                                        allows to override 'uname' to generate configuration files
>                                        for a different architecture than the current one.
> -
>  -e|--exportdir PATH: DEBIANDIR        define where to write configuration files
>                       SYSTEMDDIR
> +-c|--clear:          QEMU_CLEAR       (yes) remove registered interpreters for target TARGETS;
> +                                      then exit.
>  -c|--credential:     QEMU_CREDENTIAL  (yes) credential and security tokens are calculated according
>                                        to the binary to interpret
>  -p|--persistent:     QEMU_PERSISTENT  (yes) load the interpreter and keep it in memory; all future
> @@ -336,6 +337,25 @@ qemu_set_binfmts() {
>      done
>  }
> 
> +qemu_clear_notimplemented() {
> +    echo "ERROR: option clear not implemented for this mode yet" 1>&2
> +    usage
> +    exit 1
> +}
> +
> +qemu_clear_interpreter() {
> +    names='qemu-*'
> +    if [ $# -ne 0 ] ; then
> +        qemu_check_target_list $1
> +        unset names pre
> +        for t in $checked_target_list ; do
> +            names="${names}${pre}qemu-$t"
> +            pre=' -o -name '
> +        done
> +    fi
> +    find /proc/sys/fs/binfmt_misc/ -type f -name $names -exec sh -c 'printf %s -1 > {}' \;

The qemu-* will be expanded here if you have a qemu-XXX in the current
directory. You must use "$names".

But:

To remove all, you can do:
sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/status'

so something like

if [ $# -eq 0 ] ; then
  sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/status
fi
qemu_check_target_list $1
for t in $checked_target_list ; do
   sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/qemu-$t'
done

But I think you should also taking care of the suffix.

> +}
> +
>  CHECK=qemu_check_bintfmt_misc
>  BINFMT_SET=qemu_register_interpreter
> 
> @@ -347,12 +367,16 @@ QEMU_PATH="${QEMU_PATH:-/usr/local/bin}"
>  QEMU_SUFFIX="${QEMU_SUFFIX:-}"
>  QEMU_CREDENTIAL="${QEMU_CREDENTIAL:-no}"
>  QEMU_PERSISTENT="${QEMU_PERSISTENT:-no}"
> +QEMU_CLEAR="${QEMU_CLEAR:-no}"
> 
> -options=$(getopt -o dsQ:S:e:hcp -l debian,systemd,path:,suffix:,exportdir:,help,credential,persistent -- "$@")
> +options=$(getopt -o cdsQ:S:e:hcp -l clear,debian,systemd,path:,suffix:,exportdir:,help,credential,persistent -- "$@")
>  eval set -- "$options"
> 
>  while true ; do
>      case "$1" in
> +    -c|--clear)
> +        QEMU_CLEAR="yes"
> +        ;;
>      -d|--debian)
>          CHECK=qemu_check_debian
>          BINFMT_SET=qemu_generate_debian
> @@ -395,4 +419,15 @@ done
>  shift
> 
>  $CHECK
> +
> +if [ "x$QEMU_CLEAR" = "xyes" ] ; then
> +  case "$BINFMT_SET" in
> +    *debian)  BINFMT_CLEAR=qemu_clear_notimplemented ;;
> +    *systemd) BINFMT_CLEAR=qemu_clear_notimplemented ;;
> +    *)        BINFMT_CLEAR=qemu_clear_interpreter
> +  esac

Put this in the previous case for decoding options, please.

> +  $BINFMT_CLEAR "$@"
> +  exit
> +fi
> +
>  qemu_set_binfmts "$@"
> --
> 2.21.0
>
Unai Martinez Corral March 11, 2019, 1:19 p.m. UTC | #2
2019/3/11 12:04, Laurent Vivier:
> > +    find /proc/sys/fs/binfmt_misc/ -type f -name $names -exec sh -c 'printf %s -1 > {}' \;
>
> The qemu-* will be expanded here if you have a qemu-XXX in the current
> directory. You must use "$names".

You are correct. Indeed, I had not spotted it because I introduced a
bug when renaming 'reset' to 'clear'. Precisely, '-c' was being used
twice: for 'credential' and for 'clear'. Both issues will be fixed in
the next version.

> But:
>
> To remove all, you can do:
> sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/status'
>
> so something like
>
> if [ $# -eq 0 ] ; then
>   sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/status
> fi
> qemu_check_target_list $1
> for t in $checked_target_list ; do
>    sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/qemu-$t'
> done

Wouldn't writing to 'status' remove all the interpreters, and not only
those that correspond to qemu?

> But I think you should also taking care of the suffix.

I think that the suffix is not related to the entry in
'/proc/sys/fs/binfmt_misc/'. See, e.g.:

package qemu-$cpu
interpreter $qemu

So, independently of which is the executable (interpreter), the
package name does not include the suffix.

> > +if [ "x$QEMU_CLEAR" = "xyes" ] ; then
> > +  case "$BINFMT_SET" in
> > +    *debian)  BINFMT_CLEAR=qemu_clear_notimplemented ;;
> > +    *systemd) BINFMT_CLEAR=qemu_clear_notimplemented ;;
> > +    *)        BINFMT_CLEAR=qemu_clear_interpreter
> > +  esac
>
> Put this in the previous case for decoding options, please.

It won't work. This if/case block requires all the options to be
already parsed and processed. If I put it in the case for '-r|--clear'
above, it will only work only when '-r' is given after '--debian' or
'--systemd'. Otherwise, BINFMT_SET will always be
qemu_register_interpreter when '-crear' is evaluated. I think that we
should not rely on the users providing the options in a specific
order.

Regards,
Unai
Laurent Vivier March 11, 2019, 1:30 p.m. UTC | #3
On 11/03/2019 14:19, Unai Martinez Corral wrote:
> 2019/3/11 12:04, Laurent Vivier:
>>> +    find /proc/sys/fs/binfmt_misc/ -type f -name $names -exec sh -c 'printf %s -1 > {}' \;
>>
>> The qemu-* will be expanded here if you have a qemu-XXX in the current
>> directory. You must use "$names".
> 
> You are correct. Indeed, I had not spotted it because I introduced a
> bug when renaming 'reset' to 'clear'. Precisely, '-c' was being used
> twice: for 'credential' and for 'clear'. Both issues will be fixed in
> the next version.
> 
>> But:
>>
>> To remove all, you can do:
>> sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/status'
>>
>> so something like
>>
>> if [ $# -eq 0 ] ; then
>>   sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/status
>> fi
>> qemu_check_target_list $1
>> for t in $checked_target_list ; do
>>    sh -c 'printf %s -1 > /proc/sys/fs/binfmt_misc/qemu-$t'
>> done
> 
> Wouldn't writing to 'status' remove all the interpreters, and not only
> those that correspond to qemu?

Yes, you are right.

> 
>> But I think you should also taking care of the suffix.
> 
> I think that the suffix is not related to the entry in
> '/proc/sys/fs/binfmt_misc/'. See, e.g.:
> 
> package qemu-$cpu
> interpreter $qemu
> 
> So, independently of which is the executable (interpreter), the
> package name does not include the suffix.

Yes, you are right.

>>> +if [ "x$QEMU_CLEAR" = "xyes" ] ; then
>>> +  case "$BINFMT_SET" in
>>> +    *debian)  BINFMT_CLEAR=qemu_clear_notimplemented ;;
>>> +    *systemd) BINFMT_CLEAR=qemu_clear_notimplemented ;;
>>> +    *)        BINFMT_CLEAR=qemu_clear_interpreter
>>> +  esac
>>
>> Put this in the previous case for decoding options, please.
> 
> It won't work. This if/case block requires all the options to be
> already parsed and processed. If I put it in the case for '-r|--clear'
> above, it will only work only when '-r' is given after '--debian' or
> '--systemd'. Otherwise, BINFMT_SET will always be
> qemu_register_interpreter when '-crear' is evaluated. I think that we
> should not rely on the users providing the options in a specific
> order.

I meant something like this:

diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
index b5a16742a149..5c2651a6df57 100755
--- a/scripts/qemu-binfmt-conf.sh
+++ b/scripts/qemu-binfmt-conf.sh
@@ -327,17 +327,23 @@ QEMU_SUFFIX=""
 options=$(getopt -o ds:Q:S:e:hc:p: -l
debian,systemd:,qemu-path:,qemu-suffix:,exportdir:,help,credential:,persistent:
-- "$@")
 eval set -- "$options"

+BINFMT_CLEAR=qemu_clear_interpreter
 while true ; do
     case "$1" in
+    -c|--clear)
+        QEMU_CLEAR="yes"
+        ;;
     -d|--debian)
         CHECK=qemu_check_debian
         BINFMT_SET=qemu_generate_debian
         EXPORTDIR=${EXPORTDIR:-$DEBIANDIR}
+        BINFMT_CLEAR=qemu_clear_notimplemented
         ;;
     -s|--systemd)
         CHECK=qemu_check_systemd
         BINFMT_SET=qemu_generate_systemd
         EXPORTDIR=${EXPORTDIR:-$SYSTEMDDIR}
+        BINFMT_CLEAR=qemu_clear_notimplemented
         shift
         # check given cpu is in the supported CPU list
         if [ "$1" != "ALL" ] ; then
@@ -387,5 +393,9 @@ while true ; do
     shift
 done

+if [ "x$QEMU_CLEAR" = "xyes" ] ; then
+  $BINFMT_CLEAR "$@"
+  exit
+fi
 $CHECK
 qemu_set_binfmts
diff mbox series

Patch

diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
index fde78517ff..07d1ee1f04 100755
--- a/scripts/qemu-binfmt-conf.sh
+++ b/scripts/qemu-binfmt-conf.sh
@@ -196,7 +196,7 @@  Options and associated environment variables:

 Argument             Env-variable     Description
 TARGETS              QEMU_TARGETS     A single arch name or a list of them (see all names below);
-                                      if empty, configure all known targets;
+                                      if empty, configure/clear all known targets;
                                       if 'NONE', no interpreter is configured.
 -h|--help                             display this usage
 -Q|--path PATH:      QEMU_PATH        set path to qemu interpreter(s)
@@ -206,9 +206,10 @@  TARGETS              QEMU_TARGETS     A single arch name or a list of them (see
                                       systemd-binfmt.service; environment variable HOST_ARCH
                                       allows to override 'uname' to generate configuration files
                                       for a different architecture than the current one.
-
 -e|--exportdir PATH: DEBIANDIR        define where to write configuration files
                      SYSTEMDDIR
+-c|--clear:          QEMU_CLEAR       (yes) remove registered interpreters for target TARGETS;
+                                      then exit.
 -c|--credential:     QEMU_CREDENTIAL  (yes) credential and security tokens are calculated according
                                       to the binary to interpret
 -p|--persistent:     QEMU_PERSISTENT  (yes) load the interpreter and keep it in memory; all future
@@ -336,6 +337,25 @@  qemu_set_binfmts() {
     done
 }

+qemu_clear_notimplemented() {
+    echo "ERROR: option clear not implemented for this mode yet" 1>&2
+    usage
+    exit 1
+}
+
+qemu_clear_interpreter() {
+    names='qemu-*'
+    if [ $# -ne 0 ] ; then
+        qemu_check_target_list $1
+        unset names pre
+        for t in $checked_target_list ; do
+            names="${names}${pre}qemu-$t"
+            pre=' -o -name '
+        done
+    fi
+    find /proc/sys/fs/binfmt_misc/ -type f -name $names -exec sh -c 'printf %s -1 > {}' \;
+}
+
 CHECK=qemu_check_bintfmt_misc
 BINFMT_SET=qemu_register_interpreter

@@ -347,12 +367,16 @@  QEMU_PATH="${QEMU_PATH:-/usr/local/bin}"
 QEMU_SUFFIX="${QEMU_SUFFIX:-}"
 QEMU_CREDENTIAL="${QEMU_CREDENTIAL:-no}"
 QEMU_PERSISTENT="${QEMU_PERSISTENT:-no}"
+QEMU_CLEAR="${QEMU_CLEAR:-no}"

-options=$(getopt -o dsQ:S:e:hcp -l debian,systemd,path:,suffix:,exportdir:,help,credential,persistent -- "$@")
+options=$(getopt -o cdsQ:S:e:hcp -l clear,debian,systemd,path:,suffix:,exportdir:,help,credential,persistent -- "$@")
 eval set -- "$options"

 while true ; do
     case "$1" in
+    -c|--clear)
+        QEMU_CLEAR="yes"
+        ;;
     -d|--debian)
         CHECK=qemu_check_debian
         BINFMT_SET=qemu_generate_debian
@@ -395,4 +419,15 @@  done
 shift

 $CHECK
+
+if [ "x$QEMU_CLEAR" = "xyes" ] ; then
+  case "$BINFMT_SET" in
+    *debian)  BINFMT_CLEAR=qemu_clear_notimplemented ;;
+    *systemd) BINFMT_CLEAR=qemu_clear_notimplemented ;;
+    *)        BINFMT_CLEAR=qemu_clear_interpreter
+  esac
+  $BINFMT_CLEAR "$@"
+  exit
+fi
+
 qemu_set_binfmts "$@"