On Thu, Aug 16, 2018 at 04:28:03PM -0400, Bryan Steele wrote:
> On Thu, Aug 16, 2018 at 04:20:54PM -0400, Bryan Steele wrote:
> > This adds unveil to pflogd(8)
> >
> > pflogd(8) is a special case, residing in /sbin, it's a static PIE. As
> > such, I thought it might be worth experimenting with execpromises here.
> > This allows re-exec after privdrop, and removes chroot(2) in favour of
> > only unveil(2) and pledge(2). I've left the code there for now just in
> > case portability is a concern.
>
> Please ignore this diff for now.
>
> > The privileged part of pflogd(8) is now disallowed from accessing most
> > of the filesystem, veiled except for read-only opening of /dev/bpf, and
> > rwc for the log file, typically /var/log/pflog. This process cannot yet
> > pledge(2), so special care is needed to make sure no library functions
> > called use files permitted by certain pledges.
> >
> > The unprivileged part already runs pledged "stdio recvfd"
> >
> > This includes the diff I sent previously, I'd like to commit that part
> > separately, any oks on that one?
> >
> > https://marc.info/?l=openbsd-tech&m=153347271628532&w=2
> >
> > Also, ok for this? ;-)
> >
> > -Bryan.
Sorry about that. New diff.
Index: pflogd.8
===================================================================
RCS file: /cvs/src/sbin/pflogd/pflogd.8,v
retrieving revision 1.49
diff -u -p -u -r1.49 pflogd.8
--- sbin/pflogd/pflogd.8 30 May 2017 17:15:06 -0000 1.49
+++ sbin/pflogd/pflogd.8 16 Aug 2018 20:36:11 -0000
@@ -86,9 +86,8 @@ temporarily uses the old snaplen to keep
tries to preserve the integrity of the log file against I/O errors.
Furthermore, integrity of an existing log file is verified before
appending.
-If there is an invalid log file or an I/O error, the log file is moved
-out of the way and a new one is created.
-If a new file cannot be created, logging is suspended until a
+If there is an invalid log file or an I/O error, logging is suspended
+until a
.Dv SIGHUP
or a
.Dv SIGALRM
Index: pflogd.c
===================================================================
RCS file: /cvs/src/sbin/pflogd/pflogd.c,v
retrieving revision 1.58
diff -u -p -u -r1.58 pflogd.c
--- sbin/pflogd/pflogd.c 9 Sep 2017 13:02:52 -0000 1.58
+++ sbin/pflogd/pflogd.c 16 Aug 2018 20:36:11 -0000
@@ -75,7 +75,7 @@ int flush_buffer(FILE *);
int if_exists(char *);
void logmsg(int, const char *, ...);
void purge_buffer(void);
-int reset_dump(int);
+int reset_dump(void);
int scan_dump(FILE *, off_t);
int set_snaplen(int);
void set_suspended(int);
@@ -84,8 +84,6 @@ void sig_close(int);
void sig_hup(int);
void usage(void);
-static int try_reset_dump(int);
-
/* buffer must always be greater than snaplen */
static int bufpkt = 0; /* number of packets in buffer */
static int buflen = 0; /* allocated size of buffer */
@@ -199,6 +197,11 @@ if_exists(char *ifname)
int
init_pcap(void)
{
+ if (unveil("/dev/bpf", "r") == -1) {
+ logmsg(LOG_ERR, "unveil: %s", strerror(errno));
+ return (-1);
+ }
+
hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf);
if (hpcap == NULL) {
logmsg(LOG_ERR, "Failed to initialize: %s", errbuf);
@@ -220,6 +223,11 @@ init_pcap(void)
return (-1);
}
+ if (unveil(NULL, NULL) == -1) {
+ logmsg(LOG_ERR, "unveil: %s", strerror(errno));
+ return (-1);
+ }
+
return (0);
}
@@ -238,25 +246,7 @@ set_snaplen(int snap)
}
int
-reset_dump(int nomove)
-{
- int ret;
-
- for (;;) {
- ret = try_reset_dump(nomove);
- if (ret <= 0)
- break;
- }
-
- return (ret);
-}
-
-/*
- * tries to (re)open log file, nomove flag is used with -x switch
- * returns 0: success, 1: retry (log moved), -1: error
- */
-int
-try_reset_dump(int nomove)
+reset_dump(void)
{
struct pcap_file_header hdr;
struct stat st;
@@ -323,12 +313,9 @@ try_reset_dump(int nomove)
}
} else if (scan_dump(fp, st.st_size)) {
fclose(fp);
- if (nomove || priv_move_log()) {
- logmsg(LOG_ERR,
- "Invalid/incompatible log file, move it away");
- return (-1);
- }
- return (1);
+ logmsg(LOG_ERR,
+ "Invalid/incompatible log file, move it away");
+ return (-1);
}
dpcap = fp;
@@ -641,7 +628,7 @@ main(int argc, char **argv)
bufpkt = 0;
}
- if (reset_dump(Xflag) < 0) {
+ if (reset_dump() < 0) {
if (Xflag)
return (1);
@@ -666,10 +653,14 @@ main(int argc, char **argv)
if (gotsig_close)
break;
if (gotsig_hup) {
- if (reset_dump(0)) {
+ int was_suspended = suspended;
+ if (reset_dump()) {
logmsg(LOG_ERR,
"Logging suspended: open error");
set_suspended(1);
+ } else {
+ if (was_suspended)
+ logmsg(LOG_NOTICE, "Logging resumed");
}
gotsig_hup = 0;
}
Index: privsep.c
===================================================================
RCS file: /cvs/src/sbin/pflogd/privsep.c,v
retrieving revision 1.30
diff -u -p -u -r1.30 privsep.c
--- sbin/pflogd/privsep.c 9 Sep 2017 13:02:52 -0000 1.30
+++ sbin/pflogd/privsep.c 16 Aug 2018 20:36:11 -0000
@@ -42,7 +42,6 @@
enum cmd_types {
PRIV_INIT_PCAP, /* init pcap fdpass bpf */
PRIV_SET_SNAPLEN, /* set the snaplength */
- PRIV_MOVE_LOG, /* move logfile away */
PRIV_OPEN_LOG, /* open logfile for appending */
};
@@ -54,7 +53,6 @@ static int may_read(int, void *, size_t
static void must_read(int, void *, size_t);
static void must_write(int, void *, size_t);
static int set_snaplen(int snap);
-static int move_log(const char *name);
extern char *filename;
extern char *interface;
@@ -133,6 +131,9 @@ priv_init(int Pflag, int argc, char *arg
setproctitle("[priv]");
+ if (unveil(filename, "rwc") == -1)
+ err(1, "unveil");
+
#if 0
/* This needs to do bpf ioctl */
BROKEN if (pledge("stdio rpath wpath cpath sendfd proc bpf", NULL) == -1)
@@ -195,13 +196,6 @@ BROKEN if (pledge("stdio rpath wpath cpa
filename, strerror(olderrno));
break;
- case PRIV_MOVE_LOG:
- logmsg(LOG_DEBUG,
- "[priv]: msg PRIV_MOVE_LOG received");
- ret = move_log(filename);
- must_write(socks[0], &ret, sizeof(int));
- break;
-
default:
logmsg(LOG_ERR, "[priv]: unknown command %d", cmd);
_exit(1);
@@ -225,48 +219,6 @@ set_snaplen(int snap)
return 0;
}
-static int
-move_log(const char *name)
-{
- char ren[PATH_MAX];
- int len;
-
- for (;;) {
- int fd;
-
- len = snprintf(ren, sizeof(ren), "%s.bad.XXXXXXXX", name);
- if (len >= sizeof(ren)) {
- logmsg(LOG_ERR, "[priv] new name too long");
- return (1);
- }
-
- /* lock destination */
- fd = mkstemp(ren);
- if (fd >= 0) {
- close(fd);
- break;
- }
- if (errno != EINTR) {
- logmsg(LOG_ERR, "[priv] failed to create new name: %s",
- strerror(errno));
- return (1);
- }
- }
-
- if (rename(name, ren)) {
- logmsg(LOG_ERR, "[priv] failed to rename %s to %s: %s",
- name, ren, strerror(errno));
- unlink(ren);
- return (1);
- }
-
- logmsg(LOG_NOTICE,
- "[priv]: log file %s moved to %s", name, ren);
-
- return (0);
-}
-
-
/* receive bpf fd from privileged process using fdpass and init pcap */
int
priv_init_pcap(int snaplen)
@@ -345,22 +297,6 @@ priv_open_log(void)
fd = receive_fd(priv_fd);
return (fd);
-}
-
-/* Move-away and reopen log-file */
-int
-priv_move_log(void)
-{
- int cmd, ret;
-
- if (priv_fd < 0)
- errx(1, "%s: called from privileged portion", __func__);
-
- cmd = PRIV_MOVE_LOG;
- must_write(priv_fd, &cmd, sizeof(int));
- must_read(priv_fd, &ret, sizeof(int));
-
- return (ret);
}
/* If priv parent gets a TERM or HUP, pass it through to child instead */