[PATCH] Re: get_pid() question

From: Andries Brouwer (aeb@veritas.com)
Date: Sun Jun 25 2000 - 06:02:38 EST


On Sun, Jun 25, 2000 at 12:16:23PM +0200, Manfred Spraul wrote:

> Why is the pid value limited to 15 bits on _all_ architectures?
> I read somewhere that libc5-i386 is restricted to signed short, but what
> about the other architectures?
>
> And get_pid() doesn't contain an "out of pid" detection. AFAICS one
> thread can block 3 pid values (pid, pgrp, session), we must limit the
> number of threads to 10.000 on i386.

Yes, sooner or later we'll have to change this, and probably soon
is better than late. There are some security problems with the
re-use of pids.

Last January I made the following patch, and have used it since then.
There are no problems with pids going up to many millions.

Andries

[There are no real problems with libc5 either.
This is against linux-2.3.99p9, but it applies cleanly to 2.4.0test2.]

----------------------------------------------------------------------
diff -u --recursive --new-file ../linux-2.3.99p9/linux/fs/proc/base.c ./linux/fs/proc/base.c
--- ../linux-2.3.99p9/linux/fs/proc/base.c Wed May 24 15:18:18 2000
+++ ./linux/fs/proc/base.c Wed May 24 15:23:59 2000
@@ -30,9 +30,12 @@
  * inumbers of the rest of procfs (currently those are in 0x0000--0xffff).
  * As soon as we'll get a separate superblock we will be able to forget
  * about magical ranges too.
+ *
+ * For example, the define below may be replaced by
+ * #define fake_ino(pid,ino) 0x10000
  */
 
-#define fake_ino(pid,ino) (((pid)<<16)|(ino))
+#define fake_ino(pid,ino) (((1)<<16)|(ino))
 
 ssize_t proc_pid_read_maps(struct task_struct*,struct file*,char*,size_t,loff_t*);
 int proc_pid_stat(struct task_struct*,char*);
@@ -593,7 +596,9 @@
                                 return 1;
                         p = base_stuff + i;
                         while (p->name) {
- if (filldir(dirent, p->name, p->len, filp->f_pos, fake_ino(pid, p->type)) < 0)
+ if (filldir(dirent, p->name, p->len,
+ filp->f_pos,
+ fake_ino(pid, p->type)) < 0)
                                         return 0;
                                 filp->f_pos++;
                                 p++;
@@ -604,7 +609,8 @@
 
 /* building an inode */
 
-static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino)
+static struct inode *proc_pid_make_inode(struct super_block * sb,
+ struct task_struct *task, int ino)
 {
         struct inode * inode;
 
@@ -924,9 +930,7 @@
                         goto out;
                 pid *= 10;
                 pid += c;
- if (!pid)
- goto out;
- if (pid & 0xffff0000)
+ if (pid <= 0 || pid >= PID_MAX)
                         goto out;
         }
 
diff -u --recursive --new-file ../linux-2.3.99p9/linux/fs/proc/generic.c ./linux/fs/proc/generic.c
--- ../linux-2.3.99p9/linux/fs/proc/generic.c Wed May 24 15:18:18 2000
+++ ./linux/fs/proc/generic.c Wed May 24 15:23:59 2000
@@ -430,7 +430,7 @@
         strcpy((char*)ent->data,dest);
 
         proc_register(parent, ent);
-
+
 out:
         return ent;
 }
@@ -526,7 +526,7 @@
         ent->mode = mode;
 
         proc_register(parent, ent);
-
+
 out:
         return ent;
 }
diff -u --recursive --new-file ../linux-2.3.99p9/linux/include/linux/threads.h ./linux/include/linux/threads.h
--- ../linux-2.3.99p9/linux/include/linux/threads.h Sun Apr 30 21:49:37 2000
+++ ./linux/include/linux/threads.h Sun May 28 18:07:34 2000
@@ -17,8 +17,18 @@
 #define MIN_THREADS_LEFT_FOR_ROOT 4
 
 /*
- * This controls the maximum pid allocated to a process
+ * One more than the maximum pid allocated to a process
+ * (should be positive when assigned to an int)
  */
+#ifdef CONFIG_15BIT_PID
 #define PID_MAX 0x8000
+#else
+#define PID_MAX 0x7fffffff
+#endif
+
+/*
+ * Place where we start again after a full cycle
+ */
+#define PID_MIN 300
 
 #endif
diff -u --recursive --new-file ../linux-2.3.99p9/linux/kernel/fork.c ./linux/kernel/fork.c
--- ../linux-2.3.99p9/linux/kernel/fork.c Wed May 24 15:18:23 2000
+++ ./linux/kernel/fork.c Wed May 24 15:24:03 2000
@@ -195,26 +195,19 @@
                 return current->pid;
 
         spin_lock(&lastpid_lock);
- if((++last_pid) & 0xffff8000) {
- last_pid = 300; /* Skip daemons etc. */
- goto inside;
- }
- if(last_pid >= next_safe) {
-inside:
- next_safe = PID_MAX;
+ if(++last_pid >= next_safe) {
                 read_lock(&tasklist_lock);
         repeat:
+ if (last_pid >= PID_MAX)
+ last_pid = PID_MIN;
+ next_safe = PID_MAX;
+
                 for_each_task(p) {
                         if(p->pid == last_pid ||
                            p->pgrp == last_pid ||
- p->session == last_pid) {
- if(++last_pid >= next_safe) {
- if(last_pid & 0xffff8000)
- last_pid = 300;
- next_safe = PID_MAX;
- }
- goto repeat;
- }
+ p->session == last_pid)
+ if(++last_pid >= next_safe)
+ goto repeat;
                         if(p->pid > last_pid && next_safe > p->pid)
                                 next_safe = p->pid;
                         if(p->pgrp > last_pid && next_safe > p->pgrp)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Jun 26 2000 - 21:00:07 EST