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

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

[NET_SCHED]: Use nla_policy for attribute validation in packet schedulers

parent 5feb5e1a
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -195,6 +195,11 @@ static const u8 llc_oui_ip[] = {
	0x08, 0x00
};				/* Ethertype IP (0800) */

static const struct nla_policy atm_policy[TCA_ATM_MAX + 1] = {
	[TCA_ATM_FD]		= { .type = NLA_U32 },
	[TCA_ATM_EXCESS]	= { .type = NLA_U32 },
};

static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
			 struct nlattr **tca, unsigned long *arg)
{
@@ -225,11 +230,12 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
		return -EBUSY;
	if (opt == NULL)
		return -EINVAL;
	error = nla_parse_nested(tb, TCA_ATM_MAX, opt, NULL);

	error = nla_parse_nested(tb, TCA_ATM_MAX, opt, atm_policy);
	if (error < 0)
		return error;

	if (!tb[TCA_ATM_FD] || nla_len(tb[TCA_ATM_FD]) < sizeof(fd))
	if (!tb[TCA_ATM_FD])
		return -EINVAL;
	fd = nla_get_u32(tb[TCA_ATM_FD]);
	pr_debug("atm_tc_change: fd %d\n", fd);
@@ -243,8 +249,6 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
	if (!tb[TCA_ATM_EXCESS])
		excess = NULL;
	else {
		if (nla_len(tb[TCA_ATM_EXCESS]) != sizeof(u32))
			return -EINVAL;
		excess = (struct atm_flow_data *)
			atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
		if (!excess)
+13 −34
Original line number Diff line number Diff line
@@ -1377,6 +1377,16 @@ static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
	return 0;
}

static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
	[TCA_CBQ_LSSOPT]	= { .len = sizeof(struct tc_cbq_lssopt) },
	[TCA_CBQ_WRROPT]	= { .len = sizeof(struct tc_cbq_wrropt) },
	[TCA_CBQ_FOPT]		= { .len = sizeof(struct tc_cbq_fopt) },
	[TCA_CBQ_OVL_STRATEGY]	= { .len = sizeof(struct tc_cbq_ovl) },
	[TCA_CBQ_RATE]		= { .len = sizeof(struct tc_ratespec) },
	[TCA_CBQ_RTAB]		= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
	[TCA_CBQ_POLICE]	= { .len = sizeof(struct tc_cbq_police) },
};

static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
{
	struct cbq_sched_data *q = qdisc_priv(sch);
@@ -1384,16 +1394,11 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
	struct tc_ratespec *r;
	int err;

	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
	if (err < 0)
		return err;

	if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL ||
	    nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
		return -EINVAL;

	if (tb[TCA_CBQ_LSSOPT] &&
	    nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
	if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL)
		return -EINVAL;

	r = nla_data(tb[TCA_CBQ_RATE]);
@@ -1771,36 +1776,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
	if (opt == NULL)
		return -EINVAL;

	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
	if (err < 0)
		return err;

	if (tb[TCA_CBQ_OVL_STRATEGY] &&
	    nla_len(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(struct tc_cbq_ovl))
		return -EINVAL;

	if (tb[TCA_CBQ_FOPT] &&
	    nla_len(tb[TCA_CBQ_FOPT]) < sizeof(struct tc_cbq_fopt))
		return -EINVAL;

	if (tb[TCA_CBQ_RATE] &&
	    nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
			return -EINVAL;

	if (tb[TCA_CBQ_LSSOPT] &&
	    nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
			return -EINVAL;

	if (tb[TCA_CBQ_WRROPT] &&
	    nla_len(tb[TCA_CBQ_WRROPT]) < sizeof(struct tc_cbq_wrropt))
			return -EINVAL;

#ifdef CONFIG_NET_CLS_ACT
	if (tb[TCA_CBQ_POLICE] &&
	    nla_len(tb[TCA_CBQ_POLICE]) < sizeof(struct tc_cbq_police))
			return -EINVAL;
#endif

	if (cl) {
		/* Check parent */
		if (parentid) {
+15 −18
Original line number Diff line number Diff line
@@ -99,6 +99,14 @@ static void dsmark_put(struct Qdisc *sch, unsigned long cl)
{
}

static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
	[TCA_DSMARK_INDICES]		= { .type = NLA_U16 },
	[TCA_DSMARK_DEFAULT_INDEX]	= { .type = NLA_U16 },
	[TCA_DSMARK_SET_TC_INDEX]	= { .type = NLA_FLAG },
	[TCA_DSMARK_MASK]		= { .type = NLA_U8 },
	[TCA_DSMARK_VALUE]		= { .type = NLA_U8 },
};

static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
			 struct nlattr **tca, unsigned long *arg)
{
@@ -119,21 +127,15 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
	if (!opt)
		goto errout;

	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
	if (err < 0)
		return err;

	err = -EINVAL;
	if (tb[TCA_DSMARK_MASK]) {
		if (nla_len(tb[TCA_DSMARK_MASK]) < sizeof(u8))
		goto errout;

	if (tb[TCA_DSMARK_MASK])
		mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
	}
	if (tb[TCA_DSMARK_VALUE]) {
		if (nla_len(tb[TCA_DSMARK_VALUE]) < sizeof(u8))
			goto errout;

	if (tb[TCA_DSMARK_VALUE])
		p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]);
	}

	if (tb[TCA_DSMARK_MASK])
		p->mask[*arg-1] = mask;
@@ -359,23 +361,18 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
	if (!opt)
		goto errout;

	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
	if (err < 0)
		goto errout;

	err = -EINVAL;
	if (nla_len(tb[TCA_DSMARK_INDICES]) < sizeof(u16))
		goto errout;
	indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);

	if (hweight32(indices) != 1)
		goto errout;

	if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
		if (nla_len(tb[TCA_DSMARK_DEFAULT_INDEX]) < sizeof(u16))
			goto errout;
	if (tb[TCA_DSMARK_DEFAULT_INDEX])
		default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
	}

	mask = kmalloc(indices * 2, GFP_KERNEL);
	if (mask == NULL) {
+10 −6
Original line number Diff line number Diff line
@@ -356,7 +356,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps)
	struct tc_gred_sopt *sopt;
	int i;

	if (dps == NULL || nla_len(dps) < sizeof(*sopt))
	if (dps == NULL)
		return -EINVAL;

	sopt = nla_data(dps);
@@ -425,6 +425,12 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
	return 0;
}

static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = {
	[TCA_GRED_PARMS]	= { .len = sizeof(struct tc_gred_qopt) },
	[TCA_GRED_STAB]		= { .len = 256 },
	[TCA_GRED_DPS]		= { .len = sizeof(struct tc_gred_sopt) },
};

static int gred_change(struct Qdisc *sch, struct nlattr *opt)
{
	struct gred_sched *table = qdisc_priv(sch);
@@ -436,7 +442,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
	if (opt == NULL)
		return -EINVAL;

	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
	if (err < 0)
		return err;

@@ -444,9 +450,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
		return gred_change_table_def(sch, opt);

	if (tb[TCA_GRED_PARMS] == NULL ||
	    nla_len(tb[TCA_GRED_PARMS]) < sizeof(*ctl) ||
	    tb[TCA_GRED_STAB] == NULL ||
	    nla_len(tb[TCA_GRED_STAB]) < 256)
	    tb[TCA_GRED_STAB] == NULL)
		return -EINVAL;

	err = -EINVAL;
@@ -499,7 +503,7 @@ static int gred_init(struct Qdisc *sch, struct nlattr *opt)
	if (opt == NULL)
		return -EINVAL;

	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
	if (err < 0)
		return err;

+7 −7
Original line number Diff line number Diff line
@@ -986,6 +986,12 @@ hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
	cl->cl_flags |= HFSC_USC;
}

static const struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
	[TCA_HFSC_RSC]	= { .len = sizeof(struct tc_service_curve) },
	[TCA_HFSC_FSC]	= { .len = sizeof(struct tc_service_curve) },
	[TCA_HFSC_USC]	= { .len = sizeof(struct tc_service_curve) },
};

static int
hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
		  struct nlattr **tca, unsigned long *arg)
@@ -1002,29 +1008,23 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
	if (opt == NULL)
		return -EINVAL;

	err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, NULL);
	err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, hfsc_policy);
	if (err < 0)
		return err;

	if (tb[TCA_HFSC_RSC]) {
		if (nla_len(tb[TCA_HFSC_RSC]) < sizeof(*rsc))
			return -EINVAL;
		rsc = nla_data(tb[TCA_HFSC_RSC]);
		if (rsc->m1 == 0 && rsc->m2 == 0)
			rsc = NULL;
	}

	if (tb[TCA_HFSC_FSC]) {
		if (nla_len(tb[TCA_HFSC_FSC]) < sizeof(*fsc))
			return -EINVAL;
		fsc = nla_data(tb[TCA_HFSC_FSC]);
		if (fsc->m1 == 0 && fsc->m2 == 0)
			fsc = NULL;
	}

	if (tb[TCA_HFSC_USC]) {
		if (nla_len(tb[TCA_HFSC_USC]) < sizeof(*usc))
			return -EINVAL;
		usc = nla_data(tb[TCA_HFSC_USC]);
		if (usc->m1 == 0 && usc->m2 == 0)
			usc = NULL;
Loading