From owner-svn-src-all@freebsd.org Mon Dec 10 00:54:19 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 82250130C26A; Mon, 10 Dec 2018 00:54:19 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 21489862BF; Mon, 10 Dec 2018 00:54:19 +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 mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D82C318E53; Mon, 10 Dec 2018 00:54:18 +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 wBA0sIf0032228; Mon, 10 Dec 2018 00:54:18 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id wBA0sI59032226; Mon, 10 Dec 2018 00:54:18 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201812100054.wBA0sI59032226@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Mon, 10 Dec 2018 00:54:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r341772 - stable/12/libexec/rtld-elf X-SVN-Group: stable-12 X-SVN-Commit-Author: kib X-SVN-Commit-Paths: stable/12/libexec/rtld-elf X-SVN-Commit-Revision: 341772 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 21489862BF X-Spamd-Result: default: False [-2.97 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.997,0]; NEURAL_HAM_SHORT(-0.98)[-0.979,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-0.99)[-0.990,0] X-Rspamd-Server: mx1.freebsd.org X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 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, 10 Dec 2018 00:54:19 -0000 Author: kib Date: Mon Dec 10 00:54:18 2018 New Revision: 341772 URL: https://svnweb.freebsd.org/changeset/base/341772 Log: MFC r341441: Some fixes for LD_BIND_NOW + ifuncs. Modified: stable/12/libexec/rtld-elf/rtld.c stable/12/libexec/rtld-elf/rtld.h Directory Properties: stable/12/ (props changed) Modified: stable/12/libexec/rtld-elf/rtld.c ============================================================================== --- stable/12/libexec/rtld-elf/rtld.c Sun Dec 9 22:42:22 2018 (r341771) +++ stable/12/libexec/rtld-elf/rtld.c Mon Dec 10 00:54:18 2018 (r341772) @@ -103,6 +103,7 @@ static void init_pagesizes(Elf_Auxinfo **aux_info); static void init_rtld(caddr_t, Elf_Auxinfo **); static void initlist_add_neededs(Needed_Entry *, Objlist *); static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *); +static int initlist_objects_ifunc(Objlist *, bool, int, RtldLockState *); static void linkmap_add(Obj_Entry *); static void linkmap_delete(Obj_Entry *); static void load_filtees(Obj_Entry *, int flags, RtldLockState *); @@ -111,6 +112,7 @@ static int load_needed_objects(Obj_Entry *, int); static int load_preload_objects(void); static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int); static void map_stacks_exec(RtldLockState *); +static int obj_disable_relro(Obj_Entry *); static int obj_enforce_relro(Obj_Entry *); static Obj_Entry *obj_from_addr(const void *); static void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *); @@ -135,8 +137,6 @@ static int relocate_object(Obj_Entry *obj, bool bind_n static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int, RtldLockState *); static int resolve_object_ifunc(Obj_Entry *, bool, int, RtldLockState *); -static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now, - int flags, RtldLockState *lockstate); static int rtld_dirname(const char *, char *); static int rtld_dirname_abs(const char *, char *); static void *rtld_dlopen(const char *name, int fd, int mode); @@ -713,16 +713,6 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr map_stacks_exec(NULL); - dbg("resolving ifuncs"); - if (resolve_objects_ifunc(obj_main, - ld_bind_now != NULL && *ld_bind_now != '\0', SYMLOOK_EARLY, - NULL) == -1) - rtld_die(); - - dbg("enforcing main obj relro"); - if (obj_enforce_relro(obj_main) == -1) - rtld_die(); - if (!obj_main->crt_no_init) { /* * Make sure we don't call the main program's init and fini @@ -741,6 +731,12 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr pre_init(); wlock_acquire(rtld_bind_lock, &lockstate); + + dbg("resolving ifuncs"); + if (initlist_objects_ifunc(&initlist, ld_bind_now != NULL && + *ld_bind_now != '\0', SYMLOOK_EARLY, &lockstate) == -1) + rtld_die(); + if (obj_main->crt_no_init) preinit_main(); objlist_call_init(&initlist, &lockstate); @@ -753,6 +749,11 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr if (ld_loadfltr || obj->z_loadfltr) load_filtees(obj, 0, &lockstate); } + + dbg("enforcing main obj relro"); + if (obj_enforce_relro(obj_main) == -1) + rtld_die(); + lock_release(rtld_bind_lock, &lockstate); dbg("transferring control to program entry point = %p", obj_main->entry); @@ -2217,9 +2218,7 @@ initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, initlist_add_neededs(obj->needed_aux_filtees, list); /* Add the object to the init list. */ - if (obj->preinit_array != (Elf_Addr)NULL || obj->init != (Elf_Addr)NULL || - obj->init_array != (Elf_Addr)NULL) - objlist_push_tail(list, obj); + objlist_push_tail(list, obj); /* Add the object to the global fini list in the reverse order. */ if ((obj->fini != (Elf_Addr)NULL || obj->fini_array != (Elf_Addr)NULL) @@ -2868,11 +2867,9 @@ relocate_object(Obj_Entry *obj, bool bind_now, Obj_Ent if (reloc_plt(obj) == -1) return (-1); /* Relocate the jump slots if we are doing immediate binding. */ - if (obj->bind_now || bind_now) { - if (reloc_jmpslots(obj, flags, lockstate) == -1 || - resolve_object_ifunc(obj, true, flags, lockstate) == -1) - return (-1); - } + if ((obj->bind_now || bind_now) && reloc_jmpslots(obj, flags, + lockstate) == -1) + return (-1); /* * Process the non-PLT IFUNC relocations. The relocations are @@ -2938,24 +2935,16 @@ static int resolve_object_ifunc(Obj_Entry *obj, bool bind_now, int flags, RtldLockState *lockstate) { + + if (obj->ifuncs_resolved) + return (0); + obj->ifuncs_resolved = true; if (obj->irelative && reloc_iresolve(obj, lockstate) == -1) return (-1); - if ((obj->bind_now || bind_now) && obj->gnu_ifunc && - reloc_gnu_ifunc(obj, flags, lockstate) == -1) - return (-1); - return (0); -} - -static int -resolve_objects_ifunc(Obj_Entry *first, bool bind_now, int flags, - RtldLockState *lockstate) -{ - Obj_Entry *obj; - - for (obj = first; obj != NULL; obj = TAILQ_NEXT(obj, next)) { - if (obj->marker) - continue; - if (resolve_object_ifunc(obj, bind_now, flags, lockstate) == -1) + if ((obj->bind_now || bind_now) && obj->gnu_ifunc) { + if (obj_disable_relro(obj) || + reloc_gnu_ifunc(obj, flags, lockstate) == -1 || + obj_enforce_relro(obj)) return (-1); } return (0); @@ -2966,9 +2955,13 @@ initlist_objects_ifunc(Objlist *list, bool bind_now, i RtldLockState *lockstate) { Objlist_Entry *elm; + Obj_Entry *obj; STAILQ_FOREACH(elm, list, link) { - if (resolve_object_ifunc(elm->obj, bind_now, flags, + obj = elm->obj; + if (obj->marker) + continue; + if (resolve_object_ifunc(obj, bind_now, flags, lockstate) == -1) return (-1); } @@ -5328,17 +5321,31 @@ _rtld_is_dlopened(void *arg) return (res); } -int -obj_enforce_relro(Obj_Entry *obj) +static int +obj_remap_relro(Obj_Entry *obj, int prot) { if (obj->relro_size > 0 && mprotect(obj->relro_page, obj->relro_size, - PROT_READ) == -1) { - _rtld_error("%s: Cannot enforce relro protection: %s", - obj->path, rtld_strerror(errno)); + prot) == -1) { + _rtld_error("%s: Cannot set relro protection to %#x: %s", + obj->path, prot, rtld_strerror(errno)); return (-1); } return (0); +} + +static int +obj_disable_relro(Obj_Entry *obj) +{ + + return (obj_remap_relro(obj, PROT_READ | PROT_WRITE)); +} + +static int +obj_enforce_relro(Obj_Entry *obj) +{ + + return (obj_remap_relro(obj, PROT_READ)); } static void Modified: stable/12/libexec/rtld-elf/rtld.h ============================================================================== --- stable/12/libexec/rtld-elf/rtld.h Sun Dec 9 22:42:22 2018 (r341771) +++ stable/12/libexec/rtld-elf/rtld.h Mon Dec 10 00:54:18 2018 (r341772) @@ -265,6 +265,7 @@ typedef struct Struct_Obj_Entry { bool irelative : 1; /* Object has R_MACHDEP_IRELATIVE relocs */ bool gnu_ifunc : 1; /* Object has references to STT_GNU_IFUNC */ bool non_plt_gnu_ifunc : 1; /* Object has non-plt IFUNC references */ + bool ifuncs_resolved : 1; /* Object ifuncs were already resolved */ bool crt_no_init : 1; /* Object' crt does not call _init/_fini */ bool valid_hash_sysv : 1; /* A valid System V hash hash tag is available */ bool valid_hash_gnu : 1; /* A valid GNU hash tag is available */