duplicate PID fix for 2.4

duplicate PID fix for 2.4

Post by Takayoshi Koch » Fri, 11 Apr 2003 10:20:04


We found a problem that after a full pid situation occurs,
duplicate pids may be allocated.  A patch is attached to
this mail.  This happens only on 2.4.

Marcelo, please apply.

The detail is described below:

In get_pid(), a free pid is searched through all task_structs
even when there is no free pid.  If all pids are already allocated,
the kernel exits the loop with 'next_safe' untouched.

        if(last_pid >= next_safe) {
                next_safe = PID_MAX;
        for_each_task(p) {
                if(p->pid == last_pid        ||
                   p->pgrp == last_pid       ||
                   p->tgid == last_pid       ||
                   p->session == last_pid) {                 <= (A)
                        if(++last_pid >= next_safe) {                <= (B)
                                if(last_pid & 0xffff8000)
                                        last_pid = 300;
                                next_safe = PID_MAX;
                        if(unlikely(last_pid == beginpid))      <= (C)
                                goto nomorepids;
                        goto repeat;

In a rare case, both (B) and (C) can be true and then, next_safe
will remain PID_MAX (32768).  In that case, following get_pid() will
always succeed until last_pid reaches 32768 and there may be duplicate

When this happens?

As 'beginpid' is the pid of the process that created by the last fork(),
the task_struct of that process should be located at the tail of
the task_struct list.  So one might think that if (C) is true,
all the task_structs are scanned and (B) will never be possible
on the ground that when we are all through the task_struct list,
next_safe shuould be beginpid+1.

But this assumption is wrong because in (B), last_pid is
pre-incremented so in (A), last_pid == beginpid-1.
If the PID=beginpid-1 process is on very early in
the task_struct list, (B) is possible.

To protect this case is simple: when the condition (C) is true,
set next_safe to 0 or any safe value to guarantee that a free pid
will be searched through next time.  Or simply move (C) before (B),
which also guarantees next time search because at that point
next_safe is beginpid+1.

We prefer the former because it explicitly sets next_safe
so that the next time search is guaranteed.


[ fork.c.diff < 1K ]
--- linux-2.4.20/kernel/fork.c.orig     Wed Apr  9 16:48:19 2003

                                                last_pid = 300;
                                        next_safe = PID_MAX;
-                               if(unlikely(last_pid == beginpid))
+                               if(unlikely(last_pid == beginpid)) {
+                                       next_safe = 0;
                                        goto nomorepids;
+                               }
                                goto repeat;
                        if(p->pid > last_pid && next_safe > p->pid)


1. 2.4: Fix duplicate #include in journal.c

--- linux-2.4-ext3push/fs/jbd/journal.c.=K0002=.orig    2003-03-25 10:59:15.000000000 +0000

 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <linux/proc_fs.h>

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

2. VPN (pptp + pppd using PAP)

3. 2.4: Minor build fix for ext3 (2.4 and 2.5)

4. Linux as a server to two win95b machines?

5. 2.4 iget5_locked port attempt to 2.4 (supposedly fixed NFS version this time)

6. pppd - cannot overwrite device name...

7. Solaris 2.4 Boot Manager/How do I duplicate that floppy?

8. qprt command

9. Duplicate pids

10. Resend: 2.4 PCMCIA linear flash memory card fix

11. misc_register() fix (was Re: Linux 2.4.2ac8

12. hamachi PCI DMA fix from 2.4

13. fsync fixes for 2.4