14 Commits
Author SHA1 Message Date
Paul Hollinsky 8a21b53cd1 v2.0.5
Add support for kernels 5.9+
	Tested on 5.11.0-rc5

CAN frames with length > 8 from userspace are rejected rather
than truncated
2021-01-29 15:54:24 -05:00
Paul Hollinsky 9da27da69e Use non-sensitive kfree function
This is not sensitive data, kzfree was just used for symmetry.

kzfree was actually renamed to kfree_sensitive to show that
the symmetry was unfounded.

This change will allow us to compile in kernels 5.10+
2021-01-29 15:50:05 -05:00
Paul Hollinsky 6bbcf1b527 Reject CAN frames with length > 8
Previously, they were just truncated.

In any case, this is only hit if the userspace daemon
gives us more than 8 bytes for CAN, which it shouldn't.
2021-01-29 15:47:43 -05:00
ARughani-IntrepidandPaul Hollinsky 668e50d08c Typo "accomplished" 2020-08-06 18:10:07 -04:00
Paul Hollinsky 6025ea1349 v2.0.4
Ensure carrier is up on new kernels which require it
2019-11-13 22:49:35 -05:00
Paul Hollinsky d75acfa8a5 v2.0.3
Add support for kernels 5.1+
	Tested on 5.3.0 (Ubuntu 19.10)
2019-11-06 10:14:53 -05:00
Paul Hollinsky 96836cb186 v2.0.2
Add support for older kernels
        Tested working properly back to 4.4
Disabled aliasing for kernels <4.15
        Required, as these kernels do not have netdevice aliasing
Use the correct format specifier for (s)size_t
        Resolves a compile-time warning on 32-bit
Check the return type of copy_from_user
        Resolves a compile-time warning on ARM
Standardize kernel version checking
Requires icsscand >= v2.0.1
        icsscand v2.0.0 will not work with older kernels, and would display an obscure error
2019-08-27 18:39:21 -04:00
Paul Hollinsky 03235819fc Use the correct format specifier for (s)size_t 2019-08-27 18:20:34 -04:00
Paul Hollinsky 5031840429 Resolve warnings about unused variables when aliases are disabled 2019-08-27 18:19:31 -04:00
Paul Hollinsky 17569a82a9 Check the return type of copy_from_user 2019-08-27 18:16:50 -04:00
Paul Hollinsky 3a043ecedd Standardize kernel version check defines 2019-08-27 13:59:47 -04:00
Paul Hollinsky b5dfcee1e1 Support for kernels < 4.10.0
With 4.10.0 and later, the MTU bounds are checked by the kernel

We don't allow the client to set MTU yet so this is somewhat moot
2019-08-27 13:58:03 -04:00
Paul Hollinsky 6c061d771e Tell the kernel our MAX_MTU rather than using CANFD_MTU directly 2019-08-27 13:54:34 -04:00
Paul Hollinsky 408459cbe2 Remove aliasing support for kernels < 4.15 2019-08-27 12:53:44 -04:00
3 changed files with 76 additions and 14 deletions
+33
View File
@@ -0,0 +1,33 @@
v2.0.5
Add support for kernels 5.9+
Tested on 5.11.0-rc5
CAN frames with length > 8 from userspace are rejected rather than truncated
v2.0.4
Ensure carrier is up on new kernels which require it
v2.0.3
Add support for kernels 5.1+
Tested on 5.3.0 (Ubuntu 19.10)
v2.0.2
Add support for older kernels
Tested working properly back to 4.4
Disabled aliasing for kernels <4.15
Required, as these kernels do not have netdevice aliasing
Use the correct format specifier for (s)size_t
Resolves a compile-time warning on 32-bit
Check the return type of copy_from_user
Resolves a compile-time warning on ARM
Standardize kernel version checking
Requires icsscand >= v2.0.1
icsscand v2.0.0 will not work with older kernels, and would display an obscure error
v2.0.1
Resolve runtime warning message on changing MTU
Reviewed our locking behavior, made tweaks where necessary
v2.0.0
Full rewrite
Initial release with CAN-FD support
Requires icsscand >= v2.0.0
+2 -2
View File
@@ -1,10 +1,10 @@
Version 2.0.1 Version 2.0.5
This is the kernel object portion of the Intrepid Control Systems SocketCAN support. For SocketCAN to work with Intrepid devices you will need to have this kernel object loaded on your system. Once the module is built and loaded run [icsscand](https://github.com/intrepidcs/icsscand) to turn on SocketCAN support. This is the kernel object portion of the Intrepid Control Systems SocketCAN support. For SocketCAN to work with Intrepid devices you will need to have this kernel object loaded on your system. Once the module is built and loaded run [icsscand](https://github.com/intrepidcs/icsscand) to turn on SocketCAN support.
First, install the necessary dependencies for building kernel modules. First, install the necessary dependencies for building kernel modules.
On Ubuntu, this is acomplished by running `sudo apt install linux-headers-generic build-essential gcc git` On Ubuntu, this is accomplished by running `sudo apt install linux-headers-generic build-essential gcc git`
Clone this repository by running `git clone https://github.com/intrepidcs/intrepid-socketcan-kernel-module.git` Clone this repository by running `git clone https://github.com/intrepidcs/intrepid-socketcan-kernel-module.git`
+41 -12
View File
@@ -57,7 +57,7 @@
#define KO_DESC "Netdevice driver for Intrepid CAN/Ethernet devices" #define KO_DESC "Netdevice driver for Intrepid CAN/Ethernet devices"
#define KO_MAJOR 2 #define KO_MAJOR 2
#define KO_MINOR 0 #define KO_MINOR 0
#define KO_PATCH 1 #define KO_PATCH 5
#define KO_VERSION str(KO_MAJOR) "." str(KO_MINOR) "." str(KO_PATCH) #define KO_VERSION str(KO_MAJOR) "." str(KO_MINOR) "." str(KO_PATCH)
#define KO_VERSION_INT (KO_MAJOR << 16) | (KO_MINOR << 8) | KO_PATCH #define KO_VERSION_INT (KO_MAJOR << 16) | (KO_MINOR << 8) | KO_PATCH
@@ -89,6 +89,15 @@ MODULE_VERSION(KO_VERSION);
*/ */
#define MAX_MTU CANFD_MTU #define MAX_MTU CANFD_MTU
#define KERNEL_CHECKS_MTU_RANGE (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))
#define KERNEL_FAULT_TAKES_VMA (LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0))
#define KERNEL_SUPPORTS_ALIASES (LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0))
#define KERNEL_DEFINES_VM_FAULT_T (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))
#if KERNEL_DEFINES_VM_FAULT_T == 0
typedef int vm_fault_t;
#endif
struct intrepid_pending_tx_info { struct intrepid_pending_tx_info {
int tx_box_index; int tx_box_index;
int count; int count;
@@ -233,7 +242,7 @@ static netdev_tx_t intrepid_netdevice_xmit(struct sk_buff *skb, struct net_devic
/* This should never happen, the queue should be paused before this */ /* This should never happen, the queue should be paused before this */
ssize_t offset = TX_BOX_SIZE; ssize_t offset = TX_BOX_SIZE;
offset -= (tx_box_bytes[current_tx_box] + sizeof(neomessage_can_t) + msg.length); offset -= (tx_box_bytes[current_tx_box] + sizeof(neomessage_can_t) + msg.length);
pr_err("intrepid: %ld length message caused NETDEV_TX_BUSY (%ld)\n", msg.length, offset); pr_err("intrepid: %zu length message caused NETDEV_TX_BUSY (%zd)\n", msg.length, offset);
ret = NETDEV_TX_BUSY; ret = NETDEV_TX_BUSY;
goto exit; goto exit;
} }
@@ -264,6 +273,7 @@ static int intrepid_netdevice_stop(struct net_device *dev)
spin_lock_bh(&ics->lock); spin_lock_bh(&ics->lock);
netif_stop_queue(dev); netif_stop_queue(dev);
netif_carrier_off(dev);
spin_unlock_bh(&ics->lock); spin_unlock_bh(&ics->lock);
return 0; return 0;
@@ -272,6 +282,7 @@ static int intrepid_netdevice_stop(struct net_device *dev)
static int intrepid_netdevice_open(struct net_device *dev) static int intrepid_netdevice_open(struct net_device *dev)
{ {
netif_start_queue(dev); netif_start_queue(dev);
netif_carrier_on(dev);
return 0; return 0;
} }
@@ -317,7 +328,10 @@ static int intrepid_remove_can_if(int index)
static int intrepid_add_can_if(struct intrepid_netdevice **result, const char *requestedName) static int intrepid_add_can_if(struct intrepid_netdevice **result, const char *requestedName)
{ {
// The `requestedName` parameter is always NULL if KERNEL_SUPPORTS_ALIASES is false
#if KERNEL_SUPPORTS_ALIASES
size_t aliasLen = 0; size_t aliasLen = 0;
#endif
int i; int i;
int ret = -EPERM; int ret = -EPERM;
struct net_device *dev = NULL; struct net_device *dev = NULL;
@@ -345,19 +359,23 @@ static int intrepid_add_can_if(struct intrepid_netdevice **result, const char *r
dev->base_addr = i; dev->base_addr = i;
dev->flags |= IFF_ECHO; dev->flags |= IFF_ECHO;
#if KERNEL_CHECKS_MTU_RANGE
dev->min_mtu = CAN_MTU; dev->min_mtu = CAN_MTU;
dev->max_mtu = CANFD_MTU; dev->max_mtu = MAX_MTU;
#endif
dev->mtu = CANFD_MTU; /* TODO: Check CAN-FD support from usermode daemon */ dev->mtu = CANFD_MTU; /* TODO: Check CAN-FD support from usermode daemon */
dev->netdev_ops = &intrepid_netdevice_ops; dev->netdev_ops = &intrepid_netdevice_ops;
#if KERNEL_SUPPORTS_ALIASES
if (requestedName && ((aliasLen = strlen(requestedName)) > 0) && aliasLen < IFALIASZ) { if (requestedName && ((aliasLen = strlen(requestedName)) > 0) && aliasLen < IFALIASZ) {
dev->ifalias = kzalloc(sizeof(struct dev_ifalias) + aliasLen + 1, GFP_KERNEL); dev->ifalias = kzalloc(sizeof(struct dev_ifalias) + aliasLen + 1, GFP_KERNEL);
if (dev->ifalias == NULL) { if (dev->ifalias == NULL) {
pr_alert("intrepid: Could not allocate space for ifalias %lu\n", sizeof(struct dev_ifalias)); pr_alert("intrepid: Could not allocate space for ifalias %zu\n", sizeof(struct dev_ifalias));
} else { } else {
strncpy(dev->ifalias->ifalias, requestedName, aliasLen + 1); strncpy(dev->ifalias->ifalias, requestedName, aliasLen + 1);
pr_info("intrepid: %s alias set to %s\n", dev->name, requestedName); pr_info("intrepid: %s alias set to %s\n", dev->name, requestedName);
} }
} }
#endif
ics = netdev_priv(dev); ics = netdev_priv(dev);
ics->dev = dev; ics->dev = dev;
ics->is_stopped = 0; ics->is_stopped = 0;
@@ -453,7 +471,10 @@ static int intrepid_fill_can_frame_from_neomessage(
if (msg->status.remoteFrame) if (msg->status.remoteFrame)
cf->can_id |= CAN_RTR_FLAG; cf->can_id |= CAN_RTR_FLAG;
cf->can_dlc = get_can_dlc(msg->length); if (unlikely(msg->length > 8))
return -1;
cf->can_dlc = msg->length;
memcpy(cf->data, data, cf->can_dlc); memcpy(cf->data, data, cf->can_dlc);
stats->rx_bytes += cf->can_dlc; stats->rx_bytes += cf->can_dlc;
@@ -582,14 +603,20 @@ static long intrepid_dev_ioctl(struct file *fp, unsigned int cmd, unsigned long
switch (cmd) { switch (cmd) {
case SIOCSADDIF: { case SIOCSADDIF: {
struct intrepid_netdevice *result = NULL; struct intrepid_netdevice *result = NULL;
#if KERNEL_SUPPORTS_ALIASES
char requestedNameBuffer[IFALIASZ] = {0}; char requestedNameBuffer[IFALIASZ] = {0};
char* requestedName = NULL; char* requestedName = NULL;
int bytesNotCopied = 0;
if ((void __user*)arg != NULL) { if ((void __user*)arg != NULL) {
copy_from_user(requestedNameBuffer, (void __user*)arg, IFALIASZ); bytesNotCopied = copy_from_user(requestedNameBuffer, (void __user*)arg, IFALIASZ);
if(bytesNotCopied != 0)
pr_warn("intrepid: %d bytes not copied for alias", bytesNotCopied);
requestedName = requestedNameBuffer; requestedName = requestedNameBuffer;
} }
ret = intrepid_add_can_if(&result, requestedName); ret = intrepid_add_can_if(&result, requestedName);
#else
ret = intrepid_add_can_if(&result, NULL);
#endif
break; break;
} }
case SIOCSREMOVEIF: case SIOCSREMOVEIF:
@@ -607,9 +634,11 @@ static long intrepid_dev_ioctl(struct file *fp, unsigned int cmd, unsigned long
case SIOCGCLIENTVEROK: case SIOCGCLIENTVEROK:
/* Here we can do checks to see if the usermode daemon is /* Here we can do checks to see if the usermode daemon is
* a compatible version with us. We don't enforce anything * a compatible version with us. We don't enforce anything
* on the kernel side. For now, being version 2.X.X is good. * on the kernel side. icsscand v2.0.0 will not work with
* older kernels, and would display an obscure error, thus
* we want to ask the user to update to v2.0.1 or later
*/ */
if (VER_MAJ_FROM_INT(arg) == 2) if (VER_MAJ_FROM_INT(arg) == 2 && (VER_MIN_FROM_INT(arg) > 0 || VER_PATCH_FROM_INT(arg) >= 1))
ret = 0; /* ok to start */ ret = 0; /* ok to start */
else else
ret = 1; ret = 1;
@@ -632,8 +661,8 @@ static long intrepid_dev_ioctl(struct file *fp, unsigned int cmd, unsigned long
* *
* Starting in kernel version 4.11, (struct vm_operations_struct *)->fault() no * Starting in kernel version 4.11, (struct vm_operations_struct *)->fault() no
* longer takes the vma parameter (since it resides in vmf) */ * longer takes the vma parameter (since it resides in vmf) */
static int intrepid_vm_fault( static vm_fault_t intrepid_vm_fault(
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) #if KERNEL_FAULT_TAKES_VMA
struct vm_area_struct *vma, struct vm_area_struct *vma,
#endif #endif
struct vm_fault *vmf) struct vm_fault *vmf)
@@ -809,7 +838,7 @@ exit:
return ret; return ret;
free_net_devices: free_net_devices:
kzfree(net_devices); kfree(net_devices);
free_shared_mem: free_shared_mem:
vfree(shared_mem); vfree(shared_mem);
return ret; return ret;