/* Validate user module based on build-id (if present) */ static int _stp_usermodule_check(struct task_struct *tsk, const char *path_name, unsigned long addr) { struct _stp_module *m = NULL; unsigned long notes_addr; unsigned i, j; unsigned char practice_id_bits[MAXSTRINGLEN]; unsigned long vm_end = 0; #ifdef STP_NO_BUILDID_CHECK return 0; #endif for (i = 0; i < _stp_num_modules; i++) { m = _stp_modules[i]; if (strcmp(path_name, _stp_modules[i]->path) != 0) continue; if (m->build_id_len > 0) { int ret, build_id_len; notes_addr = addr + m->build_id_offset /* + m->module_base */; dbug_sym(1, "build-id validation [%d %s] address=%#lx build_id_offset=%#lx\n", tsk->pid, m->path, addr, m->build_id_offset); if (notes_addr <= addr) { _stp_warn ("build-id address %lx < base %lx\n", notes_addr, addr); continue; } return _stp_build_id_check (m, notes_addr, tsk); } } return 0; }
/* Iterate over _stp_modules, looking for a kernel module of given name. Run build-id checking for it. Return 0 on ok. */ static int _stp_kmodule_check (const char *name) { struct _stp_module *m = NULL; unsigned long notes_addr, base_addr; unsigned i,j; #ifdef STP_NO_BUILDID_CHECK return 0; #endif for (i = 0; i < _stp_num_modules; i++) { m = _stp_modules[i]; if (strcmp (name, m->name)) continue; if (m->build_id_len > 0 && m->notes_sect != 0) { dbug_sym(1, "build-id validation [%s]\n", m->name); /* notes end address */ notes_addr = m->notes_sect + m->build_id_offset; base_addr = m->notes_sect; if (notes_addr <= base_addr) { /* shouldn't happen */ _stp_warn ("build-id address %lx < base %lx\n", notes_addr, base_addr); continue; } return _stp_build_id_check (m, notes_addr, NULL); } /* end checking */ } /* end loop */ return 0; /* name not found */ }
/* Validate all-modules + kernel based on build-id (if present). * The completed case is the following combination: * Debuginfo Module Kernel * X X * has build-id/not unloaded has build-id/not * loaded && (has build-id/not) * * NB: build-id exists only if ld>=2.18 and kernel>= 2.6.23 */ static int _stp_module_check(void) { struct _stp_module *m = NULL; unsigned long notes_addr, base_addr; unsigned i,j; int rc = 0; #ifdef STP_NO_BUILDID_CHECK return 0; #endif for (i = 0; i < _stp_num_modules; i++) { m = _stp_modules[i]; if (m->build_id_len > 0 && m->notes_sect != 0) { dbug_sym(1, "build-id validation [%s]\n", m->name); /* kernel only */ /* skip userspace program */ if (m->name[0] != '/') continue; /* notes end address */ if (!strcmp(m->name, "kernel")) { notes_addr = _stp_kmodule_relocate("kernel", "_stext", m->build_id_offset); base_addr = _stp_kmodule_relocate("kernel", "_stext", 0); } else { notes_addr = m->notes_sect + m->build_id_offset; base_addr = m->notes_sect; } if (notes_addr <= base_addr) { /* shouldn't happen */ _stp_warn ("build-id address %lx <= base %lx\n", notes_addr, base_addr); continue; } rc |= _stp_build_id_check (m, notes_addr, NULL); } /* end checking */ } /* end loop */ return rc; }
/* Validate user module based on build-id (if present) */ static int _stp_usermodule_check(struct task_struct *tsk, const char *path_name, unsigned long addr) { struct _stp_module *m = NULL; unsigned long notes_addr; unsigned i, j; unsigned char practice_id_bits[MAXSTRINGLEN]; unsigned long vm_end = 0; #ifdef STP_NO_BUILDID_CHECK return 0; #endif WARN_ON(!path_name || path_name[0]!='/'); // user-space only for (i = 0; i < _stp_num_modules; i++) { m = _stp_modules[i]; /* PR16406 must be unique userspace name (/-prefixed path); it's also in m->name */ if (strcmp(path_name, m->path) != 0) continue; if (m->build_id_len > 0) { int ret, build_id_len; notes_addr = addr + m->build_id_offset /* + m->module_base */; dbug_sym(1, "build-id validation [%d %s] address=%#lx build_id_offset=%#lx\n", tsk->pid, m->path, addr, m->build_id_offset); if (notes_addr <= addr) { _stp_warn ("build-id address %lx < base %lx\n", notes_addr, addr); continue; } return _stp_build_id_check (m, notes_addr, tsk); } } return 0; /* not found */ }
/* Iterate over _stp_modules, looking for a kernel module of given name. Run build-id checking for it. Return 0 on ok. */ static int _stp_kmodule_check (const char *name) { struct _stp_module *m = NULL; unsigned long notes_addr, base_addr; unsigned i,j; #ifdef STP_NO_BUILDID_CHECK return 0; #endif WARN_ON(!name || name[0]=='/'); // non-userspace only for (i = 0; i < _stp_num_modules; i++) { m = _stp_modules[i]; /* PR16406 must be unique kernel module name (non-/-prefixed path) */ if (strcmp (name, m->name)) continue; if (m->build_id_len > 0 && m->notes_sect != 0) { dbug_sym(1, "build-id validation [%s]\n", m->name); /* notes end address */ notes_addr = m->notes_sect + m->build_id_offset; base_addr = m->notes_sect; if (notes_addr <= base_addr) { /* shouldn't happen */ _stp_warn ("build-id address %lx < base %lx\n", notes_addr, base_addr); continue; } return _stp_build_id_check (m, notes_addr, NULL); } /* end checking */ } /* end loop */ return 0; /* not found */ }