--- x/fs/char_dev.c +++ y/fs/char_dev.c @@ -377,6 +377,9 @@ static int chrdev_open(struct inode *ino struct cdev *new = NULL; int ret = 0; + if (!igrab(inode)) + return -ENXIO; + spin_lock(&cdev_lock); p = inode->i_cdev; if (!p) { @@ -384,8 +387,10 @@ static int chrdev_open(struct inode *ino int idx; spin_unlock(&cdev_lock); kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); - if (!kobj) + if (!kobj) { + iput(inode); return -ENXIO; + } new = container_of(kobj, struct cdev, kobj); spin_lock(&cdev_lock); /* Check i_cdev again in case somebody beat us to it while @@ -401,8 +406,10 @@ static int chrdev_open(struct inode *ino ret = -ENXIO; spin_unlock(&cdev_lock); cdev_put(new); - if (ret) + if (ret) { + iput(inode); return ret; + } ret = -ENXIO; fops = fops_get(p->ops); @@ -416,10 +423,12 @@ static int chrdev_open(struct inode *ino goto out_cdev_put; } + iput(inode); return 0; out_cdev_put: cdev_put(p); + iput(inode); return ret; }