if (r < 0)
goto ERROR;
}
+
+ // Has RUNPATH?
+ if (file->issues & PAKFIRE_FILE_HAS_RUNPATH) {
+ r = asprintf(&buffer, "%s [HAS-RUNPATH]", buffer);
+ if (r < 0)
+ goto ERROR;
+ }
}
return buffer;
return type;
}
+static int pakfire_file_elf_dyn_walk(struct pakfire_file* file, Elf* elf,
+ int (*callback)(struct pakfire_file* file, Elf64_Word key, const char* value, void* data),
+ void* data) {
+ Elf_Scn* dynamic = NULL;
+ GElf_Shdr shdr;
+ Elf_Data* elf_data = NULL;
+ int r;
+
+ // Find the dynamic linking information
+ r = pakfire_file_get_elf_section(file, elf, SHT_DYNAMIC, &dynamic, &shdr, &elf_data);
+ if (r) {
+ ERROR(file->pakfire, "%s does not have a dynamic section\n", file->path);
+ return 1;
+ }
+
+ GElf_Dyn dyn;
+ const char* value = NULL;
+
+ // Walk through all entries...
+ for (unsigned int i = 0; ; i++) {
+ // Fetch the next entry
+ if (!gelf_getdyn(elf_data, i, &dyn))
+ break;
+
+ // Fetch the value
+ value = elf_strptr(elf, shdr.sh_link, dyn.d_un.d_val);
+
+ // Call the callback
+ r = callback(file, dyn.d_tag, value, data);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
static int __pakfire_file_check_debuginfo(struct pakfire_file* file, Elf* elf, void* data) {
Elf_Scn* symtab = NULL;
int r;
return pakfire_file_open_elf(file, __pakfire_file_check_partially_relro, NULL);
}
+/*
+ RPATH/RUNPATH
+*/
+static int __pakfire_file_process_runpath(struct pakfire_file* file,
+ Elf64_Word key, const char* value, void* data) {
+ const char* runpath = NULL;
+ char buffer[PATH_MAX];
+ char* p = NULL;
+ int r;
+
+ switch (key) {
+ case DT_RUNPATH:
+ case DT_RPATH:
+ DEBUG(file->pakfire, "%s has a RUNPATH: %s\n", file->path, value);
+
+ // Copy the value into a buffer we can modify
+ r = pakfire_string_set(buffer, value);
+ if (r)
+ return r;
+
+ // Split the value by :
+ runpath = strtok_r(buffer, ":", &p);
+
+ // Iterate over all elements
+ while (runpath) {
+ DEBUG(file->pakfire, "Checking RUNPATH %s\n", runpath);
+
+ // We do not allow any relative RUNPATHs
+ if (pakfire_path_match(runpath, "**/../**")) {
+ file->issues |= PAKFIRE_FILE_HAS_RUNPATH;
+ break;
+ }
+
+ /*
+ We allow some RUNPATHs where some software is loading some
+ modules as shared objects from a private directory in /usr/lib64.
+ */
+ if (!pakfire_path_match(runpath, "/usr/lib64")
+ && !pakfire_path_match(runpath, "/usr/lib64/**")) {
+ file->issues |= PAKFIRE_FILE_HAS_RUNPATH;
+ break;
+ }
+
+ // Move on to the next RUNPATH
+ runpath = strtok_r(NULL, ":", &p);
+ }
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int __pakfire_file_check_runpath(struct pakfire_file* file, Elf* elf, void* data) {
+ return pakfire_file_elf_dyn_walk(file, elf, __pakfire_file_process_runpath, data);
+}
+
+static int pakfire_file_check_runpath(struct pakfire_file* file) {
+ return pakfire_file_open_elf(file, __pakfire_file_check_runpath, NULL);
+}
int pakfire_file_check(struct pakfire_file* file, int* issues) {
int r;
r = pakfire_file_check_relro(file);
if (r)
return r;
+
+ // Check for RUNPATH
+ r = pakfire_file_check_runpath(file);
+ if (r)
+ return r;
}
DONE: