GNU/Linux >> Tutoriels Linux >  >> Linux

Comportement par défaut de Linux par rapport à la section `.data`

Votre binaire manque PT_GNU_STACK . En tant que tel, ce changement semble avoir été causé par le commit 9fccc5c0c99f238aa1b0460fccbdb30a887e7036 :

From 9fccc5c0c99f238aa1b0460fccbdb30a887e7036 Mon Sep 17 00:00:00 2001
From: Kees Cook <[email protected]>
Date: Thu, 26 Mar 2020 23:48:17 -0700
Subject: x86/elf: Disable automatic READ_IMPLIES_EXEC on 64-bit

With modern x86 64-bit environments, there should never be a need for
automatic READ_IMPLIES_EXEC, as the architecture is intended to always
be execute-bit aware (as in, the default memory protection should be NX
unless a region explicitly requests to be executable).

There were very old x86_64 systems that lacked the NX bit, but for those,
the NX bit is, obviously, unenforceable, so these changes should have
no impact on them.

Suggested-by: Hector Marco-Gisbert <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Reviewed-by: Jason Gunthorpe <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
---
 arch/x86/include/asm/elf.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 397a1c74433ec..452beed7892bb 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -287,7 +287,7 @@ extern u32 elf_hwcap2;
  *                 CPU: | lacks NX*  | has NX, ia32     | has NX, x86_64 |
  * ELF:                 |            |                  |                |
  * ---------------------|------------|------------------|----------------|
- * missing PT_GNU_STACK | exec-all   | exec-all         | exec-all       |
+ * missing PT_GNU_STACK | exec-all   | exec-all         | exec-none      |
  * PT_GNU_STACK == RWX  | exec-stack | exec-stack       | exec-stack     |
  * PT_GNU_STACK == RW   | exec-none  | exec-none        | exec-none      |
  *
@@ -303,7 +303,7 @@ extern u32 elf_hwcap2;
  *
  */
 #define elf_read_implies_exec(ex, executable_stack)    \
-   (executable_stack == EXSTACK_DEFAULT)
+   (mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
 
 struct task_struct;
 
-- 
cgit 1.2.3-1.el7

C'était d'abord présent dans la série 5.8. Voir aussi Autorisation d'exécution inattendue de mmap lorsque des fichiers d'assemblage sont inclus dans le projet.


Ce n'est qu'une supposition :Je pense que le coupable est le READ_IMPLIES_EXEC personnalité qui était définie automatiquement en l'absence de PT_GNU_STACK segment.

Dans les sources du noyau 5.4, nous pouvons trouver ce morceau de code :

SET_PERSONALITY2(loc->elf_ex, &arch_state);
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
    current->personality |= READ_IMPLIES_EXEC;

C'est la seule chose qui puisse transformer une section RW en une section RWX. Toute autre utilisation de PROC_EXEC ne semblait pas être changé ou pertinent pour cette question, pour moi.

Le executable_stack est défini ici :

for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
    switch (elf_ppnt->p_type) {
    case PT_GNU_STACK:
        if (elf_ppnt->p_flags & PF_X)
            executable_stack = EXSTACK_ENABLE_X;
        else
            executable_stack = EXSTACK_DISABLE_X;
        break;

Mais si le PT_GNU_STACK segment n'est pas présent, cette variable conserve sa valeur par défaut :

int executable_stack = EXSTACK_DEFAULT;

Maintenant, ce flux de travail est identique dans la version 5.4 et la dernière source du noyau, ce qui a changé est la définition de elf_read_implies_exec :

Linux 5.4 :

/*
 * An executable for which elf_read_implies_exec() returns TRUE will
 * have the READ_IMPLIES_EXEC personality flag set automatically.
 */
#define elf_read_implies_exec(ex, executable_stack) \
    (executable_stack != EXSTACK_DISABLE_X)

Linux le plus récent :

/*
 * An executable for which elf_read_implies_exec() returns TRUE will
 * have the READ_IMPLIES_EXEC personality flag set automatically.
 *
 * The decision process for determining the results are:
 *
 *                 CPU: | lacks NX*  | has NX, ia32     | has NX, x86_64 |
 * ELF:                 |            |                  |                |
 * ---------------------|------------|------------------|----------------|
 * missing PT_GNU_STACK | exec-all   | exec-all         | exec-none      |
 * PT_GNU_STACK == RWX  | exec-stack | exec-stack       | exec-stack     |
 * PT_GNU_STACK == RW   | exec-none  | exec-none        | exec-none      |
 *
 *  exec-all  : all PROT_READ user mappings are executable, except when
 *              backed by files on a noexec-filesystem.
 *  exec-none : only PROT_EXEC user mappings are executable.
 *  exec-stack: only the stack and PROT_EXEC user mappings are executable.
 *
 *  *this column has no architectural effect: NX markings are ignored by
 *   hardware, but may have behavioral effects when "wants X" collides with
 *   "cannot be X" constraints in memory permission flags, as in
 *   https://lkml.kernel.org/r/[email protected]
 *
 */
#define elf_read_implies_exec(ex, executable_stack) \
    (mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)

Notez comment dans la version 5.4 le elf_read_implies_exec a renvoyé une valeur vraie si la pile n'était pas explicitement marqué comme non exécutable (via le PT_GNU_STACK segment).

Dans la dernière source, la vérification est maintenant plus défensive :le elf_read_implies_exec est vrai uniquement sur un exécutable 32 bits, dans le cas où aucun PT_GNU_STACK segment a été trouvé dans le binaire ELF.

J'ai assemblé votre programme, l'ai lié et n'ai trouvé aucun PT_GNU_STACK segment, donc cela peut être la raison.
Si tel est bien le problème et si j'ai bien suivi le code, si vous définissez la pile comme non exécutable dans le binaire, sa section de données ne devrait plus être mappée exécutable (même pas sous Linux 5.4).


Linux
  1. Comment trouver l'adresse IP de la passerelle par défaut sous Linux

  2. Comment changer le shell par défaut sous Linux

  3. Emplacement par défaut de la base de données PostgreSQL sous Linux

  4. Changer le shell par défaut sous Linux

  5. Modifier le comportement du bouton d'alimentation Linux

Commande Dig sous Linux (recherche DNS)

Fonds d'écran par défaut d'Ubuntu sur Arch Linux

Comment afficher une section spécifique dans les pages de manuel sous Linux

Comment changer le fichier journal Sudo par défaut sous Linux

Réinitialiser les paramètres du bureau Gnome par défaut sous Linux

Comment changer le shell par défaut dans le système Linux