Bugtraq mailing list archives

Re: limit maximum nr. of processes.


From: altellez () IP6SEGURIDAD COM (Alfonso Lazaro)
Date: Fri, 3 Sep 1999 13:18:02 +0200


El dia Wed, Sep 01, 1999 at 10:53:48AM +0200, Petter Wahlman <petter () proact no> escribió:

        to limit the maximum number of processes you can use the Linux-PAM

        edit /etc/pam.d/login

        #%PAM-1.0
        auth       required     /lib/security/pam_securetty.so
        auth       required     /lib/security/pam_pwdb.so shadow nullok
        auth       required     /lib/security/pam_nologin.so
        account    required     /lib/security/pam_pwdb.so
        password   required     /lib/security/pam_cracklib.so
        password   required     /lib/security/pam_pwdb.so shadow nullok use_authtok
        session    required     /lib/security/pam_pwdb.so
        session    required     /lib/security/pam_limits.so

        you have to add the last two lines

        then edit

        /etc/security/limits.conf

        # /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain>        <type>  <item>  <value>
#
#Where:
#<domain> can be:
#        - an user name
#        - a group name, with @group syntax
#        - the wildcard *, for default entry
#
#<type> can have the two values:
#        - "soft" for enforcing the soft limits
#        - "hard" for enforcing hard limits
#
#<item> can be one of the following:
#        - core - limits the core file size (KB)
#        - data - max data size (KB)
#        - fsize - maximum filesize (KB)
#        - memlock - max locked-in-memory address space (KB)
#        - nofile - max number of open files
#        - rss - max resident set size (KB)
#        - stack - max stack size (KB)
#        - cpu - max CPU time (MIN)
#        - nproc - max number of processes
#        - as - address space limit
#        - maxlogins - max number of logins for this user
#
#<domain>      <type>  <item>         <value>
#

#*               soft    core            0
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#@student        -       maxlogins       4

        as you can see you can limit the number of process and much more
        like cpu, stack ...

        


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 () sol no

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

/***************************************************************
 * secfork v1.0a - petter wahlman <bactus () 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 () 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 () 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");
}


--
Saludos.

===========================================================

   Alfonso Lazaro Tellez        altellez () ip6seguridad com
   Analista de seguridad        
   IP6Seguridad                 http://www.ip6seguridad.com     
   Tfno: +34 91-3430245         C\Alberto Alcocer 5, 1 D        
   Fax:  +34 91-3430294         Madrid ( SPAIN )
===========================================================                     



Current thread: