diff options
| -rw-r--r-- | fs/configfs/dir.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 5638c8f9362f..810c1395d6b2 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -704,13 +704,18 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 704 | struct module *owner; | 704 | struct module *owner; |
| 705 | char *name; | 705 | char *name; |
| 706 | 706 | ||
| 707 | if (dentry->d_parent == configfs_sb->s_root) | 707 | if (dentry->d_parent == configfs_sb->s_root) { |
| 708 | return -EPERM; | 708 | ret = -EPERM; |
| 709 | goto out; | ||
| 710 | } | ||
| 709 | 711 | ||
| 710 | sd = dentry->d_parent->d_fsdata; | 712 | sd = dentry->d_parent->d_fsdata; |
| 711 | if (!(sd->s_type & CONFIGFS_USET_DIR)) | 713 | if (!(sd->s_type & CONFIGFS_USET_DIR)) { |
| 712 | return -EPERM; | 714 | ret = -EPERM; |
| 715 | goto out; | ||
| 716 | } | ||
| 713 | 717 | ||
| 718 | /* Get a working ref for the duration of this function */ | ||
| 714 | parent_item = configfs_get_config_item(dentry->d_parent); | 719 | parent_item = configfs_get_config_item(dentry->d_parent); |
| 715 | type = parent_item->ci_type; | 720 | type = parent_item->ci_type; |
| 716 | subsys = to_config_group(parent_item)->cg_subsys; | 721 | subsys = to_config_group(parent_item)->cg_subsys; |
| @@ -719,15 +724,16 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 719 | if (!type || !type->ct_group_ops || | 724 | if (!type || !type->ct_group_ops || |
| 720 | (!type->ct_group_ops->make_group && | 725 | (!type->ct_group_ops->make_group && |
| 721 | !type->ct_group_ops->make_item)) { | 726 | !type->ct_group_ops->make_item)) { |
| 722 | config_item_put(parent_item); | 727 | ret = -EPERM; /* Lack-of-mkdir returns -EPERM */ |
| 723 | return -EPERM; /* What lack-of-mkdir returns */ | 728 | goto out_put; |
| 724 | } | 729 | } |
| 725 | 730 | ||
| 726 | name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL); | 731 | name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL); |
| 727 | if (!name) { | 732 | if (!name) { |
| 728 | config_item_put(parent_item); | 733 | ret = -ENOMEM; |
| 729 | return -ENOMEM; | 734 | goto out_put; |
| 730 | } | 735 | } |
| 736 | |||
| 731 | snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); | 737 | snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); |
| 732 | 738 | ||
| 733 | down(&subsys->su_sem); | 739 | down(&subsys->su_sem); |
| @@ -748,8 +754,8 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 748 | 754 | ||
| 749 | kfree(name); | 755 | kfree(name); |
| 750 | if (!item) { | 756 | if (!item) { |
| 751 | config_item_put(parent_item); | 757 | ret = -ENOMEM; |
| 752 | return -ENOMEM; | 758 | goto out_put; |
| 753 | } | 759 | } |
| 754 | 760 | ||
| 755 | ret = -EINVAL; | 761 | ret = -EINVAL; |
| @@ -776,12 +782,19 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 776 | client_drop_item(parent_item, item); | 782 | client_drop_item(parent_item, item); |
| 777 | up(&subsys->su_sem); | 783 | up(&subsys->su_sem); |
| 778 | 784 | ||
| 779 | config_item_put(parent_item); | ||
| 780 | module_put(owner); | 785 | module_put(owner); |
| 781 | } | 786 | } |
| 782 | } | 787 | } |
| 783 | } | 788 | } |
| 784 | 789 | ||
| 790 | out_put: | ||
| 791 | /* | ||
| 792 | * link_obj()/link_group() took a reference from child->parent. | ||
| 793 | * Drop our working ref | ||
| 794 | */ | ||
| 795 | config_item_put(parent_item); | ||
| 796 | |||
| 797 | out: | ||
| 785 | return ret; | 798 | return ret; |
| 786 | } | 799 | } |
| 787 | 800 | ||
| @@ -801,6 +814,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 801 | if (sd->s_type & CONFIGFS_USET_DEFAULT) | 814 | if (sd->s_type & CONFIGFS_USET_DEFAULT) |
| 802 | return -EPERM; | 815 | return -EPERM; |
| 803 | 816 | ||
| 817 | /* Get a working ref until we have the child */ | ||
| 804 | parent_item = configfs_get_config_item(dentry->d_parent); | 818 | parent_item = configfs_get_config_item(dentry->d_parent); |
| 805 | subsys = to_config_group(parent_item)->cg_subsys; | 819 | subsys = to_config_group(parent_item)->cg_subsys; |
| 806 | BUG_ON(!subsys); | 820 | BUG_ON(!subsys); |
| @@ -817,6 +831,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 817 | return ret; | 831 | return ret; |
| 818 | } | 832 | } |
| 819 | 833 | ||
| 834 | /* Get a working ref for the duration of this function */ | ||
| 820 | item = configfs_get_config_item(dentry); | 835 | item = configfs_get_config_item(dentry); |
| 821 | 836 | ||
| 822 | /* Drop reference from above, item already holds one. */ | 837 | /* Drop reference from above, item already holds one. */ |
