--- linux-2.2.19/fs/namei.c.orig Wed Oct 10 09:31:37 2001 +++ linux-2.2.19/fs/namei.c Wed Oct 10 10:30:56 2001 @@ -277,6 +277,15 @@ result->d_op->d_revalidate(result, flags); return result; } +/* + * Yes, this really increments the link_count by 5, and + * decrements it by 4. Together with checking against 25, + * this limits recursive symlink follows to 5, while + * limiting consecutive symlinks to 25. + * + * Without that kind of total limit, nasty chains of consecutive + * symlinks can cause almost arbitrarily long lookups. + */ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry, unsigned int follow) { @@ -284,13 +293,17 @@ if ((follow & LOOKUP_FOLLOW) && inode && inode->i_op && inode->i_op->follow_link) { - if (current->link_count < 5) { + if (current->link_count < 25) { struct dentry * result; - current->link_count++; + if (current->need_resched) { + current->state = TASK_RUNNING; + schedule(); + } + current->link_count += 5; /* This eats the base */ - result = inode->i_op->follow_link(dentry, base, follow); - current->link_count--; + result = inode->i_op->follow_link(dentry, base, follow|LOOKUP_INSYMLINK); + current->link_count -= 4; dput(dentry); return result; } @@ -324,6 +337,8 @@ struct dentry * dentry; struct inode *inode; + if (!(lookup_flags & LOOKUP_INSYMLINK)) + current->link_count=0; if (*name == '/') { if (base) dput(base); --- linux-2.2.19/include/linux/fs.h.orig Wed Oct 10 10:06:41 2001 +++ linux-2.2.19/include/linux/fs.h Wed Oct 10 10:07:58 2001 @@ -872,6 +872,7 @@ #define LOOKUP_DIRECTORY (2) #define LOOKUP_SLASHOK (4) #define LOOKUP_CONTINUE (8) +#define LOOKUP_INSYMLINK (16) extern struct dentry * lookup_dentry(const char *, struct dentry *, unsigned int); extern struct dentry * __namei(const char *, unsigned int);