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
This commit is contained in:
Mark Johnston 2019-01-17 17:36:18 +00:00
parent c9cf7cb85b
commit e6de40fa79
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=343117

View File

@ -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)