]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
next_pidmap: fix overflow condition
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 18 Apr 2011 17:35:30 +0000 (10:35 -0700)
committerWilly Tarreau <w@1wt.eu>
Sat, 30 Apr 2011 14:53:38 +0000 (16:53 +0200)
commit c78193e9c7bcbf25b8237ad0dec82f805c4ea69b upstream.

next_pidmap() just quietly accepted whatever 'last' pid that was passed
in, which is not all that safe when one of the users is /proc.

Admittedly the proc code should do some sanity checking on the range
(and that will be the next commit), but that doesn't mean that the
helper functions should just do that pidmap pointer arithmetic without
checking the range of its arguments.

So clamp 'last' to PID_MAX_LIMIT.  The fact that we then do "last+1"
doesn't really matter, the for-loop does check against the end of the
pidmap array properly (it's only the actual pointer arithmetic overflow
case we need to worry about, and going one bit beyond isn't going to
overflow).

[ Use PID_MAX_LIMIT rather than pid_max as per Eric Biederman ]

Reported-by: Tavis Ormandy <taviso@cmpxchg8b.com>
Analyzed-by: Robert Święcki <robert@swiecki.net>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
include/linux/pid.h
kernel/pid.c

index 93997c968ba9b563e15f566260383b8c84af55fa..8f7ea8197b2373e34479132fec873eda5c4605e6 100644 (file)
@@ -117,7 +117,7 @@ extern struct pid *find_vpid(int nr);
  */
 extern struct pid *find_get_pid(int nr);
 extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
-int next_pidmap(struct pid_namespace *pid_ns, int last);
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last);
 
 extern struct pid *alloc_pid(struct pid_namespace *ns);
 extern void free_pid(struct pid *pid);
index 064e76afa507a252f6f4de8aec046f03c6cc62a7..c19879f569c3875b2d9880f132b2fbc6045ee0f6 100644 (file)
@@ -182,11 +182,14 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
        return -1;
 }
 
-int next_pidmap(struct pid_namespace *pid_ns, int last)
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last)
 {
        int offset;
        struct pidmap *map, *end;
 
+       if (last >= PID_MAX_LIMIT)
+               return -1;
+
        offset = (last + 1) & BITS_PER_PAGE_MASK;
        map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE];
        end = &pid_ns->pidmap[PIDMAP_ENTRIES];