]> git.itanic.dy.fi Git - linux-stable/commitdiff
can: netlink: can_validate(): validate sample point for CAN and CAN-FD
authorMarc Kleine-Budde <mkl@pengutronix.de>
Wed, 1 Feb 2023 16:33:51 +0000 (17:33 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Mon, 6 Feb 2023 12:57:26 +0000 (13:57 +0100)
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: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/dev/netlink.c

index 8efa22d9f214d2f8b05b6726f22de26633687dd9..02f5c00c521f78b32baafa2185b451d3e4ca69cd 100644 (file)
@@ -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;
 }