Commit 73335cfa authored by Marc Kleine-Budde's avatar Marc Kleine-Budde
Browse files

can: netlink: can_validate(): validate sample point for CAN and CAN-FD

The sample point is a value in tenths of a percent. Meaningful values
are between 0 and 1000. Invalid values are rejected and an error
message is returned to user space via netlink.

Link: https://lore.kernel.org/all/20230202110854.2318594-8-mkl@pengutronix.de


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent a3db5424
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -36,10 +36,24 @@ static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = {
	[IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 },
};

static int can_validate_bittiming(const struct can_bittiming *bt,
				  struct netlink_ext_ack *extack)
{
	/* sample point is in one-tenth of a percent */
	if (bt->sample_point >= 1000) {
		NL_SET_ERR_MSG(extack, "sample point must be between 0 and 100%");

		return -EINVAL;
	}

	return 0;
}

static int can_validate(struct nlattr *tb[], struct nlattr *data[],
			struct netlink_ext_ack *extack)
{
	bool is_can_fd = false;
	int err;

	/* Make sure that valid CAN FD configurations always consist of
	 * - nominal/arbitration bittiming
@@ -51,6 +65,15 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
	if (!data)
		return 0;

	if (data[IFLA_CAN_BITTIMING]) {
		struct can_bittiming bt;

		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
		err = can_validate_bittiming(&bt, extack);
		if (err)
			return err;
	}

	if (data[IFLA_CAN_CTRLMODE]) {
		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
		u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK;
@@ -71,7 +94,6 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
		 */
		if (data[IFLA_CAN_TDC]) {
			struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
			int err;

			err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX,
					       data[IFLA_CAN_TDC],
@@ -102,6 +124,15 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
			return -EOPNOTSUPP;
	}

	if (data[IFLA_CAN_DATA_BITTIMING]) {
		struct can_bittiming bt;

		memcpy(&bt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), sizeof(bt));
		err = can_validate_bittiming(&bt, extack);
		if (err)
			return err;
	}

	return 0;
}