diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-01-01 19:15:01 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-01-01 19:15:01 +0000 |
commit | 83f5882af755032571414f596eb15869bd9de709 (patch) | |
tree | 7415aed3e71b5b87d8b98917ea6376f2223dcbe7 | |
parent | b382e61582a45577e4905f1bcf51efe160423542 (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.c | 63 |
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); } |