svn commit: r314678 - user/bapt/diff
Baptiste Daroussin
bapt at FreeBSD.org
Sat Mar 4 20:50:18 UTC 2017
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;
More information about the svn-src-user
mailing list