From owner-svn-src-all@freebsd.org Mon Mar 7 18:44:08 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4891EAC3697; Mon, 7 Mar 2016 18:44:08 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0BDB5F85; Mon, 7 Mar 2016 18:44:07 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u27Ii7Dp026876; Mon, 7 Mar 2016 18:44:07 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u27Ii7Ip026875; Mon, 7 Mar 2016 18:44:07 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201603071844.u27Ii7Ip026875@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Mon, 7 Mar 2016 18:44:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r296467 - head/sys/kern X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Mar 2016 18:44:08 -0000 Author: kib Date: Mon Mar 7 18:44:06 2016 New Revision: 296467 URL: https://svnweb.freebsd.org/changeset/base/296467 Log: Convert all panics from the link_elf_obj kernel linker for object files format into printfs and errors to caller. Some leaks of resources are there, but the same leaks are present in other error pathes. With the change, the kernel at least boots even when module with unexpected or corrupted ELF structure is preloaded. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Modified: head/sys/kern/link_elf_obj.c Modified: head/sys/kern/link_elf_obj.c ============================================================================== --- head/sys/kern/link_elf_obj.c Mon Mar 7 18:32:12 2016 (r296466) +++ head/sys/kern/link_elf_obj.c Mon Mar 7 18:44:06 2016 (r296467) @@ -140,7 +140,7 @@ static int link_elf_each_function_name(l static int link_elf_each_function_nameval(linker_file_t, linker_function_nameval_callback_t, void *); -static void link_elf_reloc_local(linker_file_t); +static int link_elf_reloc_local(linker_file_t); static long link_elf_symtab_get(linker_file_t, const Elf_Sym **); static long link_elf_strtab_get(linker_file_t, caddr_t *); @@ -405,15 +405,26 @@ link_elf_link_preload(linker_class_t cls break; } } - if (pb != ef->nprogtab) - panic("lost progbits"); - if (rl != ef->nreltab) - panic("lost reltab"); - if (ra != ef->nrelatab) - panic("lost relatab"); + if (pb != ef->nprogtab) { + printf("%s: lost progbits\n", filename); + error = ENOEXEC; + goto out; + } + if (rl != ef->nreltab) { + printf("%s: lost reltab\n", filename); + error = ENOEXEC; + goto out; + } + if (ra != ef->nrelatab) { + printf("%s: lost relatab\n", filename); + error = ENOEXEC; + goto out; + } /* Local intra-module relocations */ - link_elf_reloc_local(lf); + error = link_elf_reloc_local(lf); + if (error != 0) + goto out; *result = lf; return (0); @@ -634,8 +645,11 @@ link_elf_load_file(linker_class_t cls, c ef->relatab = malloc(ef->nrelatab * sizeof(*ef->relatab), M_LINKER, M_WAITOK | M_ZERO); - if (symtabindex == -1) - panic("lost symbol table index"); + if (symtabindex == -1) { + link_elf_error(filename, "lost symbol table index"); + error = ENOEXEC; + goto out; + } /* Allocate space for and load the symbol table */ ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK); @@ -650,8 +664,11 @@ link_elf_load_file(linker_class_t cls, c goto out; } - if (symstrindex == -1) - panic("lost symbol string index"); + if (symstrindex == -1) { + link_elf_error(filename, "lost symbol string index"); + error = ENOEXEC; + goto out; + } /* Allocate space for and load the symbol strings */ ef->ddbstrcnt = shdr[symstrindex].sh_size; ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK); @@ -884,19 +901,35 @@ link_elf_load_file(linker_class_t cls, c break; } } - if (pb != ef->nprogtab) - panic("lost progbits"); - if (rl != ef->nreltab) - panic("lost reltab"); - if (ra != ef->nrelatab) - panic("lost relatab"); - if (mapbase != (vm_offset_t)ef->address + mapsize) - panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n", + if (pb != ef->nprogtab) { + link_elf_error(filename, "lost progbits"); + error = ENOEXEC; + goto out; + } + if (rl != ef->nreltab) { + link_elf_error(filename, "lost reltab"); + error = ENOEXEC; + goto out; + } + if (ra != ef->nrelatab) { + link_elf_error(filename, "lost relatab"); + error = ENOEXEC; + goto out; + } + if (mapbase != (vm_offset_t)ef->address + mapsize) { + printf( + "%s: mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n", + filename != NULL ? filename : "", (u_long)mapbase, ef->address, (u_long)mapsize, (u_long)(vm_offset_t)ef->address + mapsize); + error = ENOMEM; + goto out; + } /* Local intra-module relocations */ - link_elf_reloc_local(lf); + error = link_elf_reloc_local(lf); + if (error != 0) + goto out; /* Pull in dependencies */ VOP_UNLOCK(nd.ni_vp, 0); @@ -1034,12 +1067,16 @@ relocate_file(elf_file_t ef) /* Perform relocations without addend if there are any: */ for (i = 0; i < ef->nreltab; i++) { rel = ef->reltab[i].rel; - if (rel == NULL) - panic("lost a reltab!"); + if (rel == NULL) { + link_elf_error(ef->lf.filename, "lost a reltab!"); + return (ENOEXEC); + } rellim = rel + ef->reltab[i].nrel; base = findbase(ef, ef->reltab[i].sec); - if (base == 0) - panic("lost base for reltab"); + if (base == 0) { + link_elf_error(ef->lf.filename, "lost base for reltab"); + return (ENOEXEC); + } for ( ; rel < rellim; rel++) { symidx = ELF_R_SYM(rel->r_info); if (symidx >= ef->ddbsymcnt) @@ -1053,7 +1090,7 @@ relocate_file(elf_file_t ef) symname = symbol_name(ef, rel->r_info); printf("link_elf_obj: symbol %s undefined\n", symname); - return ENOENT; + return (ENOENT); } } } @@ -1061,12 +1098,17 @@ relocate_file(elf_file_t ef) /* Perform relocations with addend if there are any: */ for (i = 0; i < ef->nrelatab; i++) { rela = ef->relatab[i].rela; - if (rela == NULL) - panic("lost a relatab!"); + if (rela == NULL) { + link_elf_error(ef->lf.filename, "lost a relatab!"); + return (ENOEXEC); + } relalim = rela + ef->relatab[i].nrela; base = findbase(ef, ef->relatab[i].sec); - if (base == 0) - panic("lost base for relatab"); + if (base == 0) { + link_elf_error(ef->lf.filename, + "lost base for relatab"); + return (ENOEXEC); + } for ( ; rela < relalim; rela++) { symidx = ELF_R_SYM(rela->r_info); if (symidx >= ef->ddbsymcnt) @@ -1080,7 +1122,7 @@ relocate_file(elf_file_t ef) symname = symbol_name(ef, rela->r_info); printf("link_elf_obj: symbol %s undefined\n", symname); - return ENOENT; + return (ENOENT); } } } @@ -1092,7 +1134,7 @@ relocate_file(elf_file_t ef) */ elf_obj_cleanup_globals_cache(ef); - return 0; + return (0); } static int @@ -1375,7 +1417,7 @@ link_elf_fix_link_set(elf_file_t ef) } } -static void +static int link_elf_reloc_local(linker_file_t lf) { elf_file_t ef = (elf_file_t)lf; @@ -1393,12 +1435,16 @@ link_elf_reloc_local(linker_file_t lf) /* Perform relocations without addend if there are any: */ for (i = 0; i < ef->nreltab; i++) { rel = ef->reltab[i].rel; - if (rel == NULL) - panic("lost a reltab!"); + if (rel == NULL) { + link_elf_error(ef->lf.filename, "lost a reltab"); + return (ENOEXEC); + } rellim = rel + ef->reltab[i].nrel; base = findbase(ef, ef->reltab[i].sec); - if (base == 0) - panic("lost base for reltab"); + if (base == 0) { + link_elf_error(ef->lf.filename, "lost base for reltab"); + return (ENOEXEC); + } for ( ; rel < rellim; rel++) { symidx = ELF_R_SYM(rel->r_info); if (symidx >= ef->ddbsymcnt) @@ -1415,12 +1461,16 @@ link_elf_reloc_local(linker_file_t lf) /* Perform relocations with addend if there are any: */ for (i = 0; i < ef->nrelatab; i++) { rela = ef->relatab[i].rela; - if (rela == NULL) - panic("lost a relatab!"); + if (rela == NULL) { + link_elf_error(ef->lf.filename, "lost a relatab!"); + return (ENOEXEC); + } relalim = rela + ef->relatab[i].nrela; base = findbase(ef, ef->relatab[i].sec); - if (base == 0) - panic("lost base for relatab"); + if (base == 0) { + link_elf_error(ef->lf.filename, "lost base for reltab"); + return (ENOEXEC); + } for ( ; rela < relalim; rela++) { symidx = ELF_R_SYM(rela->r_info); if (symidx >= ef->ddbsymcnt) @@ -1433,6 +1483,7 @@ link_elf_reloc_local(linker_file_t lf) elf_obj_lookup); } } + return (0); } static long