mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Correct locking and cancellation cleanup in syslog functions (bug 26100)
Properly serialize the access to the global state shared between the syslog functions, to avoid races in multithreaded processes. Protect a local allocation in the __vsyslog_internal function from leaking during cancellation.
This commit is contained in:
@ -91,14 +91,20 @@ struct cleanup_arg
|
|||||||
static void
|
static void
|
||||||
cancel_handler (void *ptr)
|
cancel_handler (void *ptr)
|
||||||
{
|
{
|
||||||
#ifndef NO_SIGPIPE
|
|
||||||
/* Restore the old signal handler. */
|
/* Restore the old signal handler. */
|
||||||
struct cleanup_arg *clarg = (struct cleanup_arg *) ptr;
|
struct cleanup_arg *clarg = (struct cleanup_arg *) ptr;
|
||||||
|
|
||||||
if (clarg != NULL && clarg->oldaction != NULL)
|
if (clarg != NULL)
|
||||||
__sigaction (SIGPIPE, clarg->oldaction, NULL);
|
{
|
||||||
|
#ifndef NO_SIGPIPE
|
||||||
|
if (clarg->oldaction != NULL)
|
||||||
|
__sigaction (SIGPIPE, clarg->oldaction, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Free the memstream buffer, */
|
||||||
|
free (clarg->buf);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free the lock. */
|
/* Free the lock. */
|
||||||
__libc_lock_unlock (syslog_lock);
|
__libc_lock_unlock (syslog_lock);
|
||||||
}
|
}
|
||||||
@ -169,9 +175,17 @@ __vsyslog_internal(int pri, const char *fmt, va_list ap,
|
|||||||
pri &= LOG_PRIMASK|LOG_FACMASK;
|
pri &= LOG_PRIMASK|LOG_FACMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare for multiple users. We have to take care: most
|
||||||
|
syscalls we are using are cancellation points. */
|
||||||
|
struct cleanup_arg clarg;
|
||||||
|
clarg.buf = NULL;
|
||||||
|
clarg.oldaction = NULL;
|
||||||
|
__libc_cleanup_push (cancel_handler, &clarg);
|
||||||
|
__libc_lock_lock (syslog_lock);
|
||||||
|
|
||||||
/* Check priority against setlogmask values. */
|
/* Check priority against setlogmask values. */
|
||||||
if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
|
if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
/* Set default facility if none specified. */
|
/* Set default facility if none specified. */
|
||||||
if ((pri & LOG_FACMASK) == 0)
|
if ((pri & LOG_FACMASK) == 0)
|
||||||
@ -235,6 +249,9 @@ __vsyslog_internal(int pri, const char *fmt, va_list ap,
|
|||||||
/* Close the memory stream; this will finalize the data
|
/* Close the memory stream; this will finalize the data
|
||||||
into a malloc'd buffer in BUF. */
|
into a malloc'd buffer in BUF. */
|
||||||
fclose (f);
|
fclose (f);
|
||||||
|
|
||||||
|
/* Tell the cancellation handler to free this buffer. */
|
||||||
|
clarg.buf = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output to stderr if requested. */
|
/* Output to stderr if requested. */
|
||||||
@ -252,22 +269,10 @@ __vsyslog_internal(int pri, const char *fmt, va_list ap,
|
|||||||
v->iov_len = 1;
|
v->iov_len = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__libc_cleanup_push (free, buf == failbuf ? NULL : buf);
|
|
||||||
|
|
||||||
/* writev is a cancellation point. */
|
/* writev is a cancellation point. */
|
||||||
(void)__writev(STDERR_FILENO, iov, v - iov + 1);
|
(void)__writev(STDERR_FILENO, iov, v - iov + 1);
|
||||||
|
|
||||||
__libc_cleanup_pop (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare for multiple users. We have to take care: open and
|
|
||||||
write are cancellation points. */
|
|
||||||
struct cleanup_arg clarg;
|
|
||||||
clarg.buf = buf;
|
|
||||||
clarg.oldaction = NULL;
|
|
||||||
__libc_cleanup_push (cancel_handler, &clarg);
|
|
||||||
__libc_lock_lock (syslog_lock);
|
|
||||||
|
|
||||||
#ifndef NO_SIGPIPE
|
#ifndef NO_SIGPIPE
|
||||||
/* Prepare for a broken connection. */
|
/* Prepare for a broken connection. */
|
||||||
memset (&action, 0, sizeof (action));
|
memset (&action, 0, sizeof (action));
|
||||||
@ -320,6 +325,7 @@ __vsyslog_internal(int pri, const char *fmt, va_list ap,
|
|||||||
__sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);
|
__sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
/* End of critical section. */
|
/* End of critical section. */
|
||||||
__libc_cleanup_pop (0);
|
__libc_cleanup_pop (0);
|
||||||
__libc_lock_unlock (syslog_lock);
|
__libc_lock_unlock (syslog_lock);
|
||||||
@ -430,8 +436,14 @@ setlogmask (int pmask)
|
|||||||
{
|
{
|
||||||
int omask;
|
int omask;
|
||||||
|
|
||||||
|
/* Protect against multiple users. */
|
||||||
|
__libc_lock_lock (syslog_lock);
|
||||||
|
|
||||||
omask = LogMask;
|
omask = LogMask;
|
||||||
if (pmask != 0)
|
if (pmask != 0)
|
||||||
LogMask = pmask;
|
LogMask = pmask;
|
||||||
|
|
||||||
|
__libc_lock_unlock (syslog_lock);
|
||||||
|
|
||||||
return (omask);
|
return (omask);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user