From e6de40fa7942abfdc0d3344c93f92883ecef3e67 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 17 Jan 2019 17:36:18 +0000 Subject: [PATCH] Fix handling of rights on stdio streams. - Limit rights on stdio before opening input files. Otherwise, open() may return one of the standard descriptors and we end up limiting rights such that we cannot read from one of the input files. - Use caph_limit_stdio(), which suppresses EBADF, to ensure that we don't emit an error if one of the stdio streams is closed. - Don't bother further limiting rights on stdin when stdin isn't going to be used. Doing so correctly requires checking for a number of edge cases, and it doesn't provide any significant benefit. PR: 234885 Reviewed by: oshogbo MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D18860 --- usr.bin/cmp/cmp.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/usr.bin/cmp/cmp.c b/usr.bin/cmp/cmp.c index b8d5dba14ec4..dcf32a98dcc7 100644 --- a/usr.bin/cmp/cmp.c +++ b/usr.bin/cmp/cmp.c @@ -116,14 +116,16 @@ main(int argc, char *argv[]) if (argc < 2 || argc > 4) usage(); + if (caph_limit_stdio() == -1) + err(ERR_EXIT, "failed to limit stdio"); + /* Backward compatibility -- handle "-" meaning stdin. */ special = 0; if (strcmp(file1 = argv[0], "-") == 0) { special = 1; - fd1 = 0; + fd1 = STDIN_FILENO; file1 = "stdin"; - } - else if ((fd1 = open(file1, oflag, 0)) < 0 && errno != EMLINK) { + } else if ((fd1 = open(file1, oflag, 0)) < 0 && errno != EMLINK) { if (!sflag) err(ERR_EXIT, "%s", file1); else @@ -134,10 +136,9 @@ main(int argc, char *argv[]) errx(ERR_EXIT, "standard input may only be specified once"); special = 1; - fd2 = 0; + fd2 = STDIN_FILENO; file2 = "stdin"; - } - else if ((fd2 = open(file2, oflag, 0)) < 0 && errno != EMLINK) { + } else if ((fd2 = open(file2, oflag, 0)) < 0 && errno != EMLINK) { if (!sflag) err(ERR_EXIT, "%s", file2); else @@ -175,16 +176,6 @@ main(int argc, char *argv[]) if (caph_fcntls_limit(fd2, fcntls) < 0) err(ERR_EXIT, "unable to limit fcntls for %s", file2); - if (!special) { - cap_rights_init(&rights); - if (caph_rights_limit(STDIN_FILENO, &rights) < 0) { - err(ERR_EXIT, "unable to limit stdio"); - } - } - - if (caph_limit_stdout() == -1 || caph_limit_stderr() == -1) - err(ERR_EXIT, "unable to limit stdio"); - caph_cache_catpages(); if (caph_enter() < 0)