summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2018-09-26 09:50:58 -0700
committerGitHub <[email protected]>2018-09-26 09:50:58 -0700
commit7a23c81342df05ace730bd303b4a73854dba43dd (patch)
tree39569e47af4b369c9813aca12dd8ff72a3a1e481
parentb954e36e512171d94637c709023e4d763b655d91 (diff)
Fix small sysfs leak
When zfs_kobj_init() is called with an attr_cnt of 0 only the kobj->zko_default_attrs is allocated. It subsequently won't get freed in zfs_kobj_release since the free is wrapped in a kobj->zko_attr_count != 0 conditional. Split the block in zfs_kobj_release() to make sure the kobj->zko_default_attrs are freed in this case. Additionally, fix a minor spelling mistake and typo in zfs_kobj_init() which could also cause a leak but in practice is almost certain not to fail. Reviewed-by: Richard Elling <[email protected]> Reviewed-by: Tim Chase <[email protected]> Reviewed-by: John Gallagher <[email protected]> Reviewed-by: Don Brady <[email protected]> Reviewed-by: George Melikov <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #7957
-rw-r--r--module/zfs/zfs_sysfs.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/module/zfs/zfs_sysfs.c b/module/zfs/zfs_sysfs.c
index 42822b2f2..b17c91f65 100644
--- a/module/zfs/zfs_sysfs.c
+++ b/module/zfs/zfs_sysfs.c
@@ -102,7 +102,7 @@ typedef ssize_t (*sysfs_show_func)(struct kobject *, struct attribute *,
static void
zfs_kobj_fini(zfs_mod_kobj_t *zkobj)
{
- /* finialize any child kobjects */
+ /* finalize any child kobjects */
if (zkobj->zko_child_count != 0) {
ASSERT(zkobj->zko_children);
for (int i = 0; i < zkobj->zko_child_count; i++)
@@ -119,18 +119,19 @@ zfs_kobj_release(struct kobject *kobj)
{
zfs_mod_kobj_t *zkobj = container_of(kobj, zfs_mod_kobj_t, zko_kobj);
- if (zkobj->zko_attr_count != 0) {
- ASSERT(zkobj->zko_attr_list);
- ASSERT(zkobj->zko_default_attrs);
-
+ if (zkobj->zko_attr_list != NULL) {
+ ASSERT3S(zkobj->zko_attr_count, !=, 0);
kmem_free(zkobj->zko_attr_list,
ATTR_TABLE_SIZE(zkobj->zko_attr_count));
+ zkobj->zko_attr_list = NULL;
+ }
+
+ if (zkobj->zko_default_attrs != NULL) {
kmem_free(zkobj->zko_default_attrs,
DEFAULT_ATTR_SIZE(zkobj->zko_attr_count));
- zkobj->zko_attr_count = 0;
- zkobj->zko_attr_list = NULL;
zkobj->zko_default_attrs = NULL;
}
+
if (zkobj->zko_child_count != 0) {
ASSERT(zkobj->zko_children);
@@ -139,6 +140,8 @@ zfs_kobj_release(struct kobject *kobj)
zkobj->zko_child_count = 0;
zkobj->zko_children = NULL;
}
+
+ zkobj->zko_attr_count = 0;
}
static void
@@ -170,7 +173,7 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
zkobj->zko_default_attrs = kmem_zalloc(DEFAULT_ATTR_SIZE(attr_cnt),
KM_SLEEP);
if (zkobj->zko_default_attrs == NULL) {
- if (zkobj->zko_attr_list) {
+ if (zkobj->zko_attr_list != NULL) {
kmem_free(zkobj->zko_attr_list,
ATTR_TABLE_SIZE(attr_cnt));
}
@@ -183,9 +186,11 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
zkobj->zko_children = kmem_zalloc(CHILD_TABLE_SIZE(child_cnt),
KM_SLEEP);
if (zkobj->zko_children == NULL) {
- if (attr_cnt > 0) {
- kmem_free(zkobj->zko_attr_list,
+ if (zkobj->zko_default_attrs != NULL) {
+ kmem_free(zkobj->zko_default_attrs,
DEFAULT_ATTR_SIZE(attr_cnt));
+ }
+ if (zkobj->zko_attr_list != NULL) {
kmem_free(zkobj->zko_attr_list,
ATTR_TABLE_SIZE(attr_cnt));
}