Date: Sat, 4 Mar 2017 20:50:17 +0000 (UTC) From: Baptiste Daroussin <bapt@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r314678 - user/bapt/diff Message-ID: <201703042050.v24KoHDA062712@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bapt Date: Sat Mar 4 20:50:17 2017 New Revision: 314678 URL: https://svnweb.freebsd.org/changeset/base/314678 Log: Capsicumize diff on regular files To allow to work in capsicum mode: - early spawn pr(1) if needed (lflag) - use pdfork instead of fork - use kevent to track the exit of pr(1) as pdwait4 does not exist yet Modified: user/bapt/diff/diffreg.c Modified: user/bapt/diff/diffreg.c ============================================================================== --- user/bapt/diff/diffreg.c Sat Mar 4 20:46:57 2017 (r314677) +++ user/bapt/diff/diffreg.c Sat Mar 4 20:50:17 2017 (r314678) @@ -67,9 +67,14 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/capsicum.h> +#include <sys/procdesc.h> #include <sys/stat.h> +#include <sys/types.h> +#include <sys/event.h> #include <sys/wait.h> +#include <capsicum_helpers.h> #include <ctype.h> #include <err.h> #include <errno.h> @@ -307,7 +312,9 @@ diffreg(char *file1, char *file2, int fl FILE *f1, *f2; int i, rval; int ostdout = -1; - pid_t pid = -1; + int pr_pd, kq; + struct kevent *e; + cap_rights_t rights_ro; f1 = f2 = NULL; rval = D_SAME; @@ -366,26 +373,10 @@ diffreg(char *file1, char *file2, int fl goto closem; } - switch (files_differ(f1, f2, flags)) { - case 0: - goto closem; - case 1: - break; - default: - /* error */ - status |= 2; - goto closem; - } - - if ((flags & D_FORCEASCII) == 0 && - (!asciifile(f1) || !asciifile(f2))) { - rval = D_BINARY; - status |= 1; - goto closem; - } if (lflag) { /* redirect stdout to pr */ int pfd[2]; + pid_t pid; char *header; xasprintf(&header, "%s %s %s", diffargs, file1, file2); @@ -393,7 +384,7 @@ diffreg(char *file1, char *file2, int fl fflush(stdout); rewind(stdout); pipe(pfd); - switch ((pid = fork())) { + switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { case -1: status |= 2; free(header); @@ -408,6 +399,7 @@ diffreg(char *file1, char *file2, int fl execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); _exit(127); default: + /* parent */ if (pfd[1] != STDOUT_FILENO) { ostdout = dup(STDOUT_FILENO); @@ -417,8 +409,46 @@ diffreg(char *file1, char *file2, int fl close(pfd[0]); rewind(stdout); free(header); + kq = kqueue(); + if (kq == -1) + err(2, "kqueue"); + e = xmalloc(sizeof(struct kevent)); + EV_SET(e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, + NULL); + if (kevent(kq, e, 1, NULL, 0, NULL) == -1) + err(2, "kevent"); } } + + cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); + if (cap_rights_limit(fileno(f1), &rights_ro) < 0) + err(2, "unable to limit rights on: %s", file1); + if (cap_rights_limit(fileno(f2), &rights_ro) < 0) + err(2, "unable to limit rights on: %s", file2); + if (caph_limit_stdio() == -1) + err(2, "unable to limit stdio"); + + caph_cache_catpages(); + if (cap_enter() < 0 && errno != ENOSYS) + err(2, "unable to enter capability mode"); + + switch (files_differ(f1, f2, flags)) { + case 0: + goto closem; + case 1: + break; + default: + /* error */ + status |= 2; + goto closem; + } + + if ((flags & D_FORCEASCII) == 0 && + (!asciifile(f1) || !asciifile(f2))) { + rval = D_BINARY; + status |= 1; + goto closem; + } prepare(0, f1, stb1.st_size, flags); prepare(1, f2, stb2.st_size, flags); @@ -452,19 +482,25 @@ diffreg(char *file1, char *file2, int fl check(f1, f2, flags); output(file1, f1, file2, f2, flags); if (ostdout != -1) { + /* close the pipe to pr and restore stdout */ int wstatus; - /* close the pipe to pr and restore stdout */ fflush(stdout); - rewind(stdout); if (ostdout != STDOUT_FILENO) { close(STDOUT_FILENO); dup2(ostdout, STDOUT_FILENO); close(ostdout); } - waitpid(pid, &wstatus, 0); + if (kevent(kq, NULL, 0, e, 1, NULL) == -1) + err(2, "kevent"); + wstatus = e[0].data; + if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) + errx(2, "pr exited abnormally"); + else if (WIFSIGNALED(wstatus)) + errx(2, "pr killed by signal %d", + WTERMSIG(wstatus)); } - + closem: if (anychange) { status |= 1;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703042050.v24KoHDA062712>