Date: Fri, 2 Mar 2012 21:38:07 +0000 (UTC) From: "Justin T. Gibbs" <gibbs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r232407 - projects/zfsd/head/cddl/sbin/zfsd Message-ID: <201203022138.q22Lc7Vd048457@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gibbs Date: Fri Mar 2 21:38:06 2012 New Revision: 232407 URL: http://svn.freebsd.org/changeset/base/232407 Log: Modify ZFSD to tolerate events of arbitrary size instead of assuming that events will be no larger than 1024 bytes. This corrects an infinite loop when events larger than this size are received (e.g. when a block checksum fails). cddl/sbin/zfsd/zfsd.h: Bump the event limit up to 8K and add/rename some constants to clarify exactly what ZFSD's limits control. cddl/sbin/zfsd/zfsd.h: cddl/sbin/zfsd/zfsd.cc: o Add EventBuffer::s_keyPairSepTokens[] to make explicit the characters that can separate devctl event key=value pairs. o In EventBuffer::ExtractEvent(), truncate events to the end of the last fully received key=value pair if they are longer than the event size limit imposed by ZFSD. o Prefer syslog to warn(x) for warnings generated after becoming a daemon. Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc projects/zfsd/head/cddl/sbin/zfsd/zfsd.h Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc ============================================================================== --- projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc Fri Mar 2 21:36:24 2012 (r232406) +++ projects/zfsd/head/cddl/sbin/zfsd/zfsd.cc Fri Mar 2 21:38:06 2012 (r232407) @@ -98,6 +98,11 @@ const char EventBuffer::s_eventStartToke */ const char EventBuffer::s_eventEndTokens[] = "\n"; +/** + * Key=Value pairs are terminated by whitespace. + */ +const char EventBuffer::s_keyPairSepTokens[] = " \t\n"; + //- EventBuffer Public Methods ------------------------------------------------- EventBuffer::EventBuffer(int fd) : m_fd(fd), @@ -126,7 +131,8 @@ EventBuffer::ExtractEvent(string &eventS size_t startLen(strcspn(nextEvent, s_eventStartTokens)); bool aligned(startLen == 0); if (aligned == false) { - warnx("Re-synchronizing with devd event stream"); + syslog(LOG_WARNING, + "Re-synchronizing with devd event stream"); m_nextEventOffset += startLen; m_parsedLen = m_nextEventOffset; continue; @@ -136,26 +142,45 @@ EventBuffer::ExtractEvent(string &eventS * Start tokens may be end tokens too, so skip the start * token when trying to find the end of the event. */ + bool truncated(true); size_t eventLen(strcspn(nextEvent + 1, s_eventEndTokens) + 1); if (nextEvent[eventLen] == '\0') { - /* Ran out of buffer before hitting a full event. */ - m_parsedLen += eventLen; - continue; - } - if (nextEvent[eventLen] != '\n') { - warnx("Improperly terminated event encountered"); + m_parsedLen += eventLen; + if (m_parsedLen < MAX_EVENT_SIZE) { + /* + * Ran out of buffer before hitting + * a full event. Fill() and try again. + */ + continue; + } + syslog(LOG_WARNING, + "Event exceeds event size limit of %d bytes."); + } else if (nextEvent[eventLen] != '\n') { + syslog(LOG_WARNING, + "Improperly terminated event encountered."); } else { /* * Include the normal terminator in the extracted * event data. */ eventLen += 1; + truncated = false; } m_nextEventOffset += eventLen; m_parsedLen = m_nextEventOffset; eventString.assign(nextEvent, eventLen); + + if (truncated) { + size_t fieldEnd; + + fieldEnd = eventString.find_last_of(s_keyPairSepTokens); + eventString.erase(fieldEnd); + syslog(LOG_WARNING, + "Truncated %d characters from event.", + eventLen - fieldEnd); + } return (true); } return (false); Modified: projects/zfsd/head/cddl/sbin/zfsd/zfsd.h ============================================================================== --- projects/zfsd/head/cddl/sbin/zfsd/zfsd.h Fri Mar 2 21:36:24 2012 (r232406) +++ projects/zfsd/head/cddl/sbin/zfsd/zfsd.h Fri Mar 2 21:38:06 2012 (r232407) @@ -119,21 +119,27 @@ private: */ MIN_EVENT_SIZE = 2, + /* + * The maximum event size supported by ZFSD. + * Events larger than this size (minus 1) are + * truncated at the end of the last fully received + * key/value pair. + */ + MAX_EVENT_SIZE = 8192, + /** * The maximum amount of buffer data to read at * a single time from the Devd file descriptor. - * This size matches the largest event size allowed - * in the system. */ - MAX_READ_SIZE = 1024, + MAX_READ_SIZE = MAX_EVENT_SIZE, /** * The size of EventBuffer's buffer of Devd event data. - * This is one larger than the maximum event size which - * alows us to always include a terminating NUL without - * overwriting any received data. + * This is one larger than the maximum supported event + * size, which alows us to always include a terminating + * NUL without overwriting any received data. */ - EVENT_BUFSIZE = MAX_READ_SIZE + /*NUL*/1 + EVENT_BUFSIZE = MAX_EVENT_SIZE + /*NUL*/1 }; /** The amount of data in m_buf we have yet to look at. */ @@ -151,6 +157,9 @@ private: /** Characters we treat as ending an event string. */ static const char s_eventEndTokens[]; + /** Characters found between successive "key=value" strings. */ + static const char s_keyPairSepTokens[]; + /** Temporary space for event data during our parsing. */ char m_buf[EVENT_BUFSIZE];
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203022138.q22Lc7Vd048457>