]> git.ipfire.org Git - pakfire.git/commitdiff
ELF: Create a function to easily walk through all program headers
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 3 Jan 2025 08:42:07 +0000 (08:42 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 3 Jan 2025 08:42:07 +0000 (08:42 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/elf.c

index 10f25a22b796ef1c0682737cbd6aef926ae09683..c6c681fabd0dee1482eff1c23514f31f84ff1769 100644 (file)
@@ -282,6 +282,30 @@ const char* pakfire_elf_debuglink(struct pakfire_elf* self) {
        return self->debuglink;
 }
 
+typedef int (*pakfire_elf_foreach_program_header_callback)
+       (struct pakfire_elf* self, const GElf_Phdr* phdr, void* data);
+
+static int pakfire_elf_foreach_program_header(struct pakfire_elf* self,
+               pakfire_elf_foreach_program_header_callback callback, void* data) {
+       GElf_Phdr phdr = {};
+       int r;
+
+       // Walk through all program headers
+       for (unsigned int i = 0; i < self->phnum; i++) {
+               if (!gelf_getphdr(self->elf, i, &phdr)) {
+                       ERROR(self->ctx, "Could not parse program header: %s\n", elf_errmsg(-1));
+                       return -ENOTSUP;
+               }
+
+               // Call the callback
+               r = callback(self, &phdr, data);
+               if (r)
+                       break;
+       }
+
+       return r;
+}
+
 static int pakfire_elf_get_section(struct pakfire_elf* self,
                const Elf64_Word type, const char* name, Elf_Scn** section, GElf_Shdr* header, Elf_Data** data) {
        const char* sname = NULL;
@@ -480,38 +504,33 @@ int pakfire_elf_has_ssp(struct pakfire_elf* self) {
        return 0;
 }
 
-int pakfire_elf_has_execstack(struct pakfire_elf* self) {
-       GElf_Phdr phdr;
-
-       // Walk through all program headers
-       for (unsigned int i = 0; i < self->phnum; i++) {
-               if (!gelf_getphdr(self->elf, i, &phdr)) {
-                       ERROR(self->ctx, "Could not parse program header: %s\n", elf_errmsg(-1));
-                       return -ENOTSUP;
-               }
-
-               switch (phdr.p_type) {
-                       case PT_GNU_STACK:
-                               DEBUG(self->ctx,
-                                       "%s: GNU_STACK flags: %c%c%c\n",
-                                       self->path,
-                                       (phdr.p_flags & PF_R) ? 'R' : '-',
-                                       (phdr.p_flags & PF_W) ? 'W' : '-',
-                                       (phdr.p_flags & PF_X) ? 'X' : '-'
-                               );
-
-                               // The stack cannot be writable and executable
-                               if ((phdr.p_flags & PF_W) && (phdr.p_flags & PF_X))
-                                       return 1;
+static int pakfire_elf_check_execstack(
+               struct pakfire_elf* self, const GElf_Phdr* phdr, void* data) {
+       switch (phdr->p_type) {
+               case PT_GNU_STACK:
+                       DEBUG(self->ctx,
+                               "%s: GNU_STACK flags: %c%c%c\n",
+                               self->path,
+                               (phdr->p_flags & PF_R) ? 'R' : '-',
+                               (phdr->p_flags & PF_W) ? 'W' : '-',
+                               (phdr->p_flags & PF_X) ? 'X' : '-'
+                       );
+
+                       // The stack cannot be writable and executable
+                       if ((phdr->p_flags & PF_W) && (phdr->p_flags & PF_X))
+                               return 1;
 
-                       default:
-                               break;
-               }
+               default:
+                       break;
        }
 
        return 0;
 }
 
+int pakfire_elf_has_execstack(struct pakfire_elf* self) {
+       return pakfire_elf_foreach_program_header(self, pakfire_elf_check_execstack, NULL);
+}
+
 static int pakfire_elf_has_bind_now(struct pakfire_elf* self,
                const GElf_Shdr* shdr, const GElf_Dyn* dyn, void* data) {
        switch (dyn->d_tag) {