Last active
October 11, 2016 23:48
-
-
Save brynet/9f74a77558f91a50e6b544e5c3e96a9b to your computer and use it in GitHub Desktop.
pledge(2) for fdm #2
This file contains hidden or 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 b81cd42..57b0eb6 100644 | |
--- a/child.c | |
+++ b/child.c | |
@@ -129,6 +129,35 @@ 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) { | |
+ if (!cfd->needs_inet) { | |
+ /* Revokes "proc inet dns" promises */ | |
+ if (pledge("stdio rpath wpath cpath fattr flock getpw", NULL) == -1) { | |
+ fatal("pledge"); | |
+ } | |
+ } else { | |
+ /* 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) { | |
+ if (!cfd->needs_inet) { | |
+ /* Revokes "cpath proc inet dns" promises */ | |
+ if (pledge("stdio rpath tmppath", NULL) == -1) { | |
+ fatal("pledge"); | |
+ } | |
+ } else { | |
+ /* 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..5a558c6 100644 | |
--- a/configure.ac | |
+++ b/configure.ac | |
@@ -102,6 +112,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 cdf8383..7cf87e7 100644 | |
--- a/fdm.c | |
+++ b/fdm.c | |
@@ -732,6 +732,39 @@ retry: | |
goto out; | |
} | |
+#ifdef HAVE_PLEDGE | |
+ if (conf.needs_exec && op == FDMOP_FETCH) { | |
+ log_debug2("pledge fetch exec"); | |
+ if (!conf.needs_inet) { | |
+ if (pledge("stdio rpath wpath cpath fattr flock getpw proc exec", NULL) == -1) { | |
+ log_warnx("pledge"); | |
+ exit(1); | |
+ } | |
+ } else { | |
+ 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 (mmap) cache, covered | |
+ * above by "rpath wpath cpath". Unrelated to FDMOP_CACHE. | |
+ */ | |
+ 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 +794,8 @@ retry: | |
cfd = xmalloc(sizeof *cfd); | |
cfd->account = a; | |
cfd->op = op; | |
+ cfd->needs_exec = conf.needs_exec; | |
+ cfd->needs_inet = conf.needs_inet; | |
cfd->children = &children; | |
child = child_start(&children, | |
conf.child_uid, conf.child_gid, | |
diff --git a/fdm.h b/fdm.h | |
index 0eaba68..07cf39c 100644 | |
--- a/fdm.h | |
+++ b/fdm.h | |
@@ -453,6 +453,8 @@ ARRAY_DECL(children, struct child *); | |
struct child_fetch_data { | |
struct account *account; | |
enum fdmop op; | |
+ int needs_exec; | |
+ int needs_inet; | |
struct children *children; | |
}; | |
@@ -622,6 +624,8 @@ struct conf { | |
u_int purge_after; | |
enum decision impl_act; | |
int max_accts; | |
+ int needs_exec; | |
+ int needs_inet; | |
char *lock_file; | |
int lock_wait; | |
diff --git a/parse.y b/parse.y | |
index 42f78d7..162104b 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; | |
@@ -1216,6 +1218,7 @@ actitem: execpipe strv | |
if ($1 && $9) | |
yyerror("use either imaps or set starttls"); | |
+ conf.needs_inet = 1; | |
$$ = xcalloc(1, sizeof *$$); | |
$$->deliver = &deliver_imap; | |
@@ -1256,6 +1259,8 @@ actitem: execpipe strv | |
{ | |
struct deliver_smtp_data *data; | |
+ conf.needs_inet = 1; | |
+ | |
$$ = xcalloc(1, sizeof *$$); | |
$$->deliver = &deliver_smtp; | |
@@ -1601,6 +1606,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"); | |
@@ -2198,6 +2204,7 @@ fetchtype: poptype server userpassnetrc poponly apop verify uidl tls1 starttls | |
if ($1 && $9) | |
yyerror("use either pop3s or set starttls"); | |
+ conf.needs_inet = 1; | |
$$.fetch = &fetch_pop3; | |
data = xcalloc(1, sizeof *data); | |
@@ -2246,6 +2253,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; | |
@@ -2257,6 +2265,7 @@ fetchtype: poptype server userpassnetrc poponly apop verify uidl tls1 starttls | |
if ($1 && $10) | |
yyerror("use either imaps or set starttls"); | |
+ conf.needs_inet = 1; | |
$$.fetch = &fetch_imap; | |
data = xcalloc(1, sizeof *data); | |
@@ -2305,6 +2314,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 | |
@@ -2336,6 +2346,7 @@ fetchtype: poptype server userpassnetrc poponly apop verify uidl tls1 starttls | |
if (*$6 == '\0') | |
yyerror("invalid cache"); | |
+ conf.needs_inet = 1; | |
$$.fetch = &fetch_nntp; | |
data = xcalloc(1, sizeof *data); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment