drivers/base: Fix length checks in create_syslog_header()/dev_vprintk_emit()
authorBen Hutchings <ben@decadent.org.uk>
Tue, 26 Aug 2014 07:34:44 +0000 (00:34 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Sep 2014 05:55:15 +0000 (22:55 -0700)
snprintf() returns the number of bytes that could have been written
(excluding the null), not the actual number of bytes written.  Given a
long enough subsystem or device name, these functions will advance
beyond the end of the on-stack buffer in dev_vprintk_exit(), resulting
in an information leak or stack corruption.  I don't know whether such
a long name is currently possible.

In case snprintf() returns a value >= the buffer size, do not add
structured logging information.  Also WARN if this happens, so we can
fix the driver or increase the buffer size.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/base/core.c

index 20da3ad1696b58ef6aa6a91830070063e1dc21d7..28b808c73e8ed14344472188794b94a14efea72f 100644 (file)
@@ -2007,6 +2007,8 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
                return 0;
 
        pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys);
+       if (pos >= hdrlen)
+               goto overflow;
 
        /*
         * Add device identifier DEVICE=:
@@ -2038,7 +2040,14 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
                                "DEVICE=+%s:%s", subsys, dev_name(dev));
        }
 
+       if (pos >= hdrlen)
+               goto overflow;
+
        return pos;
+
+overflow:
+       dev_WARN(dev, "device/subsystem name too long");
+       return 0;
 }
 
 int dev_vprintk_emit(int level, const struct device *dev,