Re: [PATCH 2/3] libselinux: generate Python glue code using "sed"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/1/19 5:27 AM, Nicolas Iooss wrote:
libselinux currently uses "gcc -aux-info" in order to generate glue code
for its Python bindings that throws an exception when a function returns
a negative integer value. This causes issues when another compiler than
gcc is used (such as clang or icc), as option -aux-info is specific to
gcc.

Replace "gcc -aux-info" with a command that parses the content of header
files using "sed". As this is more fragile (because the declaration of
functions is not normalized), add a new target to the Makefile in order
to test that the new method does not produce different results with
"make CC=gcc test".

When reverting commit cfe487409307 ("libselinux: mark all exported
function "extern""), "make test" now fails as expected:

     bash -e exception.sh test
     Error ensuring that all exported functions that return an int are handled by exception.sh.
     Here are functions that were not found in "gcc -aux-info" but that were collected by "sed":
     Here are functions in "gcc -aux-info" that may be missing "extern" in header file:
     selinuxfs_exists
     make: *** [Makefile:202: test] Error 1

Original thread: https://lore.kernel.org/selinux/20191012172357.GB19655@xxxxxxxxxxxxxxxxx/T/#ma78bd7fe71fb5784387a8c0cebd867d6c02ee6e4

I'm not excited about moving to a more fragile method of generating this glue code. Would it perhaps suffice for us to pre-generate the files and keep them in-tree (or package them as part of the tar file distributions) so that downstream users without gcc can just use the generated files?


Signed-off-by: Nicolas Iooss <nicolas.iooss@xxxxxxx>
Cc: Michael Shigorin <mike@xxxxxxxxxxxx>
---
  libselinux/Makefile         |  1 +
  libselinux/src/Makefile     |  5 ++++-
  libselinux/src/exception.sh | 38 +++++++++++++++++++++++++++++++------
  3 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/libselinux/Makefile b/libselinux/Makefile
index 16531fe95bf5..c0ae884f8ede 100644
--- a/libselinux/Makefile
+++ b/libselinux/Makefile
@@ -67,3 +67,4 @@ clean-rubywrap:
  	$(MAKE) -C src clean-rubywrap $@
test:
+	$(MAKE) -C src test
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index 63d6b0eda270..c12230a17b1d 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -198,7 +198,10 @@ clean: clean-pywrap clean-rubywrap
  distclean: clean
  	rm -f $(GENERATED) $(SWIGFILES)
+test:
+	bash -e exception.sh test
+
  indent:
  	../../scripts/Lindent $(filter-out $(GENERATED),$(wildcard *.[ch]))
-.PHONY: all clean clean-pywrap clean-rubywrap pywrap rubywrap swigify install install-pywrap install-rubywrap distclean
+.PHONY: all clean clean-pywrap clean-rubywrap pywrap rubywrap swigify install install-pywrap install-rubywrap distclean test indent
diff --git a/libselinux/src/exception.sh b/libselinux/src/exception.sh
index d6c8c71713ad..adbb632c2f04 100755
--- a/libselinux/src/exception.sh
+++ b/libselinux/src/exception.sh
@@ -1,11 +1,12 @@
+#!/bin/bash -e
  function except() {
-case $1 in
+case "$1" in
      selinux_file_context_cmp) # ignore
      ;;
      *)
  echo "
  %exception $1 {
-  \$action
+  \$action
    if (result < 0) {
       PyErr_SetFromErrno(PyExc_OSError);
       SWIG_fail;
@@ -15,10 +16,35 @@ echo "
  ;;
  esac
  }
-if ! ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h
+
+if [ $# -eq 1 ] && [ "$1" = "test" ]
  then
-    # clang does not support -aux-info so fall back to gcc
-    gcc -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h
+    # Ensure that "gcc -aux-info" produces the same list of functions as the sed command.
+    # The main difference between these way of producing the list of exported
+    # functions is that "gcc -aux-info" automatically inserts "extern" to all
+    # declarations and writes each one on a single line.
+    # clang does not support -aux-info, so skip the test if generating the aux file failed.
+    if ${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h
+    then
+        FCT_FROM_AUX="$(awk '/<stdin>.*extern int/ { print $6 }' temp.aux | sort -u)"
+        FCT_FROM_SED="$(sed -n 's/^extern \+int \+\([0-9A-Za-z_]\+\) *(.*$/\1/p' < ../include/selinux/selinux.h | sort -u)"
+        if [ "$FCT_FROM_AUX" != "$FCT_FROM_SED" ]
+        then
+            echo >&2 'Error ensuring that all exported functions that return an int are handled by exception.sh.'
+            echo >&2 'Here are functions that were not found in "gcc -aux-info" but that were collected by "sed":'
+            comm -13 <(echo "$FCT_FROM_AUX") <(echo "$FCT_FROM_SED")
+            echo >&2 'Here are functions in "gcc -aux-info" that may be missing "extern" in header file:'
+            comm -23 <(echo "$FCT_FROM_AUX") <(echo "$FCT_FROM_SED")
+            exit 1
+        fi
+    fi
+    rm -f -- temp.aux -.o
+    exit
  fi
-for i in `awk '/<stdin>.*extern int/ { print $6 }' temp.aux`; do except $i ; done
+
+# shellcheck disable=SC2013
+for i in $(sed -n 's/^extern \+int \+\([0-9A-Za-z_]\+\) *(.*$/\1/p' < ../include/selinux/selinux.h)
+do
+    except "$i"
+done
  rm -f -- temp.aux -.o





[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux