GRKERNSEC_FLOODTIME and GRKERNSEC_FLOODBURST Logging Flood Control
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, ¤t->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, ¤t->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.
hello :)
you are back :)
clnoe
November 10, 2010 at 13:21
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