Created
February 18, 2016 19:37
-
-
Save brynet/803e8ebf83aa128433f5 to your computer and use it in GitHub Desktop.
pledge(2) for fdm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/child.c b/child.c | |
index 70b915e..0c3b33b 100644 | |
--- a/child.c | |
+++ b/child.c | |
@@ -129,6 +129,21 @@ child_start(struct children *children, uid_t uid, gid_t gid, | |
if (geteuid() == 0) | |
dropto(uid, gid); | |
+#ifdef HAVE_PLEDGE | |
+ struct child_fetch_data *cfd = child->data; | |
+ if (!cfd->needs_exec && cfd->op == FDMOP_FETCH) { | |
+ /* Revokes "proc" promise, i.e: fork/kill */ | |
+ if (pledge("stdio rpath wpath cpath fattr flock getpw inet dns", NULL) == -1) { | |
+ fatal("pledge"); | |
+ } | |
+ } else if (cfd->op == FDMOP_POLL) { | |
+ /* Revokes "cpath proc" promises */ | |
+ if (pledge("stdio rpath tmppath inet dns", NULL) == -1) { | |
+ fatal("pledge"); | |
+ } | |
+ } | |
+#endif | |
+ | |
io = io_create(fds[1], NULL, IO_LF); | |
n = start(child, io); | |
io_close(io); | |
diff --git a/configure.ac b/configure.ac | |
index 5793c2d..5ea9e9f 100644 | |
--- a/configure.ac | |
+++ b/configure.ac | |
@@ -102,6 +102,11 @@ if test "x$found_libssl" = xno; then | |
AC_MSG_ERROR("libssl not found") | |
fi | |
+AC_CHECK_FUNC(pledge, found_pledge=yes, found_pledge=no) | |
+if test "x$found_pledge" = xyes; then | |
+ AC_DEFINE(HAVE_PLEDGE) | |
+fi | |
+ | |
AC_CHECK_DECL(strlcpy, found_strlcpy=yes, found_strlcpy=no) | |
if test "x$found_strlcpy" = xyes; then | |
AC_DEFINE(HAVE_STRLCPY) | |
diff --git a/fdm.c b/fdm.c | |
index cbe44a2..ea3731b 100644 | |
--- a/fdm.c | |
+++ b/fdm.c | |
@@ -732,6 +732,32 @@ retry: | |
goto out; | |
} | |
+#ifdef HAVE_PLEDGE | |
+ if (conf.needs_exec && op == FDMOP_FETCH) { | |
+ log_debug2("pledge fetch exec"); | |
+ if (pledge("stdio rpath wpath cpath fattr flock getpw inet dns proc exec", NULL) == -1) { | |
+ log_warnx("pledge"); | |
+ exit(1); | |
+ } | |
+ } else if (!conf.needs_exec && op == FDMOP_FETCH) { | |
+ log_debug2("pledge fetch noexec"); | |
+ if (pledge("stdio rpath wpath cpath fattr flock getpw inet dns proc", NULL) == -1) { | |
+ log_warnx("pledge"); | |
+ exit(1); | |
+ } | |
+ } else if (op == FDMOP_POLL) { | |
+ /* | |
+ * The "tmppath" promise is for shm cache, covered | |
+ * above by "wpath cpath". | |
+ */ | |
+ log_debug2("pledge poll"); | |
+ if (pledge("stdio rpath cpath tmppath inet dns proc", NULL) == -1) { | |
+ log_warnx("pledge"); | |
+ exit(1); | |
+ } | |
+ } | |
+#endif | |
+ | |
/* Initialise the child process arrays. */ | |
ARRAY_INIT(&children); | |
ARRAY_INIT(&dead_children); | |
@@ -761,6 +787,7 @@ retry: | |
cfd = xmalloc(sizeof *cfd); | |
cfd->account = a; | |
cfd->op = op; | |
+ cfd->needs_exec = conf.needs_exec; | |
cfd->children = &children; | |
child = child_start(&children, | |
conf.child_uid, conf.child_gid, | |
diff --git a/fdm.h b/fdm.h | |
index 7702e4f..69ead0c 100644 | |
--- a/fdm.h | |
+++ b/fdm.h | |
@@ -453,6 +453,7 @@ ARRAY_DECL(children, struct child *); | |
struct child_fetch_data { | |
struct account *account; | |
enum fdmop op; | |
+ int needs_exec; | |
struct children *children; | |
}; | |
@@ -622,6 +623,7 @@ struct conf { | |
u_int purge_after; | |
enum decision impl_act; | |
int max_accts; | |
+ int needs_exec; | |
char *lock_file; | |
int lock_wait; | |
diff --git a/parse.y b/parse.y | |
index c837be5..76cf292 100644 | |
--- a/parse.y | |
+++ b/parse.y | |
@@ -1109,6 +1109,7 @@ actitem: execpipe strv | |
if (*$2 == '\0') | |
yyerror("invalid command"); | |
+ conf.needs_exec = 1; | |
$$ = xcalloc(1, sizeof *$$); | |
$$->deliver = &deliver_pipe; | |
@@ -1125,6 +1126,7 @@ actitem: execpipe strv | |
if (*$2 == '\0') | |
yyerror("invalid command"); | |
+ conf.needs_exec = 1; | |
$$ = xcalloc(1, sizeof *$$); | |
$$->deliver = &deliver_rewrite; | |
@@ -1601,6 +1603,7 @@ expritem: not TOKALL | |
if (*$3 == '\0' || ($3[0] == '|' && $3[1] == '\0')) | |
yyerror("invalid command"); | |
+ conf.needs_exec = 1; | |
if ($7 == -1 && $9.str == NULL) | |
yyerror("return code or regexp must be specified"); | |
@@ -2246,6 +2249,7 @@ fetchtype: poptype server userpassnetrc poponly apop verify uidl tls1 starttls | |
data->pipecmd = $3; | |
if (data->pipecmd == NULL || *data->pipecmd == '\0') | |
yyerror("invalid pipe command"); | |
+ conf.needs_exec = 1; | |
data->apop = $6; | |
data->path = $5.path; | |
data->only = $5.only; | |
@@ -2305,6 +2309,7 @@ fetchtype: poptype server userpassnetrc poponly apop verify uidl tls1 starttls | |
data->pipecmd = $3; | |
if (data->pipecmd == NULL || *data->pipecmd == '\0') | |
yyerror("invalid pipe command"); | |
+ conf.needs_exec = 1; | |
data->only = $6; | |
} | |
| TOKSTDIN |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment