diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 2fbdff6..19aebd3 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -280,6 +280,11 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) * sd->s_parent won't change beneath us. */ parent_sd = sd->s_parent; + if(!(sd->s_flags & SYSFS_FLAG_REMOVED)) { + printk("%s-%d sysfs_dirent use after free: %s-%s\n", + __func__, __LINE__, parent_sd->s_name, sd->s_name); + dump_stack(); + } if (sysfs_type(sd) == SYSFS_KOBJ_LINK) sysfs_put(sd->s_symlink.target_sd); @@ -962,6 +967,12 @@ static struct sysfs_dirent *sysfs_dir_pos(const void *ns, int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && pos->s_parent == parent_sd && hash == pos->s_hash; + + if ((atomic_read(&pos->s_count) == 1)) { + printk("%s-%d sysfs_dirent use after free: %s(%s)-%s, %lld-%u\n", + __func__, __LINE__, parent_sd->s_name, pos->s_parent->s_name, + pos->s_name, hash, pos->s_hash); + } sysfs_put(pos); if (!valid) pos = NULL; @@ -1058,10 +1069,21 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) return 0; } +static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence) +{ + struct inode *inode = file_inode(file); + loff_t ret; + + mutex_lock(&inode->i_mutex); + ret = generic_file_llseek(file, offset, whence); + mutex_unlock(&inode->i_mutex); + + return ret; +} const struct file_operations sysfs_dir_operations = { .read = generic_read_dir, .readdir = sysfs_readdir, .release = sysfs_dir_release, - .llseek = generic_file_llseek, + .llseek = sysfs_dir_llseek, };