Commit a0bfd73d authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-next-for-5.18-20220316' of...

Merge tag 'linux-can-next-for-5.18-20220316' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2022-03-16

the first 3 patches are by Oliver Hartkopp target the CAN ISOTP
protocol and fix a problem found by syzbot in isotp_bind(), return
-EADDRNOTAVAIL in unbound sockets in isotp_recvmsg() and add support
for MSG_TRUNC to isotp_recvmsg().

Amit Kumar Mahapatra converts the xilinx,can device tree bindings to
yaml.

The last patch is by Julia Lawall and fixes typos in the ucan driver.

* tag 'linux-can-next-for-5.18-20220316' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next:
  can: ucan: fix typos in comments
  dt-bindings: can: xilinx_can: Convert Xilinx CAN binding to YAML
  can: isotp: support MSG_TRUNC flag when reading from socket
  can: isotp: return -EADDRNOTAVAIL when reading from unbound socket
  can: isotp: sanitize CAN ID checks in isotp_bind()
====================

Link: https://lore.kernel.org/r/20220316204710.716341-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b1351527 c34983c9
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/can/xilinx,can.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title:
Xilinx Axi CAN/Zynq CANPS controller
maintainers:
- Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
properties:
compatible:
enum:
- xlnx,zynq-can-1.0
- xlnx,axi-can-1.00.a
- xlnx,canfd-1.0
- xlnx,canfd-2.0
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
maxItems: 2
power-domains:
maxItems: 1
tx-fifo-depth:
$ref: "/schemas/types.yaml#/definitions/uint32"
description: CAN Tx fifo depth (Zynq, Axi CAN).
rx-fifo-depth:
$ref: "/schemas/types.yaml#/definitions/uint32"
description: CAN Rx fifo depth (Zynq, Axi CAN, CAN FD in sequential Rx mode)
tx-mailbox-count:
$ref: "/schemas/types.yaml#/definitions/uint32"
description: CAN Tx mailbox buffer count (CAN FD)
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
allOf:
- $ref: can-controller.yaml#
- if:
properties:
compatible:
contains:
enum:
- xlnx,zynq-can-1.0
then:
properties:
clock-names:
items:
- const: can_clk
- const: pclk
required:
- tx-fifo-depth
- rx-fifo-depth
- if:
properties:
compatible:
contains:
enum:
- xlnx,axi-can-1.00.a
then:
properties:
clock-names:
items:
- const: can_clk
- const: s_axi_aclk
required:
- tx-fifo-depth
- rx-fifo-depth
- if:
properties:
compatible:
contains:
enum:
- xlnx,canfd-1.0
- xlnx,canfd-2.0
then:
properties:
clock-names:
items:
- const: can_clk
- const: s_axi_aclk
required:
- tx-mailbox-count
- rx-fifo-depth
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
can@e0008000 {
compatible = "xlnx,zynq-can-1.0";
reg = <0xe0008000 0x1000>;
clocks = <&clkc 19>, <&clkc 36>;
clock-names = "can_clk", "pclk";
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&intc>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
- |
can@40000000 {
compatible = "xlnx,axi-can-1.00.a";
reg = <0x40000000 0x10000>;
clocks = <&clkc 0>, <&clkc 1>;
clock-names = "can_clk", "s_axi_aclk";
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 59 IRQ_TYPE_EDGE_RISING>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
- |
can@40000000 {
compatible = "xlnx,canfd-1.0";
reg = <0x40000000 0x2000>;
clocks = <&clkc 0>, <&clkc 1>;
clock-names = "can_clk", "s_axi_aclk";
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 59 IRQ_TYPE_EDGE_RISING>;
tx-mailbox-count = <0x20>;
rx-fifo-depth = <0x20>;
};
- |
can@ff060000 {
compatible = "xlnx,canfd-2.0";
reg = <0xff060000 0x6000>;
clocks = <&clkc 0>, <&clkc 1>;
clock-names = "can_clk", "s_axi_aclk";
interrupt-parent = <&intc>;
interrupts = <GIC_SPI 59 IRQ_TYPE_EDGE_RISING>;
tx-mailbox-count = <0x20>;
rx-fifo-depth = <0x40>;
};
Xilinx Axi CAN/Zynq CANPS controller Device Tree Bindings
---------------------------------------------------------
Required properties:
- compatible : Should be:
- "xlnx,zynq-can-1.0" for Zynq CAN controllers
- "xlnx,axi-can-1.00.a" for Axi CAN controllers
- "xlnx,canfd-1.0" for CAN FD controllers
- "xlnx,canfd-2.0" for CAN FD 2.0 controllers
- reg : Physical base address and size of the controller
registers map.
- interrupts : Property with a value describing the interrupt
number.
- clock-names : List of input clock names
- "can_clk", "pclk" (For CANPS),
- "can_clk", "s_axi_aclk" (For AXI CAN and CAN FD).
(See clock bindings for details).
- clocks : Clock phandles (see clock bindings for details).
- tx-fifo-depth : Can Tx fifo depth (Zynq, Axi CAN).
- rx-fifo-depth : Can Rx fifo depth (Zynq, Axi CAN, CAN FD in
sequential Rx mode).
- tx-mailbox-count : Can Tx mailbox buffer count (CAN FD).
- rx-mailbox-count : Can Rx mailbox buffer count (CAN FD in mailbox Rx
mode).
Example:
For Zynq CANPS Dts file:
zynq_can_0: can@e0008000 {
compatible = "xlnx,zynq-can-1.0";
clocks = <&clkc 19>, <&clkc 36>;
clock-names = "can_clk", "pclk";
reg = <0xe0008000 0x1000>;
interrupts = <0 28 4>;
interrupt-parent = <&intc>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
For Axi CAN Dts file:
axi_can_0: axi-can@40000000 {
compatible = "xlnx,axi-can-1.00.a";
clocks = <&clkc 0>, <&clkc 1>;
clock-names = "can_clk","s_axi_aclk" ;
reg = <0x40000000 0x10000>;
interrupt-parent = <&intc>;
interrupts = <0 59 1>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
For CAN FD Dts file:
canfd_0: canfd@40000000 {
compatible = "xlnx,canfd-1.0";
clocks = <&clkc 0>, <&clkc 1>;
clock-names = "can_clk", "s_axi_aclk";
reg = <0x40000000 0x2000>;
interrupt-parent = <&intc>;
interrupts = <0 59 1>;
tx-mailbox-count = <0x20>;
rx-fifo-depth = <0x20>;
};
...@@ -1392,7 +1392,7 @@ static int ucan_probe(struct usb_interface *intf, ...@@ -1392,7 +1392,7 @@ static int ucan_probe(struct usb_interface *intf,
* Stage 3 for the final driver initialisation. * Stage 3 for the final driver initialisation.
*/ */
/* Prepare Memory for control transferes */ /* Prepare Memory for control transfers */
ctl_msg_buffer = devm_kzalloc(&udev->dev, ctl_msg_buffer = devm_kzalloc(&udev->dev,
sizeof(union ucan_ctl_payload), sizeof(union ucan_ctl_payload),
GFP_KERNEL); GFP_KERNEL);
...@@ -1526,7 +1526,7 @@ static int ucan_probe(struct usb_interface *intf, ...@@ -1526,7 +1526,7 @@ static int ucan_probe(struct usb_interface *intf,
ret = ucan_device_request_in(up, UCAN_DEVICE_GET_FW_STRING, 0, ret = ucan_device_request_in(up, UCAN_DEVICE_GET_FW_STRING, 0,
sizeof(union ucan_ctl_payload)); sizeof(union ucan_ctl_payload));
if (ret > 0) { if (ret > 0) {
/* copy string while ensuring zero terminiation */ /* copy string while ensuring zero termination */
strncpy(firmware_str, up->ctl_msg_buffer->raw, strncpy(firmware_str, up->ctl_msg_buffer->raw,
sizeof(union ucan_ctl_payload)); sizeof(union ucan_ctl_payload));
firmware_str[sizeof(union ucan_ctl_payload)] = '\0'; firmware_str[sizeof(union ucan_ctl_payload)] = '\0';
......
...@@ -1046,26 +1046,29 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, ...@@ -1046,26 +1046,29 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct sk_buff *skb; struct sk_buff *skb;
int err = 0; struct isotp_sock *so = isotp_sk(sk);
int noblock; int noblock = flags & MSG_DONTWAIT;
int ret = 0;
noblock = flags & MSG_DONTWAIT; if (flags & ~(MSG_DONTWAIT | MSG_TRUNC))
flags &= ~MSG_DONTWAIT; return -EINVAL;
if (!so->bound)
return -EADDRNOTAVAIL;
skb = skb_recv_datagram(sk, flags, noblock, &err); flags &= ~MSG_DONTWAIT;
skb = skb_recv_datagram(sk, flags, noblock, &ret);
if (!skb) if (!skb)
return err; return ret;
if (size < skb->len) if (size < skb->len)
msg->msg_flags |= MSG_TRUNC; msg->msg_flags |= MSG_TRUNC;
else else
size = skb->len; size = skb->len;
err = memcpy_to_msg(msg, skb->data, size); ret = memcpy_to_msg(msg, skb->data, size);
if (err < 0) { if (ret < 0)
skb_free_datagram(sk, skb); goto out_err;
return err;
}
sock_recv_timestamp(msg, sk, skb); sock_recv_timestamp(msg, sk, skb);
...@@ -1075,9 +1078,13 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, ...@@ -1075,9 +1078,13 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
memcpy(msg->msg_name, skb->cb, msg->msg_namelen); memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
} }
/* set length of return value */
ret = (flags & MSG_TRUNC) ? skb->len : size;
out_err:
skb_free_datagram(sk, skb); skb_free_datagram(sk, skb);
return size; return ret;
} }
static int isotp_release(struct socket *sock) static int isotp_release(struct socket *sock)
...@@ -1148,6 +1155,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len) ...@@ -1148,6 +1155,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
int ifindex; int ifindex;
struct net_device *dev; struct net_device *dev;
canid_t tx_id, rx_id;
int err = 0; int err = 0;
int notify_enetdown = 0; int notify_enetdown = 0;
int do_rx_reg = 1; int do_rx_reg = 1;
...@@ -1155,8 +1163,18 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len) ...@@ -1155,8 +1163,18 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
if (len < ISOTP_MIN_NAMELEN) if (len < ISOTP_MIN_NAMELEN)
return -EINVAL; return -EINVAL;
if (addr->can_addr.tp.tx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) /* sanitize tx/rx CAN identifiers */
return -EADDRNOTAVAIL; tx_id = addr->can_addr.tp.tx_id;
if (tx_id & CAN_EFF_FLAG)
tx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
else
tx_id &= CAN_SFF_MASK;
rx_id = addr->can_addr.tp.rx_id;
if (rx_id & CAN_EFF_FLAG)
rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);
else
rx_id &= CAN_SFF_MASK;
if (!addr->can_ifindex) if (!addr->can_ifindex)
return -ENODEV; return -ENODEV;
...@@ -1168,21 +1186,13 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len) ...@@ -1168,21 +1186,13 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
do_rx_reg = 0; do_rx_reg = 0;
/* do not validate rx address for functional addressing */ /* do not validate rx address for functional addressing */
if (do_rx_reg) { if (do_rx_reg && rx_id == tx_id) {
if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id) {
err = -EADDRNOTAVAIL;
goto out;
}
if (addr->can_addr.tp.rx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) {
err = -EADDRNOTAVAIL; err = -EADDRNOTAVAIL;
goto out; goto out;
} }
}
if (so->bound && addr->can_ifindex == so->ifindex && if (so->bound && addr->can_ifindex == so->ifindex &&
addr->can_addr.tp.rx_id == so->rxid && rx_id == so->rxid && tx_id == so->txid)
addr->can_addr.tp.tx_id == so->txid)
goto out; goto out;
dev = dev_get_by_index(net, addr->can_ifindex); dev = dev_get_by_index(net, addr->can_ifindex);
...@@ -1206,16 +1216,14 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len) ...@@ -1206,16 +1216,14 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
ifindex = dev->ifindex; ifindex = dev->ifindex;
if (do_rx_reg) { if (do_rx_reg) {
can_rx_register(net, dev, addr->can_addr.tp.rx_id, can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id),
SINGLE_MASK(addr->can_addr.tp.rx_id),
isotp_rcv, sk, "isotp", sk); isotp_rcv, sk, "isotp", sk);
/* no consecutive frame echo skb in flight */ /* no consecutive frame echo skb in flight */
so->cfecho = 0; so->cfecho = 0;
/* register for echo skb's */ /* register for echo skb's */
can_rx_register(net, dev, addr->can_addr.tp.tx_id, can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),
SINGLE_MASK(addr->can_addr.tp.tx_id),
isotp_rcv_echo, sk, "isotpe", sk); isotp_rcv_echo, sk, "isotpe", sk);
} }
...@@ -1239,8 +1247,8 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len) ...@@ -1239,8 +1247,8 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
/* switch to new settings */ /* switch to new settings */
so->ifindex = ifindex; so->ifindex = ifindex;
so->rxid = addr->can_addr.tp.rx_id; so->rxid = rx_id;
so->txid = addr->can_addr.tp.tx_id; so->txid = tx_id;
so->bound = 1; so->bound = 1;
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment