return pakfire_elf_foreach_section(self, SHT_NOTE, pakfire_elf_check_cf_protection);
}
+static int pakfire_elf_check_runpath(struct pakfire_elf* self,
+ const GElf_Shdr* shdr, const GElf_Dyn* dyn, void* data) {
+ const char* runpath = NULL;
+ const char* value = NULL;
+ char buffer[PATH_MAX];
+ char* p = NULL;
+ int r;
+
+ // The result
+ char*** runpaths = data;
+
+ switch (dyn->d_tag) {
+ case DT_RUNPATH:
+ case DT_RPATH:
+ // Fetch the value
+ value = elf_strptr(self->elf, shdr->sh_link, dyn->d_un.d_val);
+ if (!value)
+ return 1;
+
+ DEBUG(self->ctx, "%s has a RUNPATH: %s\n", self->path, value);
+
+ // Copy the value into a buffer we can modify
+ r = pakfire_string_set(buffer, value);
+ if (r < 0)
+ goto ERROR;
+
+ // Split the value by :
+ runpath = strtok_r(buffer, ":", &p);
+
+ // Iterate over all elements
+ while (runpath) {
+ r = pakfire_strings_append(runpaths, runpath);
+ if (r < 0)
+ goto ERROR;
+
+ // Move on to the next RUNPATH
+ runpath = strtok_r(NULL, ":", &p);
+ }
+
+ default:
+ break;
+ }
+
+ return 0;
+
+ERROR:
+ if (*runpaths) {
+ pakfire_strings_free(*runpaths);
+ *runpaths = NULL;
+ }
+
+ return r;
+}
+
+int pakfire_elf_has_runpaths(struct pakfire_elf* self, char*** runpaths) {
+ return pakfire_elf_dyn_walk(self, pakfire_elf_check_runpath, runpaths);
+}
+
int pakfire_elf_is_stripped(struct pakfire_elf* self) {
Elf_Scn* symtab = NULL;
return 0;
}
-static int pakfire_linter_file_get_elf_section(struct pakfire_linter_file* lfile,
- const Elf64_Word type, Elf_Scn** section, GElf_Shdr* header, Elf_Data** data) {
- Elf_Scn* s = NULL;
- GElf_Shdr shdr;
-
- // Walk through all sections
- for (;;) {
- s = elf_nextscn(lfile->elf, s);
- if (!s)
- break;
-
- // Fetch the section header
- gelf_getshdr(s, &shdr);
-
- // Return any matching sections
- if (shdr.sh_type == type) {
- *section = s;
-
- // Send header if requested
- if (header)
- gelf_getshdr(s, header);
-
- // Send data if requested
- if (data)
- *data = elf_getdata(s, NULL);
-
- return 0;
- }
- }
-
- // No section found
- return 1;
-}
-
-static int pakfire_linter_file_elf_dyn_walk(struct pakfire_linter_file* lfile,
- int (*callback)(struct pakfire_linter_file* lfile,
- 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, 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, &shdr, &dyn, data);
- if (r)
- return r;
- }
-
- return 0;
-}
-
static int pakfire_linter_file_check_pie(struct pakfire_linter_file* lfile) {
if (!pakfire_elf_is_pie(lfile->_elf))
return pakfire_linter_file_error(lfile, "Missing PIE");
return pakfire_linter_file_error(lfile, "Is not RELRO");
}
-/*
- RPATH/RUNPATH
-*/
-static int __pakfire_linter_file_process_runpath(struct pakfire_linter_file* lfile,
- const GElf_Shdr* shdr, const GElf_Dyn* dyn, void* data) {
- const char* value = NULL;
- const char* runpath = NULL;
- char buffer[PATH_MAX];
- char* p = NULL;
+static int pakfire_linter_file_check_runpath(struct pakfire_linter_file* lfile) {
+ char** runpaths = NULL;
int r;
- switch (dyn->d_tag) {
- case DT_RUNPATH:
- case DT_RPATH:
- // Fetch the value
- value = elf_strptr(lfile->elf, shdr->sh_link, dyn->d_un.d_val);
- if (!value)
- return 1;
-
- DEBUG(lfile->ctx, "%s has a RUNPATH: %s\n", lfile->path, value);
-
- // Copy the value into a buffer we can modify
- r = pakfire_string_set(buffer, value);
- if (r < 0)
- return r;
-
- // Split the value by :
- runpath = strtok_r(buffer, ":", &p);
-
- // Iterate over all elements
- while (runpath) {
- DEBUG(lfile->ctx, "Checking RUNPATH %s\n", runpath);
-
- // We do not allow any relative RUNPATHs
- if (pakfire_path_match(runpath, "**/../**"))
- goto RUNPATH_DENIED;
-
- // We allow /usr/lib64 as libtool seems to link it in quite a lot
- if (pakfire_path_match("/usr/lib64", runpath))
- goto RUNPATH_PERMITTED;
+ // Fetch any runpaths
+ r = pakfire_elf_has_runpaths(lfile->_elf, &runpaths);
+ if (r < 0)
+ goto ERROR;
- // We allow any subdirectories of /usr/lib64
- if (pakfire_path_match( "/usr/lib64/**", runpath))
- goto RUNPATH_PERMITTED;
+ // Report any invalid runpaths
+ if (runpaths) {
+ for (char** runpath = runpaths; *runpath; runpath++) {
+ DEBUG(lfile->ctx, "Checking RUNPATH %s\n", *runpath);
-RUNPATH_DENIED:
- // If we make it here, this check has failed
- r = pakfire_linter_file_error(lfile, "Has illegal RPATH/RUNPATH %s", runpath);
- if (r < 0)
- return r;
+ // We allow /usr/lib64 as libtool seems to link it in quite a lot
+ if (pakfire_path_match("/usr/lib64", *runpath))
+ continue;
- break;
+ // We allow any subdirectories of /usr/lib64
+ if (pakfire_path_match( "/usr/lib64/**", *runpath))
+ continue;
-RUNPATH_PERMITTED:
- // Move on to the next RUNPATH
- runpath = strtok_r(NULL, ":", &p);
- }
-
- default:
- break;
+ // This seems to be an illegal runpath
+ r = pakfire_linter_file_error(lfile, "Has illegal RPATH/RUNPATH %s", *runpath);
+ if (r < 0)
+ goto ERROR;
+ }
}
- return 0;
-}
+ERROR:
+ if (runpaths)
+ pakfire_strings_free(runpaths);
-static int pakfire_linter_file_check_runpath(struct pakfire_linter_file* lfile) {
- return pakfire_linter_file_elf_dyn_walk(
- lfile, __pakfire_linter_file_process_runpath, NULL);
+ return r;
}
static int pakfire_linter_file_check_cf_protection(struct pakfire_linter_file* lfile) {