From owner-svn-src-all@freebsd.org Thu Aug 25 15:08:34 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 C8BBEBC6291; Thu, 25 Aug 2016 15:08:34 +0000 (UTC) (envelope-from allanjude@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 8DBF515EB; Thu, 25 Aug 2016 15:08:34 +0000 (UTC) (envelope-from allanjude@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u7PF8XSK021580; Thu, 25 Aug 2016 15:08:33 GMT (envelope-from allanjude@FreeBSD.org) Received: (from allanjude@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u7PF8Xj6021579; Thu, 25 Aug 2016 15:08:33 GMT (envelope-from allanjude@FreeBSD.org) Message-Id: <201608251508.u7PF8Xj6021579@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: allanjude set sender to allanjude@FreeBSD.org using -f From: Allan Jude Date: Thu, 25 Aug 2016 15:08:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r304807 - head/usr.bin/bsdiff/bspatch 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.22 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: Thu, 25 Aug 2016 15:08:34 -0000 Author: allanjude Date: Thu Aug 25 15:08:33 2016 New Revision: 304807 URL: https://svnweb.freebsd.org/changeset/base/304807 Log: Capsicumize bspatch Move all of the fopen() and open() calls to the top of main() Restrict each FD to least privilege (read/seek only, write only, etc) cap_enter(), and make all except the output FD read/seek only. Reviewed by: emaste, ed, oshogbo, delphij Approved by: so MFC after: 3 days Relnotes: yes Sponsored by: ScaleEngine Inc. Differential Revision: https://reviews.freebsd.org/D7358 Modified: head/usr.bin/bsdiff/bspatch/bspatch.c Modified: head/usr.bin/bsdiff/bspatch/bspatch.c ============================================================================== --- head/usr.bin/bsdiff/bspatch/bspatch.c Thu Aug 25 14:42:29 2016 (r304806) +++ head/usr.bin/bsdiff/bspatch/bspatch.c Thu Aug 25 15:08:33 2016 (r304807) @@ -27,8 +27,20 @@ #include __FBSDID("$FreeBSD$"); +#if defined(__FreeBSD__) +#include +#if __FreeBSD_version >= 1100014 +#include +#define HAVE_CAPSICUM +#elif __FreeBSD_version >= 1000000 +#include +#define HAVE_CAPSICUM +#endif +#endif + #include #include +#include #include #include #include @@ -80,6 +92,9 @@ int main(int argc, char *argv[]) off_t ctrl[3]; off_t lenread; off_t i; +#ifdef HAVE_CAPSICUM + cap_rights_t rights_ro, rights_wr; +#endif if (argc != 4) usage(); @@ -87,6 +102,43 @@ int main(int argc, char *argv[]) /* Open patch file */ if ((f = fopen(argv[3], "rb")) == NULL) err(1, "fopen(%s)", argv[3]); + /* Open patch file for control block */ + if ((cpf = fopen(argv[3], "rb")) == NULL) + err(1, "fopen(%s)", argv[3]); + /* open patch file for diff block */ + if ((dpf = fopen(argv[3], "rb")) == NULL) + err(1, "fopen(%s)", argv[3]); + /* open patch file for extra block */ + if ((epf = fopen(argv[3], "rb")) == NULL) + err(1, "fopen(%s)", argv[3]); + /* open oldfile */ + if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0) + err(1, "open(%s)", argv[1]); + /* open newfile */ + if ((newfd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, + 0666)) < 0) + err(1, "open(%s)", argv[2]); + +#ifdef HAVE_CAPSICUM + if (cap_enter() < 0) { + /* Failed to sandbox, fatal if CAPABILITY_MODE enabled */ + if (errno != ENOSYS) + err(1, "failed to enter security sandbox"); + } else { + /* Capsicum Available */ + cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); + cap_rights_init(&rights_wr, CAP_WRITE); + + if (cap_rights_limit(fileno(f), &rights_ro) < 0 || + cap_rights_limit(fileno(cpf), &rights_ro) < 0 || + cap_rights_limit(fileno(dpf), &rights_ro) < 0 || + cap_rights_limit(fileno(epf), &rights_ro) < 0 || + cap_rights_limit(oldfd, &rights_ro) < 0 || + cap_rights_limit(newfd, &rights_wr) < 0) + err(1, "cap_rights_limit() failed, could not restrict" + " capabilities"); + } +#endif /* File format: @@ -123,31 +175,22 @@ int main(int argc, char *argv[]) /* Close patch file and re-open it via libbzip2 at the right places */ if (fclose(f)) err(1, "fclose(%s)", argv[3]); - if ((cpf = fopen(argv[3], "rb")) == NULL) - err(1, "fopen(%s)", argv[3]); if (fseeko(cpf, 32, SEEK_SET)) err(1, "fseeko(%s, %lld)", argv[3], (long long)32); if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); - if ((dpf = fopen(argv[3], "rb")) == NULL) - err(1, "fopen(%s)", argv[3]); if (fseeko(dpf, 32 + bzctrllen, SEEK_SET)) err(1, "fseeko(%s, %lld)", argv[3], (long long)(32 + bzctrllen)); if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); - if ((epf = fopen(argv[3], "rb")) == NULL) - err(1, "fopen(%s)", argv[3]); if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET)) err(1, "fseeko(%s, %lld)", argv[3], (long long)(32 + bzctrllen + bzdatalen)); if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); - oldfd = open(argv[1], O_RDONLY | O_BINARY, 0); - if (oldfd < 0) - err(1, "%s", argv[1]); if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 || (old = malloc(oldsize+1)) == NULL || lseek(oldfd, 0, SEEK_SET) != 0 || @@ -215,9 +258,6 @@ int main(int argc, char *argv[]) err(1, "fclose(%s)", argv[3]); /* Write the new file */ - newfd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666); - if (newfd < 0) - err(1, "%s", argv[2]); if (write(newfd, new, newsize) != newsize || close(newfd) == -1) err(1, "%s", argv[2]);