Messages in this thread Patch in this message | | | Date | Sat, 6 Feb 1999 15:20:01 +0100 (CET) | From | Andrea Arcangeli <> | Subject | [patch] inode changes to 2.2.2-pre2 |
| |
2.2.2-pre2 only removes the depth thing but:
a) it doesn't take care of syncing inodes if the inuse list is not freeable.
b) It also continue to use the preshirnk thing (that avoid the admin to increase the inode-nr if preshirnk is 1).
c) And it still allow an user to increase the number of inodes over the inode-max limit (because it recovers with __get_free_pages() if free_inodes() failed).
So basically I think should be still very easy for a malicious user (that knows a and c) to eat memory via inode.c.
Here the other part of my latest patch rediffed against 2.2.2-pre2:
Index: inode.c =================================================================== RCS file: /var/cvs/linux/fs/inode.c,v retrieving revision 1.1.1.3 retrieving revision 1.1.2.10 diff -u -r1.1.1.3 -r1.1.2.10 --- inode.c 1999/02/06 13:20:05 1.1.1.3 +++ inode.c 1999/02/06 13:36:49 1.1.2.10 @@ -54,7 +54,7 @@ * NOTE! You also have to own the lock if you change * the i_state of an inode while it is in use.. */ -spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; /* * Statistics gathering.. @@ -62,9 +62,8 @@ struct { int nr_inodes; int nr_free_inodes; - int preshrink; /* pre-shrink dcache? */ - int dummy[4]; -} inodes_stat = {0, 0, 0,}; + int dummy[5]; +} inodes_stat = {0, 0, }; int max_inodes; @@ -140,7 +139,7 @@ inode->i_sb->s_op->write_inode(inode); } -static inline void sync_one(struct inode *inode) +static void sync_one(struct inode *inode) { if (inode->i_state & I_LOCK) { spin_unlock(&inode_lock); @@ -312,6 +311,35 @@ return busy; } +#define INODE(entry) (list_entry(entry, struct inode, i_list)) + +static int produce_freeable_inodes(void) +{ + struct super_block * sb; + int freeable = 0; + + for (sb = sb_entry(super_blocks.next); + sb != sb_entry(&super_blocks); + sb = sb_entry(sb->s_list.next)) + { + struct list_head * tmp, * head; + + if (!sb->s_dev) + continue; + + head = &sb->s_dirty; + while ((tmp = head->prev) != head) + { + struct inode * inode = INODE(tmp); + sync_one(inode); + if (!inode->i_count) + freeable = 1; + } + } + + return freeable; +} + /* * This is called with the inode lock held. It searches * the in-use for freeable inodes, which are moved to a @@ -325,7 +353,6 @@ */ #define CAN_UNUSE(inode) \ (((inode)->i_count | (inode)->i_state) == 0) -#define INODE(entry) (list_entry(entry, struct inode, i_list)) static int free_inodes(void) { @@ -333,6 +360,7 @@ int found = 0; INIT_LIST_HEAD(freeable); + again: entry = inode_in_use.next; while (entry != &inode_in_use) { struct list_head *tmp = entry; @@ -347,9 +375,11 @@ found = 1; } - if (found) { + if (found) dispose_list(freeable); - found = 1; /* silly compiler */ + else { + if (produce_freeable_inodes()) + goto again; } return found; @@ -404,7 +434,7 @@ /* * Check whether to restock the unused list. */ - if (inodes_stat.preshrink) { + if (inodes_stat.nr_inodes > max_inodes) { struct list_head *tmp; try_to_free_inodes(8); tmp = inode_unused.next; @@ -414,6 +444,9 @@ inode = list_entry(tmp, struct inode, i_list); return inode; } + spin_unlock(&inode_lock); + printk(KERN_WARNING "grow_inodes: inode-max limit reached\n"); + return NULL; } spin_unlock(&inode_lock); @@ -437,9 +470,6 @@ */ inodes_stat.nr_inodes += INODES_PER_PAGE; inodes_stat.nr_free_inodes += INODES_PER_PAGE - 1; - inodes_stat.preshrink = 0; - if (inodes_stat.nr_inodes > max_inodes) - inodes_stat.preshrink = 1; return inode; } @@ -448,7 +478,6 @@ * the dcache and then try again to free some inodes. */ prune_dcache(inodes_stat.nr_inodes >> 2); - inodes_stat.preshrink = 1; spin_lock(&inode_lock); free_inodes(); @@ -463,7 +492,7 @@ } spin_unlock(&inode_lock); - printk("grow_inodes: allocation failed\n"); + printk(KERN_WARNING "grow_inodes: allocation failed\n"); return NULL; }
Andrea Arcangeli
- 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/
| |