Re: limit maximum nr. of processes.

From: Alfonso Lazaro (altellezat_private)
Date: Fri Sep 03 1999 - 04:18:02 PDT

  • Next message: Jared Mauch: "Re: Local DoS in FreeBSD"

    El dia Wed, Sep 01, 1999 at 10:53:48AM +0200, Petter Wahlman <petterat_private> 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
    > bactusat_private
    >
    > #define QUESTION ((bb) || !(bb))  - Shakespeare.
    > echo '16i[q]sa[ln0=aln100%Pln100/snlbx]sbA6E616D6C68615720726574746550snlbxq'|dc
    > ________________________________________________________________________________
    
    > /***************************************************************
    >  * secfork v1.0a - petter wahlman <bactusat_private>
    >  *
    >  * 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 <bactusat_private>");
    > 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 <bactusat_private>..\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	altellezat_private
       Analista de seguridad	
       IP6Seguridad			http://www.ip6seguridad.com	
       Tfno: +34 91-3430245	        C\Alberto Alcocer 5, 1 D	
       Fax:  +34 91-3430294         Madrid ( SPAIN )
    ===========================================================			
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:01:36 PDT