Linux a nuke

Petr Sretr sretr na datis.cdrail.cz
Pátek Září 3 08:12:10 CEST 1999




> >
> main()
> {
>   for(;;) fork();
> }
>

Nezkouseli jste nekdo pouzit modul zverejneny
v konferenci BUGTRAQ
http://www.securityfocus.com/templates/archive.pike?list=1&date=1999-08-29&msg=Pine.LNX.4.10.9909010935350.26470-200000@arjuna.proact.no

viz. nize
To:
           BugTraq
 Subject:
           limit maximum nr. of processes.
 Date:
           Wed Sep 01 1999 04:53:48
 Author:
           "Petter Wahlman "
 Message-ID:
           <Pine.LNX.4.10.9909010935350.26470-200000 na arjuna.proact.no>


'lo!

i have made a loadable kernel module that lets you limit the maximum
number of processes members of the group USER_GID can execute.
this can e.g be used to prevent DoS attacks like:

int main()
{
 while(1) fork();
 return 1;
}

Setting the limit is easily done through the proc interface:

arjuna(root):fork~>cat /proc/maxprocs
gid: 500 restricted to: 40 processes

arjuna(root):fork~>echo 64 > /proc/maxprocs

arjuna(root):fork~>cat /proc/maxprocs
gid: 500 restricted to: 64 processes

[The module does currently only support v.2.2.X of the Linux kernel.]

________________________________________________________________________________

Petter Wahlman
bactus na sol.no

#define QUESTION ((bb) || !(bb))  - Shakespeare.
echo
'16i[q]sa[ln0=aln100%Pln100/snlbx]sbA6E616D6C68615720726574746550snlbxq'|dc

________________________________________________________________________________

/***************************************************************
 * secfork v1.0a - petter wahlman <bactus na sol.no>
 *
 * Limit the maximum number of processes members
 * of the group USER_GID can execute.
 *
 * compile:
 *    gcc foo.c -DMODULE -D__KERNEL__ -O2 -fomit-frame-pointer \
 *              -Wstrict-prototypes -Wall -Wunused -c -o secfork
 *
 * install:
 *              insmod secfork
 *
 * remove:
 *              rmmod secfork
 *
 * usage:
 *      echo 64 > /proc/maxprocs # set limit to 64 processes
 *
 ***************************************************************/

#ifndef __KERNEL__
#  define __KERNEL__
#endif
#ifndef MODULE
#  define MODULE
#endif

#include <linux/config.h>

#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>
char kernel_version [] = UTS_RELEASE;

/*
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
*/

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <sys/syscall.h>
#include <errno.h>

MODULE_AUTHOR("petter wahlman <bactus na sol.no>");
EXPORT_NO_SYMBOLS;

#define MAXPROCS        40
#define USER_GID        (int)500
#define MAXDATA         (int)8

static unsigned long maxprocs = MAXPROCS;
extern void *sys_call_table[];
asmlinkage int (*old_fork) (struct pt_regs);

static struct user_struct {
        long count;
        struct user_struct *next, **pprev;
        unsigned int uid;
}user_t;

/***( module_output )***/
static ssize_t module_output(struct file *file, char *buf, size_t len,
loff_t *offset)
{
 static int i, finished = 0;
 char msg[MAXDATA+50];

 if (finished) {
        finished = 0;
        return 0;
 }

 sprintf(msg, "gid: %d restricted to: %ld processes\n", USER_GID,
maxprocs);
 for(i = 0; i < len && msg[i]; i++)
        put_user(msg[i], buf+i);

 finished = 1;

 return i;
}

/***( module_input )***/
static ssize_t module_input(struct file *file, const char *buf, size_t
length, loff_t *offset)
{
 static char data[MAXDATA];
 int i;

 for (i = 0; i < sizeof(data)-1 && i < length; i++)
        get_user(data[i], buf+i);
 data[i] = '\0';

 maxprocs = simple_strtoul(data, NULL, 10);
 return i;
}

static int module_permission(struct inode *inode, int op)
{
 if (op == 4 || (op == 2 && current->euid == 0))
        return 0;

 return -EACCES;
}

int module_open(struct inode *inode, struct file *file)
{
  MOD_INC_USE_COUNT;

  return 0;
}

int module_close(struct inode *inode, struct file *file)
{
  MOD_DEC_USE_COUNT;

  return 0;
}

static struct file_operations fops = {
    NULL,                       /* lseek */
        module_output,
        module_input,
        NULL,                   /* readdir */
        NULL,                   /* select */
        NULL,                   /* ioctl */
        NULL,                   /* mmap */
        module_open,
        NULL,                   /* flush */
        module_close
};

static struct inode_operations iops =
  {
    &fops,
    NULL,                       /* create */
    NULL,                       /* lookup */
    NULL,                       /* link */
    NULL,                       /* unlink */
    NULL,                       /* symlink */
    NULL,                       /* mkdir */
    NULL,                       /* rmdir */
    NULL,                       /* mknod */
    NULL,                       /* rename */
    NULL,                       /* readlink */
    NULL,                       /* follow_link */
    NULL,                       /* readpage */
    NULL,                       /* writepage */
    NULL,                       /* bmap */
    NULL,                       /* truncate */
    module_permission
  };

static struct proc_dir_entry proc_entry =
{
    0, 8,
    "maxprocs", /* The file name */
    S_IFREG | S_IRUGO | S_IWUSR,
    1,                  /* links */
    0, 0,               /* uid, gid */
    0,  /* size */
    &iops,
    NULL                /* read function - in ino structure */
};

/***( new_fork )***/
int new_fork(struct pt_regs regs)
{
 static int n;

 if (current->uid == 0) return old_fork(regs);
 for (n = 0; n < NGROUPS; n++)
        if (current->groups[n] == USER_GID) {
                if (current->user->count >= maxprocs)
                        return -EPERM;
                else
                        return old_fork(regs);
        }
 return old_fork(regs);
}

/***( init_module ***/
int init_module(void)
{
 printk("secfork v1.0a - petter wahlman <bactus na sol.no>..\n");
 old_fork = sys_call_table[__NR_fork];
 sys_call_table[__NR_fork] = new_fork;

 return proc_register(&proc_root, &proc_entry);
}

void cleanup_module(void)
{
        sys_call_table[__NR_fork] = old_fork;
        proc_unregister(&proc_root, proc_entry.low_ino);
        printk("secfork unloaded..\n");
}




Další informace o konferenci Linux