xorl %eax, %eax

GRKERNSEC_FORKFAIL Fork Failure Logging

leave a comment »

This is another grsecurity logging feature which is described by this:

config GRKERNSEC_FORKFAIL
	bool "Fork failure logging"
	help
	  If you say Y here, all failed fork() attempts will be logged.
	  This could suggest a fork bomb, or someone attempting to overstep
	  their process limit.  If the sysctl option is enabled, a sysctl option
	  with name "forkfail_logging" is created.

As the description suggests, the most common local DoS was/(is?) the fork() bomb but also this assists in identifying attempts to bypass resource limits. The code is a very simple logging routine located at grsecurity/grsec_fork.c like this:

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/grsecurity.h>
#include <linux/grinternal.h>
#include <linux/errno.h>

void
gr_log_forkfail(const int retval)
{
#ifdef CONFIG_GRKERNSEC_FORKFAIL
	if (grsec_enable_forkfail && (retval == -EAGAIN || retval == -ENOMEM)) {
		switch (retval) {
			case -EAGAIN:
				gr_log_str(GR_DONT_AUDIT, GR_FAILFORK_MSG, "EAGAIN");
				break;
			case -ENOMEM:
				gr_log_str(GR_DONT_AUDIT, GR_FAILFORK_MSG, "ENOMEM");
				break;
		}
	}
#endif
	return;
}

As you can read, if the ‘grsec_enable_forkfail’ value is set and the return value passed to the function is either ‘-EAGAIN’ (Try Again) or ‘-ENOMEM’ (Out of Memory), it will execute the equivalent logging operation. Otherwise, it will just return. The sysctl option for that feature is the ‘forkfail_logging’ as we can read here:

#ifdef CONFIG_GRKERNSEC_FORKFAIL
	{
		.procname	= "forkfail_logging",
		.data		= &grsec_enable_forkfail,
		.maxlen		= sizeof(int),
		.mode		= 0600,
		.proc_handler	= &proc_dointvec,
	},
#endif

And if we look at kernel/fork.c we’ll see that this logging function is used in failed attempts of copy_process():

/*
 * This creates a new process as a copy of the old one,
 * but does not actually start it yet.
 *
 * It copies the registers, and all the appropriate
 * parts of the process environment (as per the clone
 * flags). The actual kick-off is left to the caller.
 */
static struct task_struct *copy_process(unsigned long clone_flags,
                                        unsigned long stack_start,
                                        struct pt_regs *regs,
                                        unsigned long stack_size,
                                        int __user *child_tidptr,
                                        struct pid *pid,
                                        int trace)
{
      ...
bad_fork_free:
        free_task(p);
fork_out:
        gr_log_forkfail(retval);

        return ERR_PTR(retval);
}

In order to log the event if the return value contains one of the specified error codes.

Written by xorl

November 18, 2010 at 07:33

Posted in grsecurity, linux, security

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s