Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0e889bb authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: recent match: fix "sleeping function called from invalid context"



create_proc_entry must not be called with locks held. Use a mutex
instead to protect data only changed in user context.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4e5ab4cb
Loading
Loading
Loading
Loading
+10 −5
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@ struct recent_table {


static LIST_HEAD(tables);
static LIST_HEAD(tables);
static DEFINE_SPINLOCK(recent_lock);
static DEFINE_SPINLOCK(recent_lock);
static DEFINE_MUTEX(recent_mutex);


#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry	*proc_dir;
static struct proc_dir_entry	*proc_dir;
@@ -249,7 +250,7 @@ ipt_recent_checkentry(const char *tablename, const void *ip,
	    strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
	    strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
		return 0;
		return 0;


	spin_lock_bh(&recent_lock);
	mutex_lock(&recent_mutex);
	t = recent_table_lookup(info->name);
	t = recent_table_lookup(info->name);
	if (t != NULL) {
	if (t != NULL) {
		t->refcnt++;
		t->refcnt++;
@@ -258,7 +259,7 @@ ipt_recent_checkentry(const char *tablename, const void *ip,
	}
	}


	t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
	t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
		    GFP_ATOMIC);
		    GFP_KERNEL);
	if (t == NULL)
	if (t == NULL)
		goto out;
		goto out;
	strcpy(t->name, info->name);
	strcpy(t->name, info->name);
@@ -274,10 +275,12 @@ ipt_recent_checkentry(const char *tablename, const void *ip,
	t->proc->proc_fops = &recent_fops;
	t->proc->proc_fops = &recent_fops;
	t->proc->data      = t;
	t->proc->data      = t;
#endif
#endif
	spin_lock_bh(&recent_lock);
	list_add_tail(&t->list, &tables);
	list_add_tail(&t->list, &tables);
	spin_unlock_bh(&recent_lock);
	ret = 1;
	ret = 1;
out:
out:
	spin_unlock_bh(&recent_lock);
	mutex_unlock(&recent_mutex);
	return ret;
	return ret;
}
}


@@ -288,17 +291,19 @@ ipt_recent_destroy(const struct xt_match *match, void *matchinfo,
	const struct ipt_recent_info *info = matchinfo;
	const struct ipt_recent_info *info = matchinfo;
	struct recent_table *t;
	struct recent_table *t;


	spin_lock_bh(&recent_lock);
	mutex_lock(&recent_mutex);
	t = recent_table_lookup(info->name);
	t = recent_table_lookup(info->name);
	if (--t->refcnt == 0) {
	if (--t->refcnt == 0) {
		spin_lock_bh(&recent_lock);
		list_del(&t->list);
		list_del(&t->list);
		spin_unlock_bh(&recent_lock);
		recent_table_flush(t);
		recent_table_flush(t);
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
		remove_proc_entry(t->name, proc_dir);
		remove_proc_entry(t->name, proc_dir);
#endif
#endif
		kfree(t);
		kfree(t);
	}
	}
	spin_unlock_bh(&recent_lock);
	mutex_unlock(&recent_mutex);
}
}


#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS