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

Commit e41faed9 authored by Krzysztof Mazur's avatar Krzysztof Mazur Committed by David Woodhouse
Browse files

pppoatm: fix module_put() race



The pppoatm used module_put() during unassignment from vcc with
hope that we have BKL. This assumption is no longer true.

Now owner field in atmvcc is used to move this module_put()
to vcc_destroy_socket().

Signed-off-by: default avatarKrzysztof Mazur <krzysiek@podlesie.net>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 3b1a9145
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ struct pppoatm_vcc {
	struct atm_vcc	*atmvcc;	/* VCC descriptor */
	void (*old_push)(struct atm_vcc *, struct sk_buff *);
	void (*old_pop)(struct atm_vcc *, struct sk_buff *);
	struct module *old_owner;
					/* keep old push/pop for detaching */
	enum pppoatm_encaps encaps;
	atomic_t inflight;
@@ -155,8 +156,6 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
	ppp_unregister_channel(&pvcc->chan);
	atmvcc->user_back = NULL;
	kfree(pvcc);
	/* Gee, I hope we have the big kernel lock here... */
	module_put(THIS_MODULE);
}

/* Called when an AAL5 PDU comes in */
@@ -165,9 +164,13 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
	struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
	pr_debug("\n");
	if (skb == NULL) {			/* VCC was closed */
		struct module *module;

		pr_debug("removing ATMPPP VCC %p\n", pvcc);
		module = pvcc->old_owner;
		pppoatm_unassign_vcc(atmvcc);
		atmvcc->push(atmvcc, NULL);	/* Pass along bad news */
		module_put(module);
		return;
	}
	atm_return(atmvcc, skb->truesize);
@@ -362,6 +365,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
	atomic_set(&pvcc->inflight, NONE_INFLIGHT);
	pvcc->old_push = atmvcc->push;
	pvcc->old_pop = atmvcc->pop;
	pvcc->old_owner = atmvcc->owner;
	pvcc->encaps = (enum pppoatm_encaps) be.encaps;
	pvcc->chan.private = pvcc;
	pvcc->chan.ops = &pppoatm_ops;
@@ -378,6 +382,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
	atmvcc->push = pppoatm_push;
	atmvcc->pop = pppoatm_pop;
	__module_get(THIS_MODULE);
	atmvcc->owner = THIS_MODULE;

	/* re-process everything received between connection setup and
	   backend setup */