Index: usr.bin/cmp/cmp.c =================================================================== --- usr.bin/cmp/cmp.c +++ usr.bin/cmp/cmp.c @@ -116,14 +116,16 @@ 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 @@ 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 @@ -162,6 +163,14 @@ exit(ERR_EXIT); } + /* We can further limit rights on stdin if we know it won't be used. */ + if (!special && fd1 != STDIN_FILENO && fd2 != STDIN_FILENO && + fcntl(STDIN_FILENO, F_GETFL) == 0) { + cap_rights_init(&rights); + if (caph_rights_limit(STDIN_FILENO, &rights) < 0) + err(ERR_EXIT, "unable to limit stdio"); + } + cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_MMAP_R); if (caph_rights_limit(fd1, &rights) < 0) err(ERR_EXIT, "unable to limit rights for %s", file1); @@ -175,16 +184,6 @@ 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)