]> git.ipfire.org Git - pakfire.git/commitdiff
linter: Check for RELRO
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 26 Oct 2024 11:36:09 +0000 (11:36 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 26 Oct 2024 11:36:09 +0000 (11:36 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/file.c
src/libpakfire/linter-file.c

index f4bc1bde344d1a1e70ea70ce523bb0e848b838f1..6b229c576f083a6007cf4fc655a232c970367b10 100644 (file)
@@ -2018,75 +2018,6 @@ static int pakfire_file_check_debuginfo(struct pakfire_file* file) {
        return pakfire_file_open_elf(file, __pakfire_file_check_debuginfo, NULL);
 }
 
-static int __pakfire_file_process_bind_now(struct pakfire_file* file,
-               Elf* elf, const GElf_Shdr* shdr, const GElf_Dyn* dyn, void* data) {
-       int* has_bind_now = (int*)data;
-
-       switch (dyn->d_tag) {
-               case DT_BIND_NOW:
-                       *has_bind_now = 1;
-                       break;
-
-               case DT_FLAGS:
-                       if (dyn->d_un.d_val & DF_BIND_NOW)
-                               *has_bind_now = 1;
-                       break;
-
-               case DT_FLAGS_1:
-                       if (dyn->d_un.d_val & DF_1_NOW)
-                               *has_bind_now = 1;
-                       break;
-
-               default:
-                       break;
-       }
-
-       return 0;
-}
-
-static int __pakfire_file_check_relro(
-               struct pakfire_file* file, Elf* elf, void* data) {
-       int has_bind_now = 0;
-       GElf_Phdr phdr;
-       int r;
-
-       // Check if we have BIND_NOW
-       r = pakfire_file_elf_dyn_walk(file, elf,
-               __pakfire_file_process_bind_now, &has_bind_now);
-       if (r)
-               return r;
-
-       // We are not fully RELRO
-       if (!has_bind_now) {
-               file->issues |= PAKFIRE_FILE_NO_RELRO;
-
-               return 0;
-       }
-
-       // Walk through all program headers
-       for (unsigned int i = 0;; i++) {
-               if (!gelf_getphdr(elf, i, &phdr))
-                       break;
-
-               switch (phdr.p_type) {
-                       case PT_GNU_RELRO:
-                               return 0;
-
-                       default:
-                               break;
-               }
-       }
-
-       // This file does not seem to have PT_GNU_RELRO set
-       file->issues |= PAKFIRE_FILE_NO_RELRO;
-
-       return 0;
-}
-
-static int pakfire_file_check_relro(struct pakfire_file* file) {
-       return pakfire_file_open_elf(file, __pakfire_file_check_relro, NULL);
-}
-
 /*
        RPATH/RUNPATH
 */
@@ -2674,11 +2605,6 @@ int pakfire_file_check(struct pakfire_file* file, int* issues) {
                        if (r)
                                return r;
 
-                       // Check for RELRO
-                       r = pakfire_file_check_relro(file);
-                       if (r)
-                               return r;
-
                        // Check for RUNPATH
                        r = pakfire_file_check_runpath(file);
                        if (r)
index 93821f003f1b51146f70b41e8cf51ae6eb4e5688..1834a795e762498c4caa321a80f7edd0b5a8162d 100644 (file)
@@ -282,6 +282,38 @@ static int pakfire_linter_file_get_elf_section(struct pakfire_linter_file* lfile
        return 1;
 }
 
+static int pakfire_linter_file_elf_dyn_walk(struct pakfire_linter_file* lfile, Elf* elf,
+               int (*callback)(struct pakfire_linter_file* lfile, Elf* elf,
+                       const GElf_Shdr* shdr, const GElf_Dyn* dyn, void* data), void* data) {
+       Elf_Scn* dynamic = NULL;
+       GElf_Shdr shdr;
+       Elf_Data* elf_data = NULL;
+       GElf_Dyn dyn;
+       int r;
+
+       // Find the dynamic linking information
+       r = pakfire_linter_file_get_elf_section(lfile, elf, SHT_DYNAMIC, &dynamic, &shdr, &elf_data);
+       if (r) {
+               DEBUG(lfile->ctx, "%s does not have a dynamic section\n", lfile->path);
+               return 0;
+       }
+
+       // Walk through all entries...
+       for (unsigned int i = 0; ; i++)  {
+               // Fetch the next entry
+               if (!gelf_getdyn(elf_data, i, &dyn))
+                       break;
+
+               // Call the callback
+               r = callback(lfile, elf, &shdr, &dyn, data);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+
 static int pakfire_linter_file_check_pie(struct pakfire_linter_file* lfile) {
        switch (pakfire_linter_file_get_elf_type(lfile)) {
                // Shared Object files are good
@@ -418,6 +450,74 @@ static int pakfire_linter_file_check_execstack(struct pakfire_linter_file* lfile
        return pakfire_linter_file_elf(lfile, __pakfire_linter_file_check_execstack, NULL);
 }
 
+
+static int __pakfire_linter_file_has_bind_now(struct pakfire_linter_file* lfile,
+               Elf* elf, const GElf_Shdr* shdr, const GElf_Dyn* dyn, void* data) {
+       int* has_bind_now = (int*)data;
+
+       switch (dyn->d_tag) {
+               case DT_BIND_NOW:
+                       *has_bind_now = 1;
+                       break;
+
+               case DT_FLAGS:
+                       if (dyn->d_un.d_val & DF_BIND_NOW)
+                               *has_bind_now = 1;
+                       break;
+
+               case DT_FLAGS_1:
+                       if (dyn->d_un.d_val & DF_1_NOW)
+                               *has_bind_now = 1;
+                       break;
+
+               default:
+                       break;
+       }
+
+       return 0;
+}
+
+static int __pakfire_linter_file_check_relro(
+               struct pakfire_linter_file* lfile, Elf* elf, void* data) {
+       int has_bind_now = 0;
+       GElf_Phdr phdr;
+       int r;
+
+       // Check if we have BIND_NOW
+       r = pakfire_linter_file_elf_dyn_walk(lfile, elf,
+               __pakfire_linter_file_has_bind_now, &has_bind_now);
+       if (r)
+               return r;
+
+       // We are not fully RELRO
+       if (!has_bind_now)
+               return pakfire_linter_file_error(lfile, "Is not fully RELRO");
+
+       // Walk through all program headers
+       for (unsigned int i = 0;; i++) {
+               if (!gelf_getphdr(elf, i, &phdr))
+                       break;
+
+               switch (phdr.p_type) {
+                       case PT_GNU_RELRO:
+                               r = pakfire_linter_file_warning(lfile, "Is partially RELRO");
+                               if (r < 0)
+                                       return 0;
+                               break;
+
+                       default:
+                               break;
+               }
+       }
+
+       // This file does not seem to have PT_GNU_RELRO set
+       return pakfire_linter_file_error(lfile, "Is not fully RELRO");
+}
+
+static int pakfire_linter_file_check_relro(struct pakfire_linter_file* lfile) {
+       return pakfire_linter_file_elf(lfile, __pakfire_linter_file_check_relro, NULL);
+}
+
 int pakfire_linter_file_lint(struct pakfire_linter_file* lfile) {
        int r = 0;
 
@@ -449,6 +549,11 @@ int pakfire_linter_file_lint(struct pakfire_linter_file* lfile) {
                r = pakfire_linter_file_check_execstack(lfile);
                if (r < 0)
                        return r;
+
+               // Check RELRO
+               r = pakfire_linter_file_check_relro(lfile);
+               if (r < 0)
+                       return r;
        }
 
        return 0;