Skip to content

Commit

Permalink
[PATCH 1/2] proc: fix inode number bogorithmetic
Browse files Browse the repository at this point in the history
Id which proc gets from IDR for inode number and id which proc removes
from IDR do not match. E.g. 0x11a transforms into 0x8000011a.

Which stayed unnoticed for a long time because, surprise, idr_remove()
masks out that high bit before doing anything.

All of this due to "| ~MAX_ID_MASK" in release_inode_number().

I still don't understand how it's supposed to work, because "| ~MASK"
is not an inversion for "& MAX" operation.

So, use just one nice, working addition. Make start offset unsigned int,
while I'm at it. It's longness is not used anywhere.

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Alexey Dobriyan authored and Al Viro committed Aug 1, 2008
1 parent 8266602 commit 67935df
Showing 1 changed file with 9 additions and 12 deletions.
21 changes: 9 additions & 12 deletions fs/proc/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,15 +303,15 @@ static int xlate_proc_name(const char *name,
static DEFINE_IDR(proc_inum_idr);
static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */

#define PROC_DYNAMIC_FIRST 0xF0000000UL
#define PROC_DYNAMIC_FIRST 0xF0000000U

/*
* Return an inode number between PROC_DYNAMIC_FIRST and
* 0xffffffff, or zero on failure.
*/
static unsigned int get_inode_number(void)
{
int i, inum = 0;
unsigned int i;
int error;

retry:
Expand All @@ -326,21 +326,18 @@ static unsigned int get_inode_number(void)
else if (error)
return 0;

inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST;

/* inum will never be more than 0xf0ffffff, so no check
* for overflow.
*/

return inum;
if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
spin_lock(&proc_inum_lock);
idr_remove(&proc_inum_idr, i);
spin_unlock(&proc_inum_lock);
}
return PROC_DYNAMIC_FIRST + i;
}

static void release_inode_number(unsigned int inum)
{
int id = (inum - PROC_DYNAMIC_FIRST) | ~MAX_ID_MASK;

spin_lock(&proc_inum_lock);
idr_remove(&proc_inum_idr, id);
idr_remove(&proc_inum_idr, inum - PROC_DYNAMIC_FIRST);
spin_unlock(&proc_inum_lock);
}

Expand Down

0 comments on commit 67935df

Please sign in to comment.