diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/netdevice.h | 3 | ||||
-rw-r--r-- | include/net/sock.h | 53 |
2 files changed, 55 insertions, 1 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a4664cc68e2b..09d262415769 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1066,6 +1066,7 @@ struct net_device { | |||
1066 | #define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */ | 1066 | #define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */ |
1067 | #define NETIF_F_RXHASH (1 << 28) /* Receive hashing offload */ | 1067 | #define NETIF_F_RXHASH (1 << 28) /* Receive hashing offload */ |
1068 | #define NETIF_F_RXCSUM (1 << 29) /* Receive checksumming offload */ | 1068 | #define NETIF_F_RXCSUM (1 << 29) /* Receive checksumming offload */ |
1069 | #define NETIF_F_NOCACHE_COPY (1 << 30) /* Use no-cache copyfromuser */ | ||
1069 | 1070 | ||
1070 | /* Segmentation offload features */ | 1071 | /* Segmentation offload features */ |
1071 | #define NETIF_F_GSO_SHIFT 16 | 1072 | #define NETIF_F_GSO_SHIFT 16 |
@@ -1081,7 +1082,7 @@ struct net_device { | |||
1081 | /* = all defined minus driver/device-class-related */ | 1082 | /* = all defined minus driver/device-class-related */ |
1082 | #define NETIF_F_NEVER_CHANGE (NETIF_F_HIGHDMA | NETIF_F_VLAN_CHALLENGED | \ | 1083 | #define NETIF_F_NEVER_CHANGE (NETIF_F_HIGHDMA | NETIF_F_VLAN_CHALLENGED | \ |
1083 | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL) | 1084 | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL) |
1084 | #define NETIF_F_ETHTOOL_BITS (0x3f3fffff & ~NETIF_F_NEVER_CHANGE) | 1085 | #define NETIF_F_ETHTOOL_BITS (0x7f3fffff & ~NETIF_F_NEVER_CHANGE) |
1085 | 1086 | ||
1086 | /* List of features with software fallbacks. */ | 1087 | /* List of features with software fallbacks. */ |
1087 | #define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ | 1088 | #define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ |
diff --git a/include/net/sock.h b/include/net/sock.h index da0534d3401c..43bd515e92fd 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/security.h> | 53 | #include <linux/security.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/uaccess.h> | ||
55 | 56 | ||
56 | #include <linux/filter.h> | 57 | #include <linux/filter.h> |
57 | #include <linux/rculist_nulls.h> | 58 | #include <linux/rculist_nulls.h> |
@@ -1389,6 +1390,58 @@ static inline void sk_nocaps_add(struct sock *sk, int flags) | |||
1389 | sk->sk_route_caps &= ~flags; | 1390 | sk->sk_route_caps &= ~flags; |
1390 | } | 1391 | } |
1391 | 1392 | ||
1393 | static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb, | ||
1394 | char __user *from, char *to, | ||
1395 | int copy) | ||
1396 | { | ||
1397 | if (skb->ip_summed == CHECKSUM_NONE) { | ||
1398 | int err = 0; | ||
1399 | __wsum csum = csum_and_copy_from_user(from, to, copy, 0, &err); | ||
1400 | if (err) | ||
1401 | return err; | ||
1402 | skb->csum = csum_block_add(skb->csum, csum, skb->len); | ||
1403 | } else if (sk->sk_route_caps & NETIF_F_NOCACHE_COPY) { | ||
1404 | if (!access_ok(VERIFY_READ, from, copy) || | ||
1405 | __copy_from_user_nocache(to, from, copy)) | ||
1406 | return -EFAULT; | ||
1407 | } else if (copy_from_user(to, from, copy)) | ||
1408 | return -EFAULT; | ||
1409 | |||
1410 | return 0; | ||
1411 | } | ||
1412 | |||
1413 | static inline int skb_add_data_nocache(struct sock *sk, struct sk_buff *skb, | ||
1414 | char __user *from, int copy) | ||
1415 | { | ||
1416 | int err; | ||
1417 | |||
1418 | err = skb_do_copy_data_nocache(sk, skb, from, skb_put(skb, copy), copy); | ||
1419 | if (err) | ||
1420 | __skb_trim(skb, skb->len); | ||
1421 | |||
1422 | return err; | ||
1423 | } | ||
1424 | |||
1425 | static inline int skb_copy_to_page_nocache(struct sock *sk, char __user *from, | ||
1426 | struct sk_buff *skb, | ||
1427 | struct page *page, | ||
1428 | int off, int copy) | ||
1429 | { | ||
1430 | int err; | ||
1431 | |||
1432 | err = skb_do_copy_data_nocache(sk, skb, from, | ||
1433 | page_address(page) + off, copy); | ||
1434 | if (err) | ||
1435 | return err; | ||
1436 | |||
1437 | skb->len += copy; | ||
1438 | skb->data_len += copy; | ||
1439 | skb->truesize += copy; | ||
1440 | sk->sk_wmem_queued += copy; | ||
1441 | sk_mem_charge(sk, copy); | ||
1442 | return 0; | ||
1443 | } | ||
1444 | |||
1392 | static inline int skb_copy_to_page(struct sock *sk, char __user *from, | 1445 | static inline int skb_copy_to_page(struct sock *sk, char __user *from, |
1393 | struct sk_buff *skb, struct page *page, | 1446 | struct sk_buff *skb, struct page *page, |
1394 | int off, int copy) | 1447 | int off, int copy) |