Do not leak syslog_mutex on cancellation.

Make syslog(3) resilent to cancellation occuring in supported deferred
mode.  Code must unlock syslog_mutex on cancel, install the cleanup
handler.

Diagnosed and tested by:	eugen
Discussed with:	dchagin
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2017-06-17 11:29:59 +00:00
parent 746e20fdb1
commit f3990417c5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=320052

View File

@ -129,8 +129,8 @@ syslog(int pri, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
void static void
vsyslog(int pri, const char *fmt, va_list ap) vsyslog1(int pri, const char *fmt, va_list ap)
{ {
int cnt; int cnt;
char ch, *p; char ch, *p;
@ -151,13 +151,9 @@ vsyslog(int pri, const char *fmt, va_list ap)
saved_errno = errno; saved_errno = errno;
THREAD_LOCK();
/* Check priority against setlogmask values. */ /* Check priority against setlogmask values. */
if (!(LOG_MASK(LOG_PRI(pri)) & LogMask)) { if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
THREAD_UNLOCK();
return; return;
}
/* Set default facility if none specified. */ /* Set default facility if none specified. */
if ((pri & LOG_FACMASK) == 0) if ((pri & LOG_FACMASK) == 0)
@ -167,10 +163,8 @@ vsyslog(int pri, const char *fmt, va_list ap)
tbuf_cookie.base = tbuf; tbuf_cookie.base = tbuf;
tbuf_cookie.left = sizeof(tbuf); tbuf_cookie.left = sizeof(tbuf);
fp = fwopen(&tbuf_cookie, writehook); fp = fwopen(&tbuf_cookie, writehook);
if (fp == NULL) { if (fp == NULL)
THREAD_UNLOCK();
return; return;
}
/* Build the message. */ /* Build the message. */
(void)time(&now); (void)time(&now);
@ -200,7 +194,6 @@ vsyslog(int pri, const char *fmt, va_list ap)
fmt_fp = fwopen(&fmt_cookie, writehook); fmt_fp = fwopen(&fmt_cookie, writehook);
if (fmt_fp == NULL) { if (fmt_fp == NULL) {
fclose(fp); fclose(fp);
THREAD_UNLOCK();
return; return;
} }
@ -285,10 +278,8 @@ vsyslog(int pri, const char *fmt, va_list ap)
*/ */
disconnectlog(); disconnectlog();
connectlog(); connectlog();
if (send(LogFile, tbuf, cnt, 0) >= 0) { if (send(LogFile, tbuf, cnt, 0) >= 0)
THREAD_UNLOCK();
return; return;
}
/* /*
* if the resend failed, fall through to * if the resend failed, fall through to
* possible scenario 2 * possible scenario 2
@ -303,15 +294,11 @@ vsyslog(int pri, const char *fmt, va_list ap)
if (status == CONNPRIV) if (status == CONNPRIV)
break; break;
_usleep(1); _usleep(1);
if (send(LogFile, tbuf, cnt, 0) >= 0) { if (send(LogFile, tbuf, cnt, 0) >= 0)
THREAD_UNLOCK();
return; return;
}
} }
} else { } else
THREAD_UNLOCK();
return; return;
}
/* /*
* Output the message to the console; try not to block * Output the message to the console; try not to block
@ -333,10 +320,25 @@ vsyslog(int pri, const char *fmt, va_list ap)
(void)_writev(fd, iov, 2); (void)_writev(fd, iov, 2);
(void)_close(fd); (void)_close(fd);
} }
}
static void
syslog_cancel_cleanup(void *arg __unused)
{
THREAD_UNLOCK(); THREAD_UNLOCK();
} }
void
vsyslog(int pri, const char *fmt, va_list ap)
{
THREAD_LOCK();
pthread_cleanup_push(syslog_cancel_cleanup, NULL);
vsyslog1(pri, fmt, ap);
pthread_cleanup_pop(1);
}
/* Should be called with mutex acquired */ /* Should be called with mutex acquired */
static void static void
disconnectlog(void) disconnectlog(void)
@ -423,9 +425,11 @@ openlog_unlocked(const char *ident, int logstat, int logfac)
void void
openlog(const char *ident, int logstat, int logfac) openlog(const char *ident, int logstat, int logfac)
{ {
THREAD_LOCK(); THREAD_LOCK();
pthread_cleanup_push(syslog_cancel_cleanup, NULL);
openlog_unlocked(ident, logstat, logfac); openlog_unlocked(ident, logstat, logfac);
THREAD_UNLOCK(); pthread_cleanup_pop(1);
} }