summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2016-01-01 19:15:01 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2016-01-01 19:15:01 +0000
commit83f5882af755032571414f596eb15869bd9de709 (patch)
tree7415aed3e71b5b87d8b98917ea6376f2223dcbe7
parentb382e61582a45577e4905f1bcf51efe160423542 (diff)
The pointer buf is a user space string which was directly passed
to tputchar() and could crash the kernel. Better use cnwrite() in sendsyslog2() for writing to console. It takes a struct uio which does the copyin() automatically. In addition cnwrite() outputs to the real console or to a redirected one, whichever is appropriate. One drawback is that the syslog priority cannot be stripped off easily. OK deraadt@
-rw-r--r--sys/kern/subr_log.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c
index 3038e1a7d84..540412c7ac6 100644
--- a/sys/kern/subr_log.c
+++ b/sys/kern/subr_log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_log.c,v 1.34 2015/12/05 10:11:53 tedu Exp $ */
+/* $OpenBSD: subr_log.c,v 1.35 2016/01/01 19:15:00 bluhm Exp $ */
/* $NetBSD: subr_log.c,v 1.11 1996/03/30 22:24:44 christos Exp $ */
/*
@@ -59,6 +59,8 @@
#include <sys/mount.h>
#include <sys/syscallargs.h>
+#include <dev/cons.h>
+
#define LOG_RDPRI (PZERO + 1)
#define LOG_ASYNC 0x04
@@ -76,7 +78,7 @@ int log_open; /* also used in log() */
int msgbufmapped; /* is the message buffer mapped */
struct msgbuf *msgbufp; /* the mapped buffer, itself. */
struct msgbuf *consbufp; /* console message buffer. */
-struct file *syslogf;
+struct file *syslogf;
void filt_logrdetach(struct knote *kn);
int filt_logread(struct knote *kn, long hint);
@@ -380,18 +382,15 @@ sys_sendsyslog2(struct proc *p, void *v, register_t *retval)
LOG_KERN|LOG_WARNING, dropped_count,
dropped_count == 1 ? "" : "s", orig_error);
error = dosendsyslog(p, buf, MIN((size_t)len, sizeof(buf) - 1),
- SCARG(uap, flags), UIO_SYSSPACE);
- if (error) {
- dropped_count++;
- return (error);
- }
- dropped_count = 0;
+ 0, UIO_SYSSPACE);
+ if (error == 0)
+ dropped_count = 0;
}
#endif
error = dosendsyslog(p, SCARG(uap, buf), SCARG(uap, nbyte),
SCARG(uap, flags), UIO_USERSPACE);
#ifndef SMALL_KERNEL
- if (error && error != ENOTCONN) {
+ if (error) {
dropped_count++;
orig_error = error;
}
@@ -407,31 +406,15 @@ dosendsyslog(struct proc *p, const char *buf, size_t nbyte, int flags,
struct iovec *ktriov = NULL;
int iovlen;
#endif
- extern struct tty *constty;
struct iovec aiov;
struct uio auio;
- struct file *f;
size_t len;
int error;
- if (syslogf == NULL) {
- if (constty && (flags & LOG_CONS)) {
- int i;
-
- /* Skip syslog prefix */
- if (nbyte >= 4 && buf[0] == '<' &&
- buf[3] == '>') {
- buf += 4;
- nbyte -= 4;
- }
- for (i = 0; i < nbyte; i++)
- tputchar(buf[i], constty);
- tputchar('\n', constty);
- }
+ if (syslogf == NULL && (flags & LOG_CONS) == 0)
return (ENOTCONN);
- }
- f = syslogf;
- FREF(f);
+ if (syslogf)
+ FREF(syslogf);
aiov.iov_base = (char *)buf;
aiov.iov_len = nbyte;
@@ -453,9 +436,24 @@ dosendsyslog(struct proc *p, const char *buf, size_t nbyte, int flags,
#endif
len = auio.uio_resid;
- error = sosend(f->f_data, NULL, &auio, NULL, NULL, 0);
+ if (syslogf)
+ error = sosend(syslogf->f_data, NULL, &auio, NULL, NULL, 0);
+ else
+ error = cnwrite(0, &auio, 0);
if (error == 0)
len -= auio.uio_resid;
+ if (syslogf == NULL) {
+ aiov.iov_base = "\r\n";
+ aiov.iov_len = 2;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_procp = p;
+ auio.uio_offset = 0;
+ auio.uio_resid = aiov.iov_len;
+ cnwrite(0, &auio, 0);
+ }
#ifdef KTRACE
if (ktriov != NULL) {
@@ -464,6 +462,9 @@ dosendsyslog(struct proc *p, const char *buf, size_t nbyte, int flags,
free(ktriov, M_TEMP, iovlen);
}
#endif
- FRELE(f, p);
- return error;
+ if (syslogf)
+ FRELE(syslogf, p);
+ else
+ error = ENOTCONN;
+ return (error);
}