This article describes the following topics:
- What resource limitations to consider for different environments
- Popular ulimit attributes
- Shell restriction
- Disk quotas
What limitations should be imposed?
When deciding on limits for a user, try to consider the type of account and what the account is being used for. For example, if it is an application owner account, serious consideration must be undertaken on increasing some of the ulimit settings, as you do not want error messages complaining about lack of open files or unable to write large data (amounts) to a disk. What seems to be quite an occurrence in the last few years is running out of memory. The need to raise the RSS (memory) due to a low ulimit restriction is quite a regular task. If the account is a third-party support who just wants to review logs files, then I would not be looking at ulimit resources, but rather a limit on where the user can wander around the system. I would consider a restricted shell, or a chroot Secure File Transfer Protocol (SFTP) or File Transfer Protocol (FTP) environment. If the user account was an internal support person, well they are pretty much going to try and convince you that they require unlimited resources to support this application. Certainly consider increasing the core dumps and the file size values for these types of users first.
Be realistic on what resources they get, so often you hear a call for ulimited access. It is so easy to apply a quick fix and give developers unlimited resources but take a moment of pause before going down this path. Before long, you will have many accounts with unlimited resource limits. At best, this will affect the performance of the system trying to allocate the resources, and at worst, the system could come down to its knees.
What ulimits do I have set?
Reviewing the defaults limits stanza in /etc/security/limits. These are the default settings that the user login account will use. However, these values can be overridden by specifying different ulimit values on a per user basis. Each user will have a separate stanza if any of the default values are overridden for a user. These ulimit values can be changed through System Management Interface Tool (SMIT) or chuser, or manually editing the limits file. There are two types of ulimit values, soft and hard. The soft values are displayed using the
ulimit –a command. These values can be changed by the user; however, there must be a limit to how far a user can increase their own ulimits, and this is where the hard values come into play. A user cannot go above the hard limit value, and only the root user can change that. To give a user unlimited ulimit values, the root user specifies the new values as '-1'.
To see the soft ulimits, use:
To see the hard ulimits, use:
Let's now demonstrate how a ulimit can affect normal user processing. Below is the soft file limit for a user. Note that the fsize is the maximum size in total that a user can write in to a file. In the following example, this is currently set to 2097151 512 K blocks, about 1 GB.
$ ulimit -f 2097151
Now, if the user tries to create a 900 MB file, all should be fine because the user's ulimit setting for fsize allows that.
$ dd if=/dev/zero of=filename bs=1 count=0 seek=900M 0+0 records in. 0+0 records out.
Now, if we create a 2 GB file, it will be refused.
$ dd if=/dev/zero of=filename2 bs=1 count=0 seek=2G dd: filename2: A file cannot be larger than the value set by ulimit. dd: filename2: A file cannot be larger than the value set by ulimit.
By setting the fsize to around 3 GB ,the above 2 GB file can now be generated by the user:
# chuser fsize=6291453 dxtans $ ulimit -f unlimited
Note in the above example, I did not go down the easy path and set the fsize to ulimited (-1); rather, I set it to a sensible value that was required for the processing to complete.
$ dd if=/dev/zero of=filename2 bs=1 count=0 seek=2G 0+0 records in. 0+0 records out.
Of course, this is all well and good where a user can view the ulimit setting, consider though an application account that is failing due to some ulimit issues. How can you tell what the ulimits are from a running process? Well, there is not any clean method available, and the only one I recall is using the
dbx command, a source file debugger utility. Unfortunately, this has the side effect of killing the process after you exit dbx. First, obtain the process identification number (PID) of the required process, and then use
dbx to interrogate it using the
proc limit command.
# ps -ef |grep collector dxtans 2961626 2941074 0 13:04:07 pts/0 0:00 collector # dbx -a 2961626 Waiting to attach to process 2961626 ... Successfully attached to collector. warning: Directory containing collector could not be determined. Apply 'use' command to initialize source path. Type 'help' for help. reading symbolic information ...warning: no source compiled with -g stopped in read at 0xd0398168 0xd0398168 (read+0x1a8) 80410014 lwz r2,0x14(r1) (dbx) proc rlimit rlimit name: rlimit_cur rlimit_max (units) RLIMIT_CPU: (unlimited) (unlimited) sec RLIMIT_FSIZE: (unlimited) (unlimited) bytes RLIMIT_DATA: 134217728 (unlimited) bytes RLIMIT_STACK: 33554432 (unlimited) bytes RLIMIT_CORE: (unlimited) (unlimited) bytes RLIMIT_RSS: 33554432 (unlimited) bytes RLIMIT_AS: (unlimited) (unlimited) bytes RLIMIT_NOFILE: 65535 (unlimited) descriptors (dbx) quit
From the above output, we can see the current running ulimits of a process. However, when you exit dbx, the process will be killed. Of course, the process could be stopped cleanly first, before exiting dbx.
Restricting shell and FTP
When there is a need to implement a more restrictive shell environment, one possibility is to implement the restricted shell. This is simple enough, right? Select the restricted shell you want to use by making sure that it is in: /etc/security/login.cfg. Then, use the chuser command to change the account to the restricted shell required. The user is now restricted. That is only going to work with a novice user, and not for an experienced user. All they have to do is type in another SHELL like bash (assuming that it is installed) and they are no longer restricted. To fully put a user in a restrictive shell environment, point their PATH to a BIN directory located outside of the user's HOME directory where there are links to commands that the account can only run. That is the only sure way to lock a user down in a restrictive SHELL. To impose a chroot, FTP is an easy process (thanks to the IBM® AIX® /etc/ftpaccess.ctl file). First create the user and then assign the user as a puseronly in /etc/ftpaccess.ctl, using the following format. The change is dynamic and the user will be able to change out of their HOME directory:
There are other restrictive words that can put in the file, but for a basic
chroot in their HOME directory, that will do it.
Enforcing disk quotas
One sensible method of controlling disk usage is to use disk quotas based on the limit parameters you set. This is a popular method in controlling the disk space that a user can use. Within my environment, we have a lot of machines and a lot of developers. So, if I did not enforce quotas, the HOME file system would be full on those development hosts most days. The amount of times you catch developers trying to hide database dumps in their HOME directory seems to be a normal practice. I find it beneficial also from a housekeeping point of view to use disk quota on log directories that the developers use, mainly because this is their second choice when trying to keep files on the system when they are about to breach their quota limit in their HOME directory.
Enforcing restriction on processes and the environment helps to keep your housekeeping to a minimal (there are no two ways about that). It is also a good standard to have across your development boxes, as it requires only less work on your part in clearing up files.