return 1;
}
+typedef int (*pakfire_elf_dyn_walk_callback)
+ (struct pakfire_elf* self, const GElf_Shdr* shdr, const GElf_Dyn* dyn, void* data);
+
+static int pakfire_elf_dyn_walk(struct pakfire_elf* self,
+ pakfire_elf_dyn_walk_callback callback, 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_elf_get_section(self, SHT_DYNAMIC, &dynamic, &shdr, &elf_data);
+ if (r) {
+ DEBUG(self->ctx, "%s does not have a dynamic section\n", self->path);
+ return r;
+ }
+
+ // 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(self, &shdr, &dyn, data);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
int pakfire_elf_is_pie(struct pakfire_elf* self) {
switch (pakfire_elf_type(self)) {
// Shared Object files are good
return 0;
}
+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) {
+ case DT_BIND_NOW:
+ return 1;
+ break;
+
+ case DT_FLAGS:
+ if (dyn->d_un.d_val & DF_BIND_NOW)
+ return 1;
+ break;
+
+ case DT_FLAGS_1:
+ if (dyn->d_un.d_val & DF_1_NOW)
+ return 1;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int pakfire_elf_is_fully_relro(struct pakfire_elf* self) {
+ return pakfire_elf_dyn_walk(self, pakfire_elf_has_bind_now, NULL);
+}
+
+int pakfire_elf_is_partially_relro(struct pakfire_elf* self) {
+ GElf_Phdr phdr;
+
+ // Walk through all program headers
+ for (unsigned int i = 0;; i++) {
+ if (!gelf_getphdr(self->elf, i, &phdr))
+ break;
+
+ switch (phdr.p_type) {
+ case PT_GNU_RELRO:
+ return 1;
+
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
int pakfire_elf_is_stripped(struct pakfire_elf* self) {
Elf_Scn* symtab = NULL;
return 0;
}
-static int __pakfire_linter_file_has_bind_now(struct pakfire_linter_file* lfile,
- 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) {
- int has_bind_now = 0;
- GElf_Phdr phdr;
- int r;
-
- // Check if we have BIND_NOW
- r = pakfire_linter_file_elf_dyn_walk(lfile,
- __pakfire_linter_file_has_bind_now, &has_bind_now);
- if (r)
- return r;
-
- // We are fully RELRO
- if (has_bind_now)
+ // If the file is fully RELRO, everything is good
+ if (pakfire_elf_is_fully_relro(lfile->_elf))
return 0;
- // Walk through all program headers
- for (unsigned int i = 0;; i++) {
- if (!gelf_getphdr(lfile->elf, i, &phdr))
- break;
-
- switch (phdr.p_type) {
- case PT_GNU_RELRO:
- return pakfire_linter_file_warning(lfile, "Is partially RELRO");
-
- default:
- break;
- }
- }
+ // Show a warning if the file is only partially RELRO
+ else if (pakfire_elf_is_partially_relro(lfile->_elf))
+ return pakfire_linter_file_warning(lfile, "Is partially RELRO");
- // This file does not seem to have PT_GNU_RELRO set
+ // Return an error if this file is not RELRO at all
return pakfire_linter_file_error(lfile, "Is not RELRO");
}