public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Race in fs/proc/generic.c:make_inode_number()
@ 2001-04-05  5:14 Tom Leete
  2001-04-05 14:36 ` [PATCH] " Tom Leete
  0 siblings, 1 reply; 4+ messages in thread
From: Tom Leete @ 2001-04-05  5:14 UTC (permalink / raw)
  To: linux-kernel

Hello,

The proc_alloc_map bitfield is unprotected by any lock, and
find_first_zero_bit() is not atomic. Concurrent module loading can race
here.

static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8];

static int make_inode_number(void)
{
	int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
	if (i<0 || i>=PROC_NDYNAMIC) 
		return -1;
	set_bit(i, (void *) proc_alloc_map);
	return PROC_DYNAMIC_FIRST + i;
}

Cheers,
Tom

-- 
The Daemons lurk and are dumb. -- Emerson

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] Re: Race in fs/proc/generic.c:make_inode_number()
  2001-04-05  5:14 Race in fs/proc/generic.c:make_inode_number() Tom Leete
@ 2001-04-05 14:36 ` Tom Leete
  2001-04-06 12:01   ` Maneesh Soni
  0 siblings, 1 reply; 4+ messages in thread
From: Tom Leete @ 2001-04-05 14:36 UTC (permalink / raw)
  To: Linus Torvalds, Alan Cox; +Cc: linux-kernel

I wrote:
> 
> The proc_alloc_map bitfield is unprotected by any lock, and
> find_first_zero_bit() is not atomic. Concurrent module loading can race
> here.

Hello,

Here is a patch for this. It looks like callers are always in user context
(kmalloc flag GFP_KERNEL), so I used a light spinlock.

Cheers,
Tom
-- 
The Daemons lurk and are dumb. -- Emerson

--- linux-2.4.3/fs/proc/generic.c.orig	Thu Apr  5 10:03:02 2001
+++ linux-2.4.3/fs/proc/generic.c	Thu Apr  5 10:22:48 2001
@@ -192,13 +192,22 @@
 
 static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8];
 
+spinlock_t proc_alloc_map_lock = RW_LOCK_UNLOCKED;
+
 static int make_inode_number(void)
 {
-	int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
-	if (i<0 || i>=PROC_NDYNAMIC) 
-		return -1;
+	int i;
+	spin_lock(&proc_alloc_map_lock);
+	i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
+	if (i<0 || i>=PROC_NDYNAMIC) {
+		i = -1;
+		goto out;
+	}
 	set_bit(i, (void *) proc_alloc_map);
-	return PROC_DYNAMIC_FIRST + i;
+	i += PROC_DYNAMIC_FIRST;
+out:
+	spin_unlock(&proc_alloc_map_lock);
+	return i;
 }
 
 static int proc_readlink(struct dentry *dentry, char *buffer, int buflen)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Re: Race in fs/proc/generic.c:make_inode_number()
  2001-04-05 14:36 ` [PATCH] " Tom Leete
@ 2001-04-06 12:01   ` Maneesh Soni
  2001-04-06 15:47     ` Tom Leete
  0 siblings, 1 reply; 4+ messages in thread
From: Maneesh Soni @ 2001-04-06 12:01 UTC (permalink / raw)
  To: Tom Leete; +Cc: linux-kernel

Just a couple of points:

On Thu, Apr 05, 2001 at 10:36:10AM -0400, Tom Leete wrote:
[...]
> +spinlock_t proc_alloc_map_lock = RW_LOCK_UNLOCKED;
> +
Why not make this static?
Initializer should be SPIN_LOCK_UNLOCKED.

Maneesh Soni
Linux Technology Center,
IBM Bangalore.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Re: Race in fs/proc/generic.c:make_inode_number()
  2001-04-06 12:01   ` Maneesh Soni
@ 2001-04-06 15:47     ` Tom Leete
  0 siblings, 0 replies; 4+ messages in thread
From: Tom Leete @ 2001-04-06 15:47 UTC (permalink / raw)
  To: smaneesh, Linus Torvalds, Alan Cox; +Cc: linux-kernel

Maneesh Soni wrote:
> 
> Just a couple of points:
> 
> On Thu, Apr 05, 2001 at 10:36:10AM -0400, Tom Leete wrote:
> [...]
> > +spinlock_t proc_alloc_map_lock = RW_LOCK_UNLOCKED;
> > +
> Why not make this static?
> Initializer should be SPIN_LOCK_UNLOCKED.
> 

Thanks, you're right on both counts.

Linus, Alan, this version is more correct. I also checked for other uses of
proc_alloc_map[], The only case is in deallocation, and it looks ok to me.

Tom

-- 
The Daemons lurk and are dumb. -- Emerson

diff -u linux-2.4.3/fs/proc/generic.c.orig linux-2.4.3/fs/proc/generic.c
--- linux-2.4.3/fs/proc/generic.c.orig	Thu Apr  5 10:03:02 2001
+++ linux-2.4.3/fs/proc/generic.c	Thu Apr  5 10:22:48 2001
@@ -192,13 +192,22 @@
 
 static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8];
 
+spinlock_t proc_alloc_map_lock = RW_LOCK_UNLOCKED;
+
 static int make_inode_number(void)
 {
-	int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
-	if (i<0 || i>=PROC_NDYNAMIC) 
-		return -1;
+	int i;
+	spin_lock(&proc_alloc_map_lock);
+	i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
+	if (i<0 || i>=PROC_NDYNAMIC) {
+		i = -1;
+		goto out;
+	}
 	set_bit(i, (void *) proc_alloc_map);
-	return PROC_DYNAMIC_FIRST + i;
+	i += PROC_DYNAMIC_FIRST;
+out:
+	spin_unlock(&proc_alloc_map_lock);
+	return i;
 }
 
 static int proc_readlink(struct dentry *dentry, char *buffer, int buflen)

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2001-04-06 15:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-04-05  5:14 Race in fs/proc/generic.c:make_inode_number() Tom Leete
2001-04-05 14:36 ` [PATCH] " Tom Leete
2001-04-06 12:01   ` Maneesh Soni
2001-04-06 15:47     ` Tom Leete

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox