git: 95381c0139d6 - main - syslogd: Use process descriptors
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 28 Sep 2023 15:52:33 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=95381c0139d639c78c922956621cae152471a09b
commit 95381c0139d639c78c922956621cae152471a09b
Author: Jake Freeland <jfree@FreeBSD.org>
AuthorDate: 2023-09-01 02:50:14 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-09-28 15:51:53 +0000
syslogd: Use process descriptors
Prepare for program Capsicumization by storing process descriptors
instead of pids. Signal delivery is not permitted in capability mode,
so we can use pdkill(2) to terminate child processes.
Reviewed by: markj
MFC after: 3 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D41369
---
usr.sbin/syslogd/syslogd.c | 109 ++++++++++++++++++++++-----------------------
1 file changed, 54 insertions(+), 55 deletions(-)
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index 9498b900ed9b..fff45372fda8 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -107,6 +107,7 @@ static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
#include <sys/event.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/procdesc.h>
#include <sys/queue.h>
#include <sys/resource.h>
#include <sys/socket.h>
@@ -298,7 +299,7 @@ struct filed {
} f_forw; /* F_FORW */
struct {
char f_pname[MAXPATHLEN];
- pid_t f_pid;
+ int f_procdesc;
} f_pipe; /* F_PIPE */
} f_un;
#define fu_uname f_un.f_uname
@@ -306,7 +307,7 @@ struct filed {
#define fu_forw_hname f_un.f_forw.f_hname
#define fu_forw_addr f_un.f_forw.f_addr
#define fu_pipe_pname f_un.f_pipe.f_pname
-#define fu_pipe_pid f_un.f_pipe.f_pid
+#define fu_pipe_pd f_un.f_pipe.f_procdesc
/* Book-keeping. */
char f_prevline[MAXSVLINE]; /* last message logged */
@@ -327,7 +328,7 @@ static struct filed consfile; /* Console */
* Queue of about-to-be dead processes we should watch out for.
*/
struct deadq_entry {
- pid_t dq_pid;
+ int dq_procdesc;
int dq_timeout;
TAILQ_ENTRY(deadq_entry) dq_entries;
};
@@ -438,9 +439,9 @@ static void addpeer(const char *, const char *, mode_t);
static void addsock(const char *, const char *, mode_t);
static void cfline(const char *, const char *, const char *, const char *);
static const char *cvthname(struct sockaddr *);
-static void deadq_enter(pid_t, const char *);
-static int deadq_remove(struct deadq_entry *);
-static int deadq_removebypid(pid_t);
+static void deadq_enter(int);
+static void deadq_remove(struct deadq_entry *);
+static bool deadq_removebypid(pid_t);
static int decode(const char *, const CODE *);
static void die(int) __dead2;
static void dofsync(void);
@@ -495,7 +496,10 @@ close_filed(struct filed *f)
f->f_type = F_UNUSED;
break;
case F_PIPE:
- f->fu_pipe_pid = 0;
+ if (f->fu_pipe_pd >= 0) {
+ deadq_enter(f->fu_pipe_pd);
+ f->fu_pipe_pd = -1;
+ }
break;
default:
break;
@@ -1944,20 +1948,16 @@ fprintlog_write(struct filed *f, struct iovlist *il, int flags)
case F_PIPE:
dprintf(" %s\n", f->fu_pipe_pname);
iovlist_append(il, "\n");
- if (f->fu_pipe_pid == 0) {
+ if (f->fu_pipe_pd == -1) {
if ((f->f_file = p_open(f->fu_pipe_pname,
- &f->fu_pipe_pid)) < 0) {
+ &f->fu_pipe_pd)) < 0) {
logerror(f->fu_pipe_pname);
break;
}
}
if (writev(f->f_file, il->iov, il->iovcnt) < 0) {
- int e = errno;
-
- deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
- close_filed(f);
- errno = e;
logerror(f->fu_pipe_pname);
+ close_filed(f);
}
break;
@@ -2260,7 +2260,7 @@ static void
reapchild(int signo __unused)
{
int status;
- pid_t pid;
+ pid_t pid, pipe_pid;
struct filed *f;
while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) {
@@ -2270,8 +2270,16 @@ reapchild(int signo __unused)
/* Now, look in list of active processes. */
STAILQ_FOREACH(f, &fhead, next) {
- if (f->f_type == F_PIPE &&
- f->fu_pipe_pid == pid) {
+ if (f->f_type == F_PIPE) {
+ if (pdgetpid(f->fu_pipe_pd, &pipe_pid) == -1) {
+ dprintf("Failed to query PID: %s\n",
+ strerror(errno));
+ continue;
+ }
+ if (pipe_pid != pid)
+ continue;
+ /* Do not enter into deadq. */
+ f->fu_pipe_pd = -1;
close_filed(f);
log_deadchild(pid, status, f->fu_pipe_pname);
break;
@@ -2352,7 +2360,8 @@ die(int signo)
/* flush any pending output */
if (f->f_prevcount)
fprintlog_successive(f, 0);
- if (f->f_type == F_PIPE && f->fu_pipe_pid > 0)
+ /* close our end of the pipe */
+ if (f->f_type == F_PIPE)
close_filed(f);
}
if (signo) {
@@ -2608,7 +2617,6 @@ init(bool reload)
close_filed(f);
break;
case F_PIPE:
- deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname);
close_filed(f);
break;
default:
@@ -3135,7 +3143,7 @@ cfline(const char *line, const char *prog, const char *host,
break;
case '|':
- f->fu_pipe_pid = 0;
+ f->fu_pipe_pd = -1;
(void)strlcpy(f->fu_pipe_pname, p + 1,
sizeof(f->fu_pipe_pname));
f->f_type = F_PIPE;
@@ -3220,7 +3228,7 @@ markit(void)
switch (dq->dq_timeout) {
case 0:
/* Already signalled once, try harder now. */
- if (kill(dq->dq_pid, SIGKILL) != 0)
+ if (pdkill(dq->dq_procdesc, SIGKILL) != 0)
(void)deadq_remove(dq);
break;
@@ -3233,7 +3241,7 @@ markit(void)
* didn't even really exist, in case we simply
* drop it from the dead queue).
*/
- if (kill(dq->dq_pid, SIGTERM) != 0)
+ if (pdkill(dq->dq_procdesc, SIGTERM) != 0)
(void)deadq_remove(dq);
else
dq->dq_timeout--;
@@ -3610,10 +3618,10 @@ validate(struct sockaddr *sa, const char *hname)
* opposed to a FILE *.
*/
static int
-p_open(const char *prog, pid_t *rpid)
+p_open(const char *prog, int *rpd)
{
sigset_t sigset = { };
- int pfd[2], nulldesc;
+ int nulldesc, pfd[2], pd;
pid_t pid;
char *argv[4]; /* sh -c cmd NULL */
char errmsg[200];
@@ -3624,7 +3632,7 @@ p_open(const char *prog, pid_t *rpid)
/* we are royally screwed anyway */
return (-1);
- switch ((pid = fork())) {
+ switch ((pid = pdfork(&pd, PD_CLOEXEC))) {
case -1:
close(nulldesc);
return (-1);
@@ -3676,63 +3684,54 @@ p_open(const char *prog, pid_t *rpid)
(int)pid);
logerror(errmsg);
}
- *rpid = pid;
+ *rpd = pd;
return (pfd[1]);
}
static void
-deadq_enter(pid_t pid, const char *name)
+deadq_enter(int pd)
{
struct deadq_entry *dq;
- int status;
- if (pid == 0)
+ if (pd == -1)
return;
- /*
- * Be paranoid, if we can't signal the process, don't enter it
- * into the dead queue (perhaps it's already dead). If possible,
- * we try to fetch and log the child's status.
- */
- if (kill(pid, 0) != 0) {
- if (waitpid(pid, &status, WNOHANG) > 0)
- log_deadchild(pid, status, name);
- return;
- }
dq = malloc(sizeof(*dq));
if (dq == NULL) {
logerror("malloc");
exit(1);
}
- *dq = (struct deadq_entry){
- .dq_pid = pid,
- .dq_timeout = DQ_TIMO_INIT
- };
+
+ dq->dq_procdesc = pd;
+ dq->dq_timeout = DQ_TIMO_INIT;
TAILQ_INSERT_TAIL(&deadq_head, dq, dq_entries);
}
-static int
+static void
deadq_remove(struct deadq_entry *dq)
{
- if (dq != NULL) {
- TAILQ_REMOVE(&deadq_head, dq, dq_entries);
- free(dq);
- return (1);
- }
-
- return (0);
+ TAILQ_REMOVE(&deadq_head, dq, dq_entries);
+ close(dq->dq_procdesc);
+ free(dq);
}
-static int
+static bool
deadq_removebypid(pid_t pid)
{
struct deadq_entry *dq;
+ pid_t dq_pid;
TAILQ_FOREACH(dq, &deadq_head, dq_entries) {
- if (dq->dq_pid == pid)
- break;
+ if (pdgetpid(dq->dq_procdesc, &dq_pid) == -1) {
+ dprintf("Failed to query PID: %s\n", strerror(errno));
+ continue;
+ }
+ if (dq_pid == pid) {
+ deadq_remove(dq);
+ return (true);
+ }
}
- return (deadq_remove(dq));
+ return (false);
}
static void