From owner-svn-src-all@freebsd.org Tue May 16 19:53:40 2017 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 580C9D70A96; Tue, 16 May 2017 19:53:40 +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 1107A3E9; Tue, 16 May 2017 19:53:40 +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 v4GJrdEr001574; Tue, 16 May 2017 19:53:39 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4GJrdmU001573; Tue, 16 May 2017 19:53:39 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201705161953.v4GJrdmU001573@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Tue, 16 May 2017 19:53:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r318380 - head/libexec/rtld-elf 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.23 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: Tue, 16 May 2017 19:53:40 -0000 Author: kib Date: Tue May 16 19:53:38 2017 New Revision: 318380 URL: https://svnweb.freebsd.org/changeset/base/318380 Log: Pretend that there is some security when executing in direct mode. Do not allow direct exec if we the process is suid. Try to follow Unix permission checks for DACs, ignore ACLs. Reviewed by: emaste Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D10750 Modified: head/libexec/rtld-elf/rtld.c Modified: head/libexec/rtld-elf/rtld.c ============================================================================== --- head/libexec/rtld-elf/rtld.c Tue May 16 19:48:07 2017 (r318379) +++ head/libexec/rtld-elf/rtld.c Tue May 16 19:53:38 2017 (r318380) @@ -345,12 +345,14 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ const Elf_Phdr *phdr; Objlist initlist; RtldLockState lockstate; + struct stat st; Elf_Addr *argcp; char **argv, *argv0, **env, **envp, *kexecpath, *library_path_rpath; caddr_t imgentry; char buf[MAXPATHLEN]; int argc, fd, i, mib[2], phnum; size_t len; + bool dir_enable; /* * On entry, the dynamic linker itself has not been relocated yet. @@ -419,6 +421,11 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ assert(aux_info[AT_PHDR] != NULL); phdr = (const Elf_Phdr *)aux_info[AT_PHDR]->a_un.a_ptr; if (phdr == obj_rtld.phdr) { + if (!trust) { + rtld_printf("Tainted process refusing to run binary %s\n", + argv0); + rtld_die(); + } dbg("opening main program in direct exec mode"); if (argc >= 2) { argv0 = argv[1]; @@ -428,6 +435,37 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_ rtld_strerror(errno)); rtld_die(); } + if (fstat(fd, &st) == -1) { + rtld_printf("Stat %s: %s\n", argv0, + rtld_strerror(errno)); + rtld_die(); + } + + /* + * Rough emulation of the permission checks done by + * execve(2), only Unix DACs are checked, ACLs are + * ignored. Preserve the semantic of disabling owner + * to execute if owner x bit is cleared, even if + * others x bit is enabled. + * mmap(2) does not allow to mmap with PROT_EXEC if + * binary' file comes from noexec mount. We cannot + * set VV_TEXT on the binary. + */ + dir_enable = false; + if (st.st_uid == geteuid()) { + if ((st.st_mode & S_IXUSR) != 0) + dir_enable = true; + } else if (st.st_gid == getegid()) { + if ((st.st_mode & S_IXGRP) != 0) + dir_enable = true; + } else if ((st.st_mode & S_IXOTH) != 0) { + dir_enable = true; + } + if (!dir_enable) { + rtld_printf("No execute permission for binary %s\n", + argv0); + rtld_die(); + } /* * For direct exec mode, argv[0] is the interpreter