Page MenuHomeFreeBSD

D41465.id126826.diff
No OneTemporary

D41465.id126826.diff

diff --git a/usr.sbin/syslogd/Makefile b/usr.sbin/syslogd/Makefile
--- a/usr.sbin/syslogd/Makefile
+++ b/usr.sbin/syslogd/Makefile
@@ -17,7 +17,8 @@
.if ${MK_CASPER} != "no"
SRCS+= syslogd_cap.c \
- syslogd_cap_config.c
+ syslogd_cap_config.c \
+ syslogd_cap_log.c
CFLAGS+= -DWITH_CASPER
LIBADD+= cap_net casper nv
.endif
diff --git a/usr.sbin/syslogd/syslogd.h b/usr.sbin/syslogd/syslogd.h
--- a/usr.sbin/syslogd/syslogd.h
+++ b/usr.sbin/syslogd/syslogd.h
@@ -67,6 +67,7 @@
#include <sys/nv.h>
#include <sys/queue.h>
#include <sys/time.h>
+#include <sys/uio.h>
#define SYSLOG_NAMES
#include <sys/syslog.h>
@@ -75,6 +76,8 @@
#include <stdbool.h>
#include <stdio.h>
+#include "ttymsg.h"
+
#define MAXLINE 8192 /* maximum line length */
#define MAXSVLINE MAXLINE /* maximum saved line length */
#define MAXUNAMES 20 /* maximum number of user names */
@@ -172,11 +175,23 @@
STAILQ_ENTRY(filed) next; /* next in linked list */
};
+/*
+ * List of iovecs to which entries can be appended.
+ * Used for constructing the message to be logged.
+ */
+struct iovlist {
+ struct iovec iov[TTYMSG_IOV_MAX];
+ size_t iovcnt;
+ size_t totalsize;
+};
+
extern const char *ConfFile;
extern char LocalHostName[MAXHOSTNAMELEN];
void closelogfiles(void);
void logerror(const char *);
+int p_open(size_t, const char *, pid_t *);
nvlist_t *readconfigfile(const char *);
+void wallmsg(const struct filed *, struct iovec *, const int);
#endif /* !_SYSLOGD_H_ */
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -142,7 +142,6 @@
#include "pathnames.h"
#include "syslogd.h"
#include "syslogd_cap.h"
-#include "ttymsg.h"
const char *ConfFile = _PATH_LOGCONF;
static const char *PidFile = _PATH_LOGPID;
@@ -350,12 +349,10 @@
static nvlist_t *prop_filter_compile(const char *);
static void parsemsg(const char *, char *);
static void printsys(char *);
-static int p_open(const char *, pid_t *);
static const char *ttymsg_check(struct iovec *, int, char *, int);
static void usage(void);
static bool validate(struct sockaddr *, const char *);
static void unmapped(struct sockaddr *);
-static void wallmsg(struct filed *, struct iovec *, const int iovlen);
static int waitdaemon(int);
static void increase_rcvbuf(int);
@@ -1670,16 +1667,6 @@
needdofsync = false;
}
-/*
- * List of iovecs to which entries can be appended.
- * Used for constructing the message to be logged.
- */
-struct iovlist {
- struct iovec iov[TTYMSG_IOV_MAX];
- size_t iovcnt;
- size_t totalsize;
-};
-
static void
iovlist_init(struct iovlist *il)
{
@@ -1836,8 +1823,16 @@
dprintf(" %s\n", f->f_pname);
iovlist_append(il, "\n");
if (f->f_procdesc == -1) {
- if ((f->f_file = p_open(f->f_pname,
- &f->f_procdesc)) < 0) {
+ struct filed *f_in_list;
+ int i = 0;
+
+ STAILQ_FOREACH(f_in_list, &fhead, next) {
+ if (f_in_list == f)
+ break;
+ ++i;
+ }
+ f->f_file = p_open(i, f->f_pname, &f->f_procdesc);
+ if (f->f_file < 0) {
logerror(f->f_pname);
break;
}
@@ -2079,8 +2074,8 @@
* Write the specified message to either the entire
* world, or a list of approved users.
*/
-static void
-wallmsg(struct filed *f, struct iovec *iov, const int iovlen)
+void
+wallmsg(const struct filed *f, struct iovec *iov, const int iovlen)
{
static int reenter; /* avoid calling ourselves */
struct utmpx *ut;
@@ -2096,10 +2091,8 @@
continue;
if (f->f_type == F_WALL) {
if ((p = ttymsg(iov, iovlen, ut->ut_line,
- TTYMSGTIME)) != NULL) {
- errno = 0; /* already in msg */
- logerror(p);
- }
+ TTYMSGTIME)) != NULL)
+ dprintf("%s\n", p);
continue;
}
/* should we send the message to this user? */
@@ -2108,10 +2101,8 @@
break;
if (!strcmp(f->f_uname[i], ut->ut_user)) {
if ((p = ttymsg_check(iov, iovlen, ut->ut_line,
- TTYMSGTIME)) != NULL) {
- errno = 0; /* already in msg */
- logerror(p);
- }
+ TTYMSGTIME)) != NULL)
+ dprintf("%s\n", p);
break;
}
}
@@ -3442,14 +3433,13 @@
* Fairly similar to popen(3), but returns an open descriptor, as
* opposed to a FILE *.
*/
-static int
-p_open(const char *prog, int *rpd)
+int
+p_open(size_t filed_idx __unused, const char *prog, int *rpd)
{
struct sigaction act = { };
int pfd[2], pd;
pid_t pid;
char *argv[4]; /* sh -c cmd NULL */
- char errmsg[200];
if (pipe(pfd) == -1)
return (-1);
@@ -3464,18 +3454,14 @@
argv[1] = strdup("-c");
argv[2] = strdup(prog);
argv[3] = NULL;
- if (argv[0] == NULL || argv[1] == NULL || argv[2] == NULL) {
- logerror("strdup");
- exit(1);
- }
+ if (argv[0] == NULL || argv[1] == NULL || argv[2] == NULL)
+ err(1, "strdup");
alarm(0);
act.sa_handler = SIG_DFL;
for (size_t i = 0; i < nitems(sigcatch); ++i) {
- if (sigaction(sigcatch[i], &act, NULL) == -1) {
- logerror("sigaction");
- exit(1);
- }
+ if (sigaction(sigcatch[i], &act, NULL) == -1)
+ err(1, "sigaction");
}
dup2(pfd[0], STDIN_FILENO);
@@ -3498,11 +3484,8 @@
*/
if (fcntl(pfd[1], F_SETFL, O_NONBLOCK) == -1) {
/* This is bad. */
- (void)snprintf(errmsg, sizeof(errmsg),
- "Warning: cannot change pipe to PID %d to "
- "non-blocking behaviour.",
- (int)pid);
- logerror(errmsg);
+ dprintf("Warning: cannot change pipe to PID %d to non-blocking"
+ "behaviour.", pid);
}
*rpd = pd;
return (pfd[1]);
diff --git a/usr.sbin/syslogd/syslogd_cap.h b/usr.sbin/syslogd/syslogd_cap.h
--- a/usr.sbin/syslogd/syslogd_cap.h
+++ b/usr.sbin/syslogd/syslogd_cap.h
@@ -47,8 +47,27 @@
#include "syslogd.h"
+/*
+ * Log file data used by the casper process to
+ * verify filed integrity.
+ */
+struct cap_filed {
+ size_t idx;
+ char pipe_cmd[MAXPATHLEN];
+ SLIST_ENTRY(cap_filed) next;
+};
+extern SLIST_HEAD(cfiled_list, cap_filed) cfiled_head;
+
+int cap_p_open(cap_channel_t *, size_t, const char *, int *);
nvlist_t *cap_readconfigfile(cap_channel_t *, const char *);
+const char *cap_ttymsg(cap_channel_t *, struct iovec *, int, const char *, int);
+void cap_wallmsg(cap_channel_t *, const struct filed *, struct iovec *,
+ const int);
+
+int casper_p_open(nvlist_t *, nvlist_t *);
int casper_readconfigfile(nvlist_t *, nvlist_t *);
+int casper_ttymsg(nvlist_t *, nvlist_t *);
+int casper_wallmsg(nvlist_t *);
nvlist_t *filed_to_nvlist(const struct filed *);
nvlist_t *prop_filter_to_nvlist(const struct prop_filter *pfilter);
@@ -58,8 +77,14 @@
#else /* !WITH_CASPER */
+#define cap_p_open(chan, f, rpd) \
+ p_open(f, rpd)
#define cap_readconfigfile(chan, cf) \
readconfigfile(cf)
+#define cap_ttymsg(chan, iov, iovcnt, line, tmout) \
+ ttymsg(iov, iovcnt, line, tmout)
+#define cap_wallmsg(chan, f, iov, iovcnt) \
+ wallmsg(f, iov, iovcnt)
#endif /* WITH_CASPER */
diff --git a/usr.sbin/syslogd/syslogd_cap.c b/usr.sbin/syslogd/syslogd_cap.c
--- a/usr.sbin/syslogd/syslogd_cap.c
+++ b/usr.sbin/syslogd/syslogd_cap.c
@@ -45,8 +45,14 @@
{
int error = EINVAL;
- if (strcmp(cmd, "readconfigfile") == 0)
+ if (strcmp(cmd, "p_open") == 0)
+ error = casper_p_open(nvlin, nvlout);
+ else if (strcmp(cmd, "readconfigfile") == 0)
error = casper_readconfigfile(nvlin, nvlout);
+ else if (strcmp(cmd, "ttymsg") == 0)
+ error = casper_ttymsg(nvlin, nvlout);
+ else if (strcmp(cmd, "wallmsg") == 0)
+ error = casper_wallmsg(nvlin);
return (error);
}
diff --git a/usr.sbin/syslogd/syslogd_cap_config.c b/usr.sbin/syslogd/syslogd_cap_config.c
--- a/usr.sbin/syslogd/syslogd_cap_config.c
+++ b/usr.sbin/syslogd/syslogd_cap_config.c
@@ -277,6 +277,9 @@
int
casper_readconfigfile(nvlist_t *nvlin, nvlist_t *nvlout)
{
+ const nvlist_t * const *filed_list;
+ nvlist_t *nvl_conf;
+ size_t n_fileds;
const char *path;
/*
@@ -291,6 +294,35 @@
strlcpy(LocalHostName, nvlist_get_string(nvlin, "LocalHostName"),
sizeof(LocalHostName));
- nvlist_move_nvlist(nvlout, "nvl_conf", readconfigfile(path));
+ nvl_conf = readconfigfile(path);
+
+ /* Remove old filed data in case we are reloading. */
+ while (!SLIST_EMPTY(&cfiled_head)) {
+ struct cap_filed *cfiled;
+
+ cfiled = SLIST_FIRST(&cfiled_head);
+ SLIST_REMOVE_HEAD(&cfiled_head, next);
+ free(cfiled);
+ }
+ /* Record F_PIPE filed data for use in p_open(). */
+ if (!nvlist_exists_nvlist_array(nvl_conf, "filed_list"))
+ return (0);
+ filed_list = nvlist_get_nvlist_array(nvl_conf, "filed_list", &n_fileds);
+ for (size_t i = 0; i < n_fileds; ++i) {
+ if (nvlist_get_number(filed_list[i], "f_type") == F_PIPE) {
+ struct cap_filed *cfiled;
+ const char *pipe_cmd;
+
+ cfiled = malloc(sizeof(*cfiled));
+ if (cfiled == NULL)
+ err(1, "malloc");
+ cfiled->idx = i;
+ pipe_cmd = nvlist_get_string(filed_list[i], "f_pname");
+ strlcpy(cfiled->pipe_cmd, pipe_cmd, sizeof(cfiled->pipe_cmd));
+ SLIST_INSERT_HEAD(&cfiled_head, cfiled, next);
+ }
+ }
+
+ nvlist_move_nvlist(nvlout, "nvl_conf", nvl_conf);
return (0);
}
diff --git a/usr.sbin/syslogd/syslogd_cap_log.c b/usr.sbin/syslogd/syslogd_cap_log.c
new file mode 100644
--- /dev/null
+++ b/usr.sbin/syslogd/syslogd_cap_log.c
@@ -0,0 +1,225 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 The FreeBSD Foundation
+ *
+ * This software was developed by Jake Freeland <jfree@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <string.h>
+
+#include "syslogd_cap.h"
+
+struct cfiled_list cfiled_head;
+
+static void
+iovec_to_nvlist(const struct iovec *iov, nvlist_t *nvl)
+{
+ nvlist_add_string(nvl, "iov_base", iov->iov_base);
+ nvlist_add_number(nvl, "iov_len", iov->iov_len);
+}
+
+static void
+nvlist_to_iovec(const nvlist_t *nvl, struct iovec *iov)
+{
+ iov->iov_base = strdup(nvlist_get_string(nvl, "iov_base"));
+ iov->iov_len = nvlist_get_number(nvl, "iov_len");
+}
+
+int
+cap_p_open(cap_channel_t *chan, size_t filed_idx, const char *prog,
+ int *procdesc)
+{
+ nvlist_t *nvl = nvlist_create(0);
+ int error, pipedesc_w;
+
+ nvlist_add_string(nvl, "cmd", "p_open");
+ nvlist_add_number(nvl, "filed_idx", filed_idx);
+ nvlist_add_string(nvl, "prog", prog);
+ nvl = cap_xfer_nvlist(chan, nvl);
+ if (nvl == NULL) {
+ logerror("Failed to xfer p_open nvlist");
+ exit(1);
+ }
+ error = nvlist_get_number(nvl, "error");
+ if (error != 0) {
+ errno = error;
+ logerror("Failed to open piped command");
+ }
+ pipedesc_w = dnvlist_take_descriptor(nvl, "pipedesc_w", -1);
+ *procdesc = dnvlist_take_descriptor(nvl, "procdesc", -1);
+
+ nvlist_destroy(nvl);
+ return (pipedesc_w);
+}
+
+int
+casper_p_open(nvlist_t *nvlin, nvlist_t *nvlout)
+{
+ struct cap_filed *cfiled;
+ size_t filed_idx;
+ int pipedesc_w, procdesc = -1;
+ const char *prog;
+
+ filed_idx = nvlist_get_number(nvlin, "filed_idx");
+ prog = nvlist_get_string(nvlin, "prog");
+ SLIST_FOREACH(cfiled, &cfiled_head, next) {
+ if (cfiled->idx != filed_idx)
+ continue;
+ if (strcmp(cfiled->pipe_cmd, prog) != 0)
+ return (-1);
+
+ pipedesc_w = p_open(filed_idx, prog, &procdesc);
+ if (pipedesc_w == -1)
+ return (-1);
+ nvlist_move_descriptor(nvlout, "pipedesc_w", pipedesc_w);
+ nvlist_move_descriptor(nvlout, "procdesc", procdesc);
+ return (0);
+ }
+
+ return (-1);
+}
+
+const char *
+cap_ttymsg(cap_channel_t *chan, struct iovec *iov, int iovcnt,
+ const char *line, int tmout)
+{
+ nvlist_t *nvl = nvlist_create(0);
+ int error;
+ static char errbuf[1024];
+ char *ret = NULL;
+
+ nvlist_add_string(nvl, "cmd", "ttymsg");
+ for (int i = 0; i < iovcnt; ++i) {
+ nvlist_t *nvl_iov = nvlist_create(0);
+ iovec_to_nvlist(iov + i, nvl_iov);
+ nvlist_append_nvlist_array(nvl, "iovec_list", nvl_iov);
+ nvlist_destroy(nvl_iov);
+ }
+ nvlist_add_string(nvl, "line", line);
+ nvlist_add_number(nvl, "tmout", tmout);
+
+ nvl = cap_xfer_nvlist(chan, nvl);
+ if (nvl == NULL) {
+ logerror("Failed to xfer ttymsg nvlist");
+ exit(1);
+ }
+ error = nvlist_get_number(nvl, "error");
+ if (error != 0) {
+ errno = error;
+ logerror("Failed to ttymsg");
+ }
+ if (nvlist_exists_string(nvl, "errstr")) {
+ const char *errstr = nvlist_get_string(nvl, "errstr");
+ (void)strlcpy(errbuf, errstr, sizeof(errbuf));
+ ret = errbuf;
+ }
+
+ nvlist_destroy(nvl);
+ return (ret);
+}
+
+int
+casper_ttymsg(nvlist_t *nvlin, nvlist_t *nvlout)
+{
+ const nvlist_t * const *nvl_iov;
+ struct iovec *iov;
+ size_t iovcnt;
+ int tmout;
+ const char *line;
+
+ nvl_iov = nvlist_get_nvlist_array(nvlin, "iovec_list", &iovcnt);
+ assert(iovcnt <= TTYMSG_IOV_MAX);
+ iov = calloc(iovcnt, sizeof(*iov));
+ for (size_t i = 0; i < iovcnt; ++i)
+ nvlist_to_iovec(nvl_iov[i], iov + i);
+ line = nvlist_get_string(nvlin, "line");
+ tmout = nvlist_get_number(nvlin, "tmout");
+ line = ttymsg(iov, iovcnt, line, tmout);
+ if (line != NULL)
+ nvlist_add_string(nvlout, "errstr", line);
+
+ free(iov);
+ return (0);
+}
+
+void
+cap_wallmsg(cap_channel_t *chan, const struct filed *f, struct iovec *iov,
+ int iovcnt)
+{
+ nvlist_t *nvl = nvlist_create(0);
+ int error;
+
+ nvlist_add_string(nvl, "cmd", "wallmsg");
+ /*
+ * The filed_to_nvlist() function is not needed
+ * here because wallmsg() only uses f_type and
+ * fu_uname members, which are both inline.
+ */
+ nvlist_add_binary(nvl, "filed", f, sizeof(*f));
+ for (int i = 0; i < iovcnt; ++i) {
+ nvlist_t *nvl_iov = nvlist_create(0);
+ iovec_to_nvlist(iov + i, nvl_iov);
+ nvlist_append_nvlist_array(nvl, "iovec_list", nvl_iov);
+ nvlist_destroy(nvl_iov);
+ }
+
+ nvl = cap_xfer_nvlist(chan, nvl);
+ if (nvl == NULL) {
+ logerror("Failed to xfer wallmsg nvlist");
+ exit(1);
+ }
+ error = nvlist_get_number(nvl, "error");
+ if (error != 0) {
+ errno = error;
+ logerror("Failed to wallmsg");
+ }
+ nvlist_destroy(nvl);
+}
+
+int
+casper_wallmsg(nvlist_t *nvlin)
+{
+ const struct filed *f;
+ const nvlist_t * const *nvl_iov;
+ struct iovec *iov;
+ size_t sz;
+
+ f = nvlist_get_binary(nvlin, "filed", &sz);
+ assert(sz == sizeof(*f));
+ nvl_iov = nvlist_get_nvlist_array(nvlin, "iovec_list", &sz);
+ assert(sz <= TTYMSG_IOV_MAX);
+ iov = calloc(sz, sizeof(*iov));
+ for (size_t i = 0; i < sz; ++i)
+ nvlist_to_iovec(nvl_iov[i], iov + i);
+ wallmsg(f, iov, sz);
+
+ for (size_t i = 0; i < sz; ++i)
+ free(iov[i].iov_base);
+ free(iov);
+ return (0);
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 27, 5:06 AM (7 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24272475
Default Alt Text
D41465.id126826.diff (15 KB)

Event Timeline