From 3812c801fbfcfd8f92ee3b2fc17983ce843c2cbe Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 24 Nov 2025 22:03:11 +0100 Subject: [PATCH] Build: ensure that installed shared libs are not executable This is a Debian policy, which collides with the default behaviour of GCC rsp. the plattform linker. The latter creates all ELF files as executable, possibly because some platforms require that, and also because some libraries provide a main() function for diagnostics. The argument by the Debian people is that most libraries don't provide such a main() and that this is an esoteric feature which should not be supported by default. We can fix that in our SCons build, since we use a specialised Builder to also define the install targets systematically; it suffices to add a post-action to these install targets for shared objects. Note: currently Debian/Trixie provides SCons 4.8, but v4.10 will provide a shorthand notation with the env.Chmod Action factory. --- admin/scons/LumieraEnvironment.py | 22 ++- wiki/thinkPad.ichthyo.mm | 299 +++++++++++++++++++++++++++++- 2 files changed, 316 insertions(+), 5 deletions(-) diff --git a/admin/scons/LumieraEnvironment.py b/admin/scons/LumieraEnvironment.py index 99a10199f..196b619a1 100644 --- a/admin/scons/LumieraEnvironment.py +++ b/admin/scons/LumieraEnvironment.py @@ -320,7 +320,7 @@ class LumieraModuleBuilder(WrappedStandardExeBuilder): Lumiera modules; modules are assumed to reside in a subdirectory below the executable. """ custEnv = lumiEnv.Clone() - custEnv.Append(LINKFLAGS = "-Wl,-soname="+self.defineSoname(target,**kw)) + custEnv.Append( LINKFLAGS = "-Wl,-soname="+self.defineSoname(target,**kw)) custEnv.Append( LINKFLAGS = "-Wl,-rpath=\\$$ORIGIN/../modules,--enable-new-dtags" ) if 'addLibs' in kw: custEnv.Append(LIBS = kw['addLibs']) @@ -330,6 +330,26 @@ class LumieraModuleBuilder(WrappedStandardExeBuilder): def getInstallDestination(self, lumiEnv): return lumiEnv.path.installLib + def installTarget(self, env, buildTarget, **kw): + """ ensure a shared library is not marked executable. + The default toolchain on Linux often installs shared libraries as executable, which seems + to be necessary on some arcane Unix platforms. However, Debian Policy prohibits that. + See https://unix.stackexchange.com/questions/400187/why-should-or-should-not-shared-libraries-be-executable-e-g-red-hat-vs-debian + """ + toInstall = super().installTarget(env, buildTarget, **kw) + if toInstall: + def _Chmod(target, source, env): + """ Workaround since env.Chmod is present only in SCons 4.10 """ + import os + for t in target: + os.chmod(str(t), 0o644) + return None +# removeExecBit = env.Chmod(toInstall, 0o644) + msg = '....... clear exec perm %s' % [str(t) for t in toInstall] + removeExecBit = env.Action(_Chmod, msg) + env.AddPostAction(toInstall, removeExecBit) + return toInstall + def defineSoname (self, target, **kw): """ internal helper to extract or guess a suitable library SONAME, either using an diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2cfafb541..79190b7ce 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -159320,6 +159320,34 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -178649,6 +178677,268 @@ Since then others have made contributions, see the log for the history. + + + + + + + + + +

+ der verhält sich nach dem Motto: »schad ja nix«... +

+

+ Auf einigen esoterischen Platformen müssen Shared-Libs tatsächlich executable sein, und auf allen anderen Plattformen wird das Flag ignoriert +

+ + +
+
+ + + + + + +

+ Es ist nämlich so: Shared-Libs können eine main()-Funktion enthalten; und wenn das der Fall ist, können sie auch als Executables aufgerufen werden. Rein theoretisch könnte das ein Baustein in einem komplexen Exploit sein, der aus einer überraschenden Ecke käme, da das ein Thema ist, was niemand »auf dem Radar hat«. Manche Libraries haben in der Tat ein Main, und das macht typischerweise gewisse Diagnose-Funktionalität. +

+

+ +

+

+ Klingt alles doch einigermaßen an den Haaren herbeigezogen, aber Debian stellt sich auf den Standpunkt: Unnötiges verbieten schad' nix +

+ + +
+
+ + + + + + + + + + + +

+ ...das liegt daran, daß ich das Bauen von Executables und Libraries und Plugins bereits hochgradig customised habe, im LumieraEnvironment. Das bedeutet, es gibt bereits einen env.Install()-Aufruf, tief in Lumiera-spezifischem Framework-Code. Genau diesen Aufruf muß ich nun so modifizieren, daß entweder davor oder danach noch die Permissions geändert werden. +

+ + +
+ + + + + + + + +

+ Use one of these approaches: chain actions in a single Command, or install first then attach a post-action (via AddPostAction  or Command on the installed node). Both keep the install and chmod as a single build step. +

+
+ + +

+ Examples +

+
    +
  • + Chain actions in a single Command (recommended when you want one target built by a composed action): +
  • +
+

+    
+

+ py +

+
+
env.Command(
+    target = '$INSTDIR/myfile',
+    source = 'myfile',
+    action = [
+        env.Install('$INSTDIR', '$SOURCE'),
+        SCons.Action.Action('chmod 0644 $TARGET')
+    ]
+)
+
    +
  • + Install then add a post-action to change permissions (clear intent, uses SCons helpers): +
  • +
+

+    
+

+ py +

+
+
installed = env.Install('$INSTDIR', 'myfile')
+env.AddPostAction(installed, SCons.Action.Action('chmod 0644 $TARGET'))
+
    +
  • + Install then use the built-in Chmod builder on the installed node: +
  • +
+

+    
+

+ py +

+
+
installed = env.Install('$INSTDIR', 'myfile')
+env.Chmod(installed[0], 0o644)
+
+ + +

+ Tips & Alternatives +

+
    +
  • + Prefer env.Command when you need a single atomic step that both installs and changes permissions. +
  • +
  • + Use AddPostAction when you want to keep the install separate and express a follow-up operation. +
  • +
  • + env.Chmod is a portable, Python-level builder; string chmod  commands rely on the shell/OS. +
  • +
+ + +
+ + + + + + + +

+ das wäre schön ... demnach ist ja SCons wirklich so generisch, wie ich gehofft hatte +

+ + +
+
+ + + + + + + + + + + +

+ die entsprechende Methode hanhabt einen Builder-Parameter install=True +

+ + +
+ + + + + +

+ ...den habe ich wohl so eingebaut, damit dieser Umstand auch deklarativ sichtbar wird; zudem gibt es Build-Resultate, die nicht installiert werden (z.B. Tests) +

+ + +
+
+ + + + + + +

+ Es ist klar wie das geht, ich empfinde es aber nach heutigen Standards nicht mehr als besonders schön, aber praktisch, da das hier ein letztlich in sich geschlossenes Ökosystem ist +

+ + +
+
+ + + + + + + + + + + +

+ Debian/Trixie hat 4.8 +

+ +
+ +
+
+
+ + + + + + + + + + +

+ Nein. Macht den Code viel komplexer und steht in keinem Verhältnis zum Nutzen, denn die paar Library-Builder invocations werden uns nicht umbringen +

+ + +
+ +
+ + + +
+
+
+
@@ -181166,7 +181456,8 @@ Since then others have made contributions, see the log for the history.ARCHFLAGS=" -fstack-protector-strong"

- + +
@@ -181426,7 +181717,8 @@ Since then others have made contributions, see the log for the history. - + + @@ -181442,7 +181734,6 @@ Since then others have made contributions, see the log for the history. - @@ -181479,7 +181770,7 @@ Since then others have made contributions, see the log for the history. - +