diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-27 19:33:13 +0100 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-27 19:33:13 +0100 | 
| commit | c2a552197106b45d0d801d5b8a6be47563a700df (patch) | |
| tree | 61d42c1887b843170874bfec3cacc45211ed916a /net/sched/cls_api.c | |
| parent | 9905f32aefbe3d9cb2d24c3bd9c882397eaf3842 (diff) | |
| parent | d6d5df1db6e9d7f8f76d2911707f7d5877251b02 (diff) | |
Merge 5.4-rc5 into tty-next
We want the tty/serial fix in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/sched/cls_api.c')
| -rw-r--r-- | net/sched/cls_api.c | 36 | 
1 files changed, 33 insertions, 3 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 64584a1df425..8717c0b26c90 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -162,11 +162,22 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)  	return TC_H_MAJ(first);  } +static bool tcf_proto_check_kind(struct nlattr *kind, char *name) +{ +	if (kind) +		return nla_strlcpy(name, kind, IFNAMSIZ) >= IFNAMSIZ; +	memset(name, 0, IFNAMSIZ); +	return false; +} +  static bool tcf_proto_is_unlocked(const char *kind)  {  	const struct tcf_proto_ops *ops;  	bool ret; +	if (strlen(kind) == 0) +		return false; +  	ops = tcf_proto_lookup_ops(kind, false, NULL);  	/* On error return false to take rtnl lock. Proto lookup/create  	 * functions will perform lookup again and properly handle errors. @@ -1843,6 +1854,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,  {  	struct net *net = sock_net(skb->sk);  	struct nlattr *tca[TCA_MAX + 1]; +	char name[IFNAMSIZ];  	struct tcmsg *t;  	u32 protocol;  	u32 prio; @@ -1899,13 +1911,19 @@ replay:  	if (err)  		return err; +	if (tcf_proto_check_kind(tca[TCA_KIND], name)) { +		NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); +		err = -EINVAL; +		goto errout; +	} +  	/* Take rtnl mutex if rtnl_held was set to true on previous iteration,  	 * block is shared (no qdisc found), qdisc is not unlocked, classifier  	 * type is not specified, classifier is not unlocked.  	 */  	if (rtnl_held ||  	    (q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || -	    !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { +	    !tcf_proto_is_unlocked(name)) {  		rtnl_held = true;  		rtnl_lock();  	} @@ -2063,6 +2081,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,  {  	struct net *net = sock_net(skb->sk);  	struct nlattr *tca[TCA_MAX + 1]; +	char name[IFNAMSIZ];  	struct tcmsg *t;  	u32 protocol;  	u32 prio; @@ -2102,13 +2121,18 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,  	if (err)  		return err; +	if (tcf_proto_check_kind(tca[TCA_KIND], name)) { +		NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); +		err = -EINVAL; +		goto errout; +	}  	/* Take rtnl mutex if flushing whole chain, block is shared (no qdisc  	 * found), qdisc is not unlocked, classifier type is not specified,  	 * classifier is not unlocked.  	 */  	if (!prio ||  	    (q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || -	    !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { +	    !tcf_proto_is_unlocked(name)) {  		rtnl_held = true;  		rtnl_lock();  	} @@ -2216,6 +2240,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,  {  	struct net *net = sock_net(skb->sk);  	struct nlattr *tca[TCA_MAX + 1]; +	char name[IFNAMSIZ];  	struct tcmsg *t;  	u32 protocol;  	u32 prio; @@ -2252,12 +2277,17 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,  	if (err)  		return err; +	if (tcf_proto_check_kind(tca[TCA_KIND], name)) { +		NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); +		err = -EINVAL; +		goto errout; +	}  	/* Take rtnl mutex if block is shared (no qdisc found), qdisc is not  	 * unlocked, classifier type is not specified, classifier is not  	 * unlocked.  	 */  	if ((q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || -	    !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { +	    !tcf_proto_is_unlocked(name)) {  		rtnl_held = true;  		rtnl_lock();  	}  | 
