Cleanup socket file at exit.

We can't unlink the file if it's outside the chroot, so we need to keep
a simple worker outside of it.
This commit is contained in:
Quentin Rameau 2017-07-09 14:36:46 +02:00 committed by Laslo Hunhold
parent 260ef0a988
commit 141bb88af1
2 changed files with 75 additions and 30 deletions

View file

@ -55,6 +55,7 @@ when dropping privileges.
Create the UNIX-domain socket file Create the UNIX-domain socket file
.Ar sockfile .Ar sockfile
and listen on it for incoming connections. and listen on it for incoming connections.
The file will be cleaned up at exit.
.It Fl v .It Fl v
Print version information to stdout and exit. Print version information to stdout and exit.
.El .El

104
quark.c
View file

@ -5,6 +5,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/wait.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ctype.h> #include <ctype.h>
@ -28,6 +29,8 @@
#include "arg.h" #include "arg.h"
char *argv0; char *argv0;
static int insock;
static char *udsname;
#include "config.h" #include "config.h"
@ -824,7 +827,7 @@ serve(int insock)
} }
} }
void static void
die(const char *errstr, ...) die(const char *errstr, ...)
{ {
va_list ap; va_list ap;
@ -917,6 +920,23 @@ getusock(char *udsname, uid_t uid, gid_t gid)
return insock; return insock;
} }
static void
cleanup(void)
{
close(insock);
if (udsname) {
if (unlink(udsname) < 0)
fprintf(stderr, "unlink: %s\n", strerror(errno));
}
}
static void
sigcleanup(int sig)
{
cleanup();
_exit(1);
}
static void static void
usage(void) usage(void)
{ {
@ -932,8 +952,8 @@ main(int argc, char *argv[])
struct passwd *pwd = NULL; struct passwd *pwd = NULL;
struct group *grp = NULL; struct group *grp = NULL;
struct rlimit rlim; struct rlimit rlim;
int i, insock; pid_t cpid, wpid;
char *udsname = NULL; int i, status = 0;
ARGBEGIN { ARGBEGIN {
case 'd': case 'd':
@ -971,6 +991,13 @@ main(int argc, char *argv[])
usage(); usage();
} }
atexit(cleanup);
if (signal(SIGINT, sigcleanup) == SIG_ERR) {
fprintf(stderr, "%s: signal: Failed to handle SIGINT\n",
argv0);
return 1;
}
/* compile and check the supplied vhost regexes */ /* compile and check the supplied vhost regexes */
if (vhosts) { if (vhosts) {
for (i = 0; i < LEN(vhost); i++) { for (i = 0; i < LEN(vhost); i++) {
@ -1011,35 +1038,52 @@ main(int argc, char *argv[])
insock = udsname ? getusock(udsname, pwd->pw_uid, grp->gr_gid) : insock = udsname ? getusock(udsname, pwd->pw_uid, grp->gr_gid) :
getipsock(); getipsock();
/* chroot */ switch (cpid = fork()) {
if (chdir(servedir) < 0) { case -1:
die("%s: chdir %s: %s\n", argv0, servedir, strerror(errno)); fprintf(stderr, "%s: fork: %s\n", argv0, strerror(errno));
} break;
if (chroot(".") < 0) { case 0:
die("%s: chroot .: %s\n", argv0, strerror(errno)); /* reap children automatically */
if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
fprintf(stderr, "%s: signal: Failed to set SIG_IGN on"
"SIGINT\n", argv0);
return 1;
}
/* chroot */
if (chdir(servedir) < 0) {
die("%s: chdir %s: %s\n", argv0, servedir, strerror(errno));
}
if (chroot(".") < 0) {
die("%s: chroot .: %s\n", argv0, strerror(errno));
}
/* drop root */
if (grp && setgroups(1, &(grp->gr_gid)) < 0) {
die("%s: setgroups: %s\n", argv0, strerror(errno));
}
if (grp && setgid(grp->gr_gid) < 0) {
die("%s: setgid: %s\n", argv0, strerror(errno));
}
if (pwd && setuid(pwd->pw_uid) < 0) {
die("%s: setuid: %s\n", argv0, strerror(errno));
}
if (getuid() == 0) {
die("%s: won't run as root user\n", argv0);
}
if (getgid() == 0) {
die("%s: won't run as root group\n", argv0);
}
serve(insock);
_exit(0);
default:
while ((wpid = wait(&status)) > 0)
;
} }
/* drop root */ cleanup();
if (grp && setgroups(1, &(grp->gr_gid)) < 0) { return status;
die("%s: setgroups: %s\n", argv0, strerror(errno));
}
if (grp && setgid(grp->gr_gid) < 0) {
die("%s: setgid: %s\n", argv0, strerror(errno));
}
if (pwd && setuid(pwd->pw_uid) < 0) {
die("%s: setuid: %s\n", argv0, strerror(errno));
}
if (getuid() == 0) {
die("%s: won't run as root user\n", argv0);
}
if (getgid() == 0) {
die("%s: won't run as root group\n", argv0);
}
serve(insock);
close(insock);
return 0;
} }
/* /*