[BACK]Return to debug.c CVS log [TXT][DIR] Up to [Development] / xfs-linux / support

File: [Development] / xfs-linux / support / debug.c (download)

Revision 1.35, Wed Nov 29 02:51:22 2006 UTC (10 years, 10 months ago) by lachlan.longdrop.melbourne.sgi.com
Branch: MAIN
Changes since 1.34: +13 -10 lines

Prevent buffer overrun in cmn_err().

The message buffer used by cmn_err() is only 256 bytes and some CXFS
messages were exceeding this length.  Since we were using vsprintf()
and not checking for buffer overruns we were clobbering memory beyond
the buffer.  The size of the buffer has been increased to 1024 bytes
so we can capture these larger messages and we are now using vsnprintf()
to prevent overrunning the buffer size.
Merge of xfs-linux-melb:xfs-kern:27561a by kenmcd.

  Prevent buffer overrun in cmn_err() by using vsnprintf() and increase
  buffer size to 1024 bytes.

/*
 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <xfs.h>
#include "debug.h"
#include "spin.h"
#include <asm/page.h>
#include <linux/sched.h>
#include <linux/kernel.h>

static char		message[1024];	/* keep it off the stack */
static DEFINE_SPINLOCK(xfs_err_lock);

/* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */
#define XFS_MAX_ERR_LEVEL	7
#define XFS_ERR_MASK		((1 << 3) - 1)
static const char * const	err_level[XFS_MAX_ERR_LEVEL+1] =
					{KERN_EMERG, KERN_ALERT, KERN_CRIT,
					 KERN_ERR, KERN_WARNING, KERN_NOTICE,
					 KERN_INFO, KERN_DEBUG};

void
cmn_err(register int level, char *fmt, ...)
{
	char	*fp = fmt;
	int	len;
	ulong	flags;
	va_list	ap;

	level &= XFS_ERR_MASK;
	if (level > XFS_MAX_ERR_LEVEL)
		level = XFS_MAX_ERR_LEVEL;
	spin_lock_irqsave(&xfs_err_lock,flags);
	va_start(ap, fmt);
	if (*fmt == '!') fp++;
	len = vsnprintf(message, sizeof(message), fp, ap);
	if (len >= sizeof(message))
		len = sizeof(message) - 1;
	if (message[len-1] == '\n')
		message[len-1] = 0;
	printk("%s%s\n", err_level[level], message);
	va_end(ap);
	spin_unlock_irqrestore(&xfs_err_lock,flags);
	BUG_ON(level == CE_PANIC);
}

void
icmn_err(register int level, char *fmt, va_list ap)
{
	ulong	flags;
	int	len;

	level &= XFS_ERR_MASK;
	if(level > XFS_MAX_ERR_LEVEL)
		level = XFS_MAX_ERR_LEVEL;
	spin_lock_irqsave(&xfs_err_lock,flags);
	len = vsnprintf(message, sizeof(message), fmt, ap);
	if (len >= sizeof(message))
		len = sizeof(message) - 1;
	if (message[len-1] == '\n')
		message[len-1] = 0;
	printk("%s%s\n", err_level[level], message);
	spin_unlock_irqrestore(&xfs_err_lock,flags);
	BUG_ON(level == CE_PANIC);
}

void
assfail(char *expr, char *file, int line)
{
	printk("Assertion failed: %s, file: %s, line: %d\n", expr, file, line);
	BUG();
}

#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM))
unsigned long random(void)
{
	static unsigned long	RandomValue = 1;
	/* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */
	register long	rv = RandomValue;
	register long	lo;
	register long	hi;

	hi = rv / 127773;
	lo = rv % 127773;
	rv = 16807 * lo - 2836 * hi;
	if (rv <= 0) rv += 2147483647;
	return RandomValue = rv;
}
#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */