From mboxrd@z Thu Jan 1 00:00:00 1970 From: John Fastabend Subject: Re: [Patch net-next] net_sched: properly check for empty skb array on error path Date: Mon, 18 Dec 2017 19:58:44 -0800 Message-ID: <4caae5f5-63e2-65c8-522e-0dfe736a7738@gmail.com> References: <20171218223426.4685-1-xiyou.wangcong@gmail.com> <11149665-47bb-ec52-fdf0-db7bfa67152e@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Cc: Linux Kernel Network Developers To: Cong Wang Return-path: Received: from mail-pl0-f66.google.com ([209.85.160.66]:42145 "EHLO mail-pl0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933188AbdLSD64 (ORCPT ); Mon, 18 Dec 2017 22:58:56 -0500 Received: by mail-pl0-f66.google.com with SMTP id bd8so6215988plb.9 for ; Mon, 18 Dec 2017 19:58:56 -0800 (PST) In-Reply-To: Content-Language: en-US Sender: netdev-owner@vger.kernel.org List-ID: On 12/18/2017 06:20 PM, Cong Wang wrote: > On Mon, Dec 18, 2017 at 5:25 PM, John Fastabend > wrote: >> On 12/18/2017 02:34 PM, Cong Wang wrote: >>> First, the check of &q->ring.queue against NULL is wrong, it >>> is always false. We should check the value rather than the address. >>> >> >> Thanks. >> >>> Secondly, we need the same check in pfifo_fast_reset() too, >>> as both ->reset() and ->destroy() are called in qdisc_destroy(). >>> >> >> not that it hurts to have the check here, but if init fails >> in qdisc_create it seems only ->destroy() is called without >> a ->reset(). >> >> Is there another path for init() to fail that I'm missing. > > Pretty sure ->reset() is called in qdisc_destroy() and also before > ->destroy(): > Except, the failed init path does not call qdisc_destroy. static struct Qdisc *qdisc_create(struct net_device *dev, [...] if (ops->init) { err = ops->init(sch, tca[TCA_OPTIONS]); if (err != 0) goto err_out5; } [...] err_out5: /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */ if (ops->destroy) ops->destroy(sch); err_out3: dev_put(dev); kfree((char *) sch - sch->padded); err_out2: module_put(ops->owner); err_out: *errp = err; return NULL; [...] > > void qdisc_destroy(struct Qdisc *qdisc) > { > const struct Qdisc_ops *ops = qdisc->ops; > struct sk_buff *skb, *tmp; > > if (qdisc->flags & TCQ_F_BUILTIN || > !refcount_dec_and_test(&qdisc->refcnt)) > return; > > #ifdef CONFIG_NET_SCHED > qdisc_hash_del(qdisc); > > qdisc_put_stab(rtnl_dereference(qdisc->stab)); > #endif > gen_kill_estimator(&qdisc->rate_est); > if (ops->reset) > ops->reset(qdisc); > if (ops->destroy) > ops->destroy(qdisc); >