1

I know of the sysinfo() function that returns a procs parameter representing the total number of processes currently running on your Linux system.

However, there is the RLIMIT_NPROC parameter to the setrlimit() and getrlimit() function that limit the number of child processes a process can have.

In order for the system to enforce that number, I would imagine it knows the current number of processes in that group. Is that number readily accessible?

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • Well you can know the number of processes you actually spawned by the number of successfull `fork()` syscalls you have made... You only have to count them each time that forks returns `0` and you have it. If you also account for the number of successful `wait(2)` calls you do, you'll have the total number of processes you created, the number active (just substract them) and the number of processes that have finished. – Luis Colorado Oct 17 '16 at 07:08
  • By the way, knowing the number of processes you have not actually forked, imposes a security issue in your system. – Luis Colorado Oct 17 '16 at 07:09

2 Answers2

1

To enforce the RLIMIT_NPROC limit, linux kernel reads &p->real_cred->user->processes field in copy_process function (on fork() for example) http://lxr.free-electrons.com/source/kernel/fork.c?v=4.8#L1371

 1371         if (atomic_read(&p->real_cred->user->processes) >=
 1372                         task_rlimit(p, RLIMIT_NPROC)) {

or in sys_execve (do_execveat_common in fs/exec.c):

1504    if ((current->flags & PF_NPROC_EXCEEDED) &&
1505        atomic_read(&current_user()->processes) > rlimit(RLIMIT_NPROC)) {
1506        retval = -EAGAIN;
1507        goto out_ret;

So, if the processes is larger than RLIMIT_NPROC, function will fail. This field is defined as part of struct user_struct (accessed with struct cred real_cred in sched.h as

 atomic_t processes;    /* How many processes does this user have? */

So the process count accounting is per-user.

There is decrement of the field in copy_process in case of fail:

1655 bad_fork_cleanup_count:
1656    atomic_dec(&p->cred->user->processes);

And increment of the field is in copy_cred: http://code.metager.de/source/xref/linux/stable/kernel/cred.c#313

313 /*
314 * Copy credentials for the new process created by fork()
315 *
316 * We share if we can, but under some circumstances we have to generate a new
317 * set.
318 *
319 * The new process gets the current process's subjective credentials as its
320 * objective and subjective credentials
321 */
322 int copy_creds(struct task_struct *p, unsigned long clone_flags)

339         atomic_inc(&p->cred->user->processes);

372 atomic_inc(&new->user->processes);

man page says that it is per-user limit: http://man7.org/linux/man-pages/man2/setrlimit.2.html

   RLIMIT_NPROC
          The maximum number of processes (or, more precisely on Linux,
          threads) that can be created for the real user ID of the
          calling process.  Upon encountering this limit, fork(2) fails
          with the error EAGAIN.
osgx
  • 90,338
  • 53
  • 357
  • 513
  • Ah. I did not read that properly. I always though it was per "group of processes" and not per user. That changes the deal altogether. Now you do not present a function to go read that `p->real_cred->user->processes`, I suppose there are none? Although if it is a process field, it could be availble/possible to access it? – Alexis Wilke Oct 16 '16 at 00:37
  • 1
    @AlexisWilke, I see no read of this in `fs/proc`: http://code.metager.de/source/search?q=processes&defs=&refs=&path=%2Flinux%2Fstable%2Ffs%2Fproc&hist=&type=; no reads in fs/kernel too: http://code.metager.de/source/search?q=processes&defs=&refs=&path=%2Flinux%2Fstable%2Fkernel&hist=&type= (neither in cred.c). /proc and /sys files are usually implemented here. You can try to implement your own kernel module to export this value somewhere (list of ways to interact with kernel & modules - http://stackoverflow.com/a/10816922/196561); Or ask in linux kernel mailing list? – osgx Oct 16 '16 at 03:13
0

I don't think your last statement is necessarily true. There could be more processes in a group than RLIMIT_NPROC, for example if child processes create children of their own. These are all in the same group, despite none having violated the limit.

But regardless, you could definitely get the information by reading and parsing the procfs. Given a process's group, you can search other /proc/<pid>/stat pseudo-files for those with the same group (pgrp line in the page.) This might be inefficient, though, or annoying to implement.

bnaecker
  • 6,152
  • 1
  • 20
  • 33
  • To enforce the RLIMIT_NPROC limit, kernel reads `&p->real_cred->user->processes` field in `copy_process` - http://lxr.free-electrons.com/source/kernel/fork.c?v=4.8#L1371 - it can be `atomic_t processes; /* How many processes does this user have? */` field of [sched.h](http://code.metager.de/source/xref/linux/stable/include/linux/sched.h#816). So the process count accounting is per-user. – osgx Oct 15 '16 at 23:28
  • or if you do an explicit `setpgrp(2)` call, you can move a live process from group to group with the restriction of they belonging to the same session id. This breaks completely the number of processes in a group link to the process hierarchy. – Luis Colorado Oct 17 '16 at 07:13
  • Yeah, I used the word "group" in my question, but really, as osgx pointed out, the `RLIMIT_NPROC` applies to a user and not a Unix group. So one would have to check all processes that belong to a certain user. Obviously, just like groups, users can move from user to user, although really only those with enough capabilities can do that. Most do not have enough rights. One can use `libprocps4` to get the list of processes in structures. – Alexis Wilke Oct 17 '16 at 07:43