Skip to content

Commit

Permalink
fix two possible local DoS
Browse files Browse the repository at this point in the history
  • Loading branch information
poolpOrg committed May 29, 2015
1 parent 18d7c33 commit c008f17
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
36 changes: 33 additions & 3 deletions smtpd/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions smtpd/mproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit c008f17

Please sign in to comment.