950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. From 4b729a06b15fc5ee3694dcc62346dcb718ae4290 Mon Sep 17 00:00:00 2001
  2. From: Oliver Hartkopp <[email protected]>
  3. Date: Sun, 26 Mar 2023 13:59:11 +0200
  4. Subject: [PATCH] can: isotp: add module parameter for maximum pdu size
  5. commit 96d1c81e6a0478535342dff6c730adb076cd84e8 upstream.
  6. With ISO 15765-2:2016 the PDU size is not limited to 2^12 - 1 (4095)
  7. bytes but can be represented as a 32 bit unsigned integer value which
  8. allows 2^32 - 1 bytes (~4GB). The use-cases like automotive unified
  9. diagnostic services (UDS) and flashing of ECUs still use the small
  10. static buffers which are provided at socket creation time.
  11. When a use-case requires to transfer PDUs up to 1025 kByte the maximum
  12. PDU size can now be extended by setting the module parameter
  13. max_pdu_size. The extended size buffers are only allocated on a
  14. per-socket/connection base when needed at run-time.
  15. changes since v2: https://lore.kernel.org/all/[email protected]
  16. - use ARRAY_SIZE() to reference DEFAULT_MAX_PDU_SIZE only at one place
  17. changes since v1: https://lore.kernel.org/all/[email protected]
  18. - limit the minimum 'max_pdu_size' to 4095 to maintain the classic
  19. behavior before ISO 15765-2:2016
  20. Link: https://github.com/raspberrypi/linux/issues/5371
  21. Signed-off-by: Oliver Hartkopp <[email protected]>
  22. Link: https://lore.kernel.org/all/[email protected]
  23. Signed-off-by: Marc Kleine-Budde <[email protected]>
  24. ---
  25. net/can/isotp.c | 65 ++++++++++++++++++++++++++++++++++++++++++-------
  26. 1 file changed, 56 insertions(+), 9 deletions(-)
  27. --- a/net/can/isotp.c
  28. +++ b/net/can/isotp.c
  29. @@ -85,10 +85,21 @@ MODULE_ALIAS("can-proto-6");
  30. /* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can
  31. * take full 32 bit values (4 Gbyte). We would need some good concept to handle
  32. - * this between user space and kernel space. For now increase the static buffer
  33. - * to something about 64 kbyte to be able to test this new functionality.
  34. + * this between user space and kernel space. For now set the static buffer to
  35. + * something about 8 kbyte to be able to test this new functionality.
  36. */
  37. -#define MAX_MSG_LENGTH 66000
  38. +#define DEFAULT_MAX_PDU_SIZE 8300
  39. +
  40. +/* maximum PDU size before ISO 15765-2:2016 extension was 4095 */
  41. +#define MAX_12BIT_PDU_SIZE 4095
  42. +
  43. +/* limit the isotp pdu size from the optional module parameter to 1MByte */
  44. +#define MAX_PDU_SIZE (1025 * 1024U)
  45. +
  46. +static unsigned int max_pdu_size __read_mostly = DEFAULT_MAX_PDU_SIZE;
  47. +module_param(max_pdu_size, uint, 0444);
  48. +MODULE_PARM_DESC(max_pdu_size, "maximum isotp pdu size (default "
  49. + __stringify(DEFAULT_MAX_PDU_SIZE) ")");
  50. /* N_PCI type values in bits 7-4 of N_PCI bytes */
  51. #define N_PCI_SF 0x00 /* single frame */
  52. @@ -124,13 +135,15 @@ enum {
  53. };
  54. struct tpcon {
  55. - unsigned int idx;
  56. + u8 *buf;
  57. + unsigned int buflen;
  58. unsigned int len;
  59. + unsigned int idx;
  60. u32 state;
  61. u8 bs;
  62. u8 sn;
  63. u8 ll_dl;
  64. - u8 buf[MAX_MSG_LENGTH + 1];
  65. + u8 sbuf[DEFAULT_MAX_PDU_SIZE];
  66. };
  67. struct isotp_sock {
  68. @@ -498,7 +511,17 @@ static int isotp_rcv_ff(struct sock *sk,
  69. if (so->rx.len + ae + off + ff_pci_sz < so->rx.ll_dl)
  70. return 1;
  71. - if (so->rx.len > MAX_MSG_LENGTH) {
  72. + /* PDU size > default => try max_pdu_size */
  73. + if (so->rx.len > so->rx.buflen && so->rx.buflen < max_pdu_size) {
  74. + u8 *newbuf = kmalloc(max_pdu_size, GFP_ATOMIC);
  75. +
  76. + if (newbuf) {
  77. + so->rx.buf = newbuf;
  78. + so->rx.buflen = max_pdu_size;
  79. + }
  80. + }
  81. +
  82. + if (so->rx.len > so->rx.buflen) {
  83. /* send FC frame with overflow status */
  84. isotp_send_fc(sk, ae, ISOTP_FC_OVFLW);
  85. return 1;
  86. @@ -802,7 +825,7 @@ static void isotp_create_fframe(struct c
  87. cf->data[0] = so->opt.ext_address;
  88. /* create N_PCI bytes with 12/32 bit FF_DL data length */
  89. - if (so->tx.len > 4095) {
  90. + if (so->tx.len > MAX_12BIT_PDU_SIZE) {
  91. /* use 32 bit FF_DL notation */
  92. cf->data[ae] = N_PCI_FF;
  93. cf->data[ae + 1] = 0;
  94. @@ -939,7 +962,17 @@ static int isotp_sendmsg(struct socket *
  95. goto err_event_drop;
  96. }
  97. - if (!size || size > MAX_MSG_LENGTH) {
  98. + /* PDU size > default => try max_pdu_size */
  99. + if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) {
  100. + u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL);
  101. +
  102. + if (newbuf) {
  103. + so->tx.buf = newbuf;
  104. + so->tx.buflen = max_pdu_size;
  105. + }
  106. + }
  107. +
  108. + if (!size || size > so->tx.buflen) {
  109. err = -EINVAL;
  110. goto err_out_drop;
  111. }
  112. @@ -1194,6 +1227,12 @@ static int isotp_release(struct socket *
  113. so->ifindex = 0;
  114. so->bound = 0;
  115. + if (so->rx.buf != so->rx.sbuf)
  116. + kfree(so->rx.buf);
  117. +
  118. + if (so->tx.buf != so->tx.sbuf)
  119. + kfree(so->tx.buf);
  120. +
  121. sock_orphan(sk);
  122. sock->sk = NULL;
  123. @@ -1588,6 +1627,11 @@ static int isotp_init(struct sock *sk)
  124. so->rx.state = ISOTP_IDLE;
  125. so->tx.state = ISOTP_IDLE;
  126. + so->rx.buf = so->rx.sbuf;
  127. + so->tx.buf = so->tx.sbuf;
  128. + so->rx.buflen = ARRAY_SIZE(so->rx.sbuf);
  129. + so->tx.buflen = ARRAY_SIZE(so->tx.sbuf);
  130. +
  131. hrtimer_init(&so->rxtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
  132. so->rxtimer.function = isotp_rx_timer_handler;
  133. hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
  134. @@ -1670,7 +1714,10 @@ static __init int isotp_module_init(void
  135. {
  136. int err;
  137. - pr_info("can: isotp protocol\n");
  138. + max_pdu_size = max_t(unsigned int, max_pdu_size, MAX_12BIT_PDU_SIZE);
  139. + max_pdu_size = min_t(unsigned int, max_pdu_size, MAX_PDU_SIZE);
  140. +
  141. + pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size);
  142. err = can_proto_register(&isotp_can_proto);
  143. if (err < 0)