Permalink
Browse files

fix two possible local DoS

  • Loading branch information...
poolpOrg committed May 29, 2015
1 parent 18d7c33 commit c008f17c30f78b4877be768e641a56317e927dca
Showing with 41 additions and 3 deletions.
  1. +33 −3 smtpd/control.c
  2. +8 −0 smtpd/mproc.c
View
@@ -73,9 +73,11 @@ extern const char *backend_stat;
static uint32_t connid = 0;
static struct tree ctl_conns;
static struct tree ctl_count;
static struct stat_digest digest;
#define CONTROL_FD_RESERVE 5
#define CONTROL_FD_RESERVE 5
#define CONTROL_MAXCONN_PER_CLIENT 5
static void
control_imsg(struct mproc *p, struct imsg *imsg)
@@ -282,6 +284,7 @@ control(void)
signal(SIGHUP, SIG_IGN);
tree_init(&ctl_conns);
tree_init(&ctl_count);
memset(&digest, 0, sizeof digest);
digest.startup = time(NULL);
@@ -330,6 +333,9 @@ control_accept(int listenfd, short event, void *arg)
socklen_t len;
struct sockaddr_un sun;
struct ctl_conn *c;
size_t *count;
uid_t euid;
gid_t egid;
if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE)
goto pause;
@@ -346,16 +352,30 @@ control_accept(int listenfd, short event, void *arg)
session_socket_blockmode(connfd, BM_NONBLOCK);
c = xcalloc(1, sizeof(*c), "control_accept");
if (getpeereid(connfd, &c->euid, &c->egid) == -1)
if (getpeereid(connfd, &euid, &egid) == -1)
fatal("getpeereid");
count = tree_get(&ctl_count, euid);
if (count == NULL)
count = xcalloc(1, sizeof *count, "control_accept");
if (*count == CONTROL_MAXCONN_PER_CLIENT) {
close(connfd);
return;
}
(*count)++;
c = xcalloc(1, sizeof(*c), "control_accept");
c->euid = euid;
c->egid = egid;
c->id = ++connid;
c->mproc.proc = PROC_CLIENT;
c->mproc.handler = control_dispatch_ext;
c->mproc.data = c;
mproc_init(&c->mproc, connfd);
mproc_enable(&c->mproc);
tree_xset(&ctl_conns, c->id, c);
tree_set(&ctl_count, c->euid, count);
stat_backend->increment("control.session", 1);
return;
@@ -368,6 +388,16 @@ control_accept(int listenfd, short event, void *arg)
static void
control_close(struct ctl_conn *c)
{
size_t *count;
count = tree_get(&ctl_count, c->euid);
(*count)--;
if (*count == 0) {
tree_xpop(&ctl_count, c->euid);
free(count);
}
else
tree_set(&ctl_count, c->euid, count);
tree_xpop(&ctl_conns, c->id);
mproc_clear(&c->mproc);
free(c);
View
@@ -188,6 +188,14 @@ mproc_dispatch(int fd, short event, void *arg)
for (;;) {
if ((n = imsg_get(&p->imsgbuf, &imsg)) == -1) {
if (smtpd_process == PROC_CONTROL &&
p->proc == PROC_CLIENT) {
log_warnx("warn: client sent invalid imsg "
"over control socket");
p->handler(p, NULL);
return;
}
log_warn("fatal: %s: error in imsg_get for %s",
proc_name(smtpd_process), p->name);
fatalx(NULL);

0 comments on commit c008f17

Please sign in to comment.