Linux multi-user security - attack prevention with ulimit.

Published: Thursday, 30 May 2010 16:32

In the lastarticle [ Multi-user Linux security - insider resource attacks ] I discussed several methods an attacker with user-level access to a multi-user Linux environment could use to cause harm through forms of Denial of Service (Dos). As noted, everything I mentioned had the theme of resource wastage. To combat this issue, it is necessary for the administrator to restrict users to reasonable parameters that, if done correctly, the average user will not notice.

Fortunately Linux offers the 'ulimit' command, which specifies "user limits". This command can set maximum limits for everything from process count to virtual memory and stack size. It is up to you to select the correct values to keep all users happy - dont just divide resources into the number of users you have. How many users will be logged in at any time? Do certain users need to be garunteed a specific amount of RAM? Do some applications utilise hundreds of small forks?

Starting ulimit

There are several methods avaiable depending upon your situation. I'd advise you to use #1 if possible.

In the remainder of this article I shall describe using the following on the command line (basis of option 3). Converting this knowledge to changing the config files (if you chose #1 or #2), should be fairly straight forward.

  1. ulimit

The command is used in the following manner;

  1. ulimit [-acdfHlmnpsStuv] [limit]

The lower case characters mainly represent limits that can be changed, the capital 'H' and 'S' stand for HARD and SOFT limits respectively. Not entering either of these is the same as entering both of them.

Note that ulimit is a built-in shell command, so some shells may not support it, others may do it differently. On my FreeBSD machine, I need to use;

  1. limits

If you want to alter ulimit limits through a programs code, then check out;

  1. info ulimit

Hard and Soft Limits

When browsing limits config files, or other resources on the internet, you will notice the use of 'hard' (maximum) and 'soft' (current) limits. Hard limits are kernel settings, which cannot be exceeded (and obviously cannot be set above the kernel's maximum allowed value). Soft limits can be modified by users, as long as they are within the bounds of the hard limit.

More precisely, to quote the manual;

"current limit"

The current limit is the value the system will not allow usage to
exceed. It is also called the "soft limit" because the process
being limited can generally raise the current limit at will.

"maximum limit"
The maximum limit is the maximum value to which a process is
allowed to set its current limit. It is also called the "hard
limit" because there is no way for a process to get around it. A
process may lower its own maximum limit, but only the superuser
may increase a maximum limit.

View All Limits

Before you begin, run;

  1. ulimit -a

This will display all limits on your system. Be weary of 'unlimited'. On a single user (i.e. Desktop) system, this may be fine, but probably not so on a server.

Preventing Fok-Bombs: Setting Process Limits

Fortunately, setting a maximum number of processes allowed to be created for a particular user is fairly trivial. If configured correctly, the fork bomb will only be able to affect the user that initiated the attack.

To find the current maximum number of processes allowed per user, use the following command;

  1. ulimit -u

This should be a reasonable number, much less than a thousand, certainly not 'unlimited'! I usually restrict normal users to about 200 processes, as I am writing this I am using 36 processes, and have a few terminals, email, browsers etc running (on a Desktop machine) To set the value;

  1. ulimit -u 200

Max Memory

I think this is quite an important one to set as it is easy to abuse memory accidentally. The memory leak shown in the last article is all too commonly displayed in commercial software, let alone workstation systems used to develop new software.

The flag for this is -l

Max File Size

The set-max-filesize flag is -f. Again, a desktop machine might not be too much of an issue, and can sometimes be more of a hindrance than help. I used to have mine set to 5GB, but handling large backups was then restricted.

All ulimit Flags

Here is a list of all of the ulimit flags taken from the manual. I have given the basic usage above, now experiment with the values and see what works best for your environment.

-a All current limits are reported.
-c The maximum size of core files created.
-d The maximum size of a process's data segment.
-f The maximum size of files created by the shell(default option)
-l The maximum size that may be locked into memory.
-m The maximum resident set size.
-n The maximum number of open file descriptors.
-p The pipe buffer size.
-s The maximum stack size.
-t The maximum amount of cpu time in seconds.
-u The maximum number of processes available to a single user.
-v The maximum amount of virtual memory available to the process.

Note that all values exacpt those below use the '1024' scale (e.g. 1Kb = 1024 bytes)

-t is in seconds.
-p is in 512 byte increments.
-n and -u are integers (normal numbers).