xorl %eax, %eax

GRKERNSEC_FLOODTIME and GRKERNSEC_FLOODBURST Logging Flood Control

with 2 comments

This is another neat feature that is described like this:

config GRKERNSEC_FLOODTIME
	int "Seconds in between log messages (minimum)"
	default 10
	help
	  This option allows you to enforce the number of seconds between
	  grsecurity log messages.  The default should be suitable for most
	  people, however, if you choose to change it, choose a value small enough
	  to allow informative logs to be produced, but large enough to
	  prevent flooding.

Believe it or not this is very useful since log flooding was always being used by attackers to hide a suspicious message inside tons of useless ones. Personally, I’m aware of at least a single exploit that used this technique because it was triggering some *very* suspicious messages. So, here is how this works…

static int gr_log_start(int audit)
{
	char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT;
	char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt;
	char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;

	if (audit == GR_DO_AUDIT)
		goto set_fmt;

	if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) {
		grsec_alert_wtime = jiffies;
		grsec_alert_fyet = 0;
	} else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) {
		grsec_alert_fyet++;
	} else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) {
		grsec_alert_wtime = jiffies;
		grsec_alert_fyet++;
		printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME);
		return FLOODING;
	} else return FLOODING;

set_fmt:
	memset(buf, 0, PAGE_SIZE);
	if (current->signal->curr_ip && gr_acl_is_enabled()) {
		sprintf(fmt, "%s%s", loglevel, "grsec: From %pI4: (%.64s:%c:%.950s) ");
		snprintf(buf, PAGE_SIZE - 1, fmt, &current->signal->curr_ip, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
	} else if (current->signal->curr_ip) {
		sprintf(fmt, "%s%s", loglevel, "grsec: From %pI4: ");
		snprintf(buf, PAGE_SIZE - 1, fmt, &current->signal->curr_ip);
	} else if (gr_acl_is_enabled()) {
		sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) ");
		snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
	} else {
		sprintf(fmt, "%s%s", loglevel, "grsec: ");
		strcpy(buf, fmt);
	}

	return NO_FLOODING;
}

The above routine is part of grsecurity/grsec_log.c file and it uses a simple ‘if’ clause to check the current time (based on the jiffies’ value) and the time of the alert against the constant value ‘CONFIG_GRKERNSEC_FLOODTIME’ which by default is set to 10.
Additionally, you can also read another interesting check. If there is a flood going on and the ‘grsec_alert_fyet’ is less than ‘CONFIG_GRKERNSEC_FLOODBURST’ it will keep incrementing until it reaches a value equal to ‘CONFIG_GRKERNSEC_FLOODBURST’. When this is done it will stop logging for ‘CONFIG_GRKERNSEC_FLOODTIME’ seconds. The second constant value you saw above is described like this:

config GRKERNSEC_FLOODBURST
	int "Number of messages in a burst (maximum)"
	default 4
	help
	  This option allows you to choose the maximum number of messages allowed
	  within the flood time interval you chose in a separate option.  The
	  default should be suitable for most people, however if you find that
	  many of your logs are being interpreted as flooding, you may want to
	  raise this value.

Where the default value is 4. Based on grsecurity’s default values if a system attempts to print 4 messages in an interval of 10 seconds it will disable logging for 10 seconds. Finally, this function is called from the grsecurity’s generic printing routine gr_log_varargs().

void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
{
	int logtype;
	char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
	char *str1, *str2, *str3;
	void *voidptr;
	int num1, num2;
	unsigned long ulong1, ulong2;
	struct dentry *dentry;
	struct vfsmount *mnt;
	struct file *file;
	struct task_struct *task;
	const struct cred *cred, *pcred;
	va_list ap;

	BEGIN_LOCKS(audit);
	logtype = gr_log_start(audit);
	if (logtype == FLOODING) {
		END_LOCKS(audit);
		return;
	}
	va_start(ap, argtypes);
	switch (argtypes) {
   ...
	va_end(ap);
	gr_log_end(audit);
	END_LOCKS(audit);
}

I believe that many people will argue that having a log flood is better than disabling log for a specified time but in my opinion, depending on the usage of the system you can tune those values and have some great results.

Written by xorl

November 9, 2010 at 11:48

Posted in grsecurity, linux, security

2 Responses

Subscribe to comments with RSS.

  1. hello :)
    you are back :)

    clnoe

    November 10, 2010 at 13:21

  2. GRKERNSEC_FLOODBURST and GRKERNSEC_FLOODTIME are dangerous.
    the default option allows for an attacker to do the following:

    1) flood
    2) grsec switches to silent mode (writing into the logfile that flood suppression is now enabled)
    3) attack the system
    4) no logs of the attack are stored

    Alex

    March 7, 2012 at 13:56


Leave a comment