diff options
Diffstat (limited to 'include/net/sock.h')
-rw-r--r-- | include/net/sock.h | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index 01810a3f19df..c0b938cb4b1a 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> |
@@ -177,7 +178,6 @@ struct sock_common { | |||
177 | * @sk_dst_cache: destination cache | 178 | * @sk_dst_cache: destination cache |
178 | * @sk_dst_lock: destination cache lock | 179 | * @sk_dst_lock: destination cache lock |
179 | * @sk_policy: flow policy | 180 | * @sk_policy: flow policy |
180 | * @sk_rmem_alloc: receive queue bytes committed | ||
181 | * @sk_receive_queue: incoming packets | 181 | * @sk_receive_queue: incoming packets |
182 | * @sk_wmem_alloc: transmit queue bytes committed | 182 | * @sk_wmem_alloc: transmit queue bytes committed |
183 | * @sk_write_queue: Packet sending queue | 183 | * @sk_write_queue: Packet sending queue |
@@ -1389,6 +1389,59 @@ static inline void sk_nocaps_add(struct sock *sk, int flags) | |||
1389 | sk->sk_route_caps &= ~flags; | 1389 | sk->sk_route_caps &= ~flags; |
1390 | } | 1390 | } |
1391 | 1391 | ||
1392 | static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb, | ||
1393 | char __user *from, char *to, | ||
1394 | int copy, int offset) | ||
1395 | { | ||
1396 | if (skb->ip_summed == CHECKSUM_NONE) { | ||
1397 | int err = 0; | ||
1398 | __wsum csum = csum_and_copy_from_user(from, to, copy, 0, &err); | ||
1399 | if (err) | ||
1400 | return err; | ||
1401 | skb->csum = csum_block_add(skb->csum, csum, offset); | ||
1402 | } else if (sk->sk_route_caps & NETIF_F_NOCACHE_COPY) { | ||
1403 | if (!access_ok(VERIFY_READ, from, copy) || | ||
1404 | __copy_from_user_nocache(to, from, copy)) | ||
1405 | return -EFAULT; | ||
1406 | } else if (copy_from_user(to, from, copy)) | ||
1407 | return -EFAULT; | ||
1408 | |||
1409 | return 0; | ||
1410 | } | ||
1411 | |||
1412 | static inline int skb_add_data_nocache(struct sock *sk, struct sk_buff *skb, | ||
1413 | char __user *from, int copy) | ||
1414 | { | ||
1415 | int err, offset = skb->len; | ||
1416 | |||
1417 | err = skb_do_copy_data_nocache(sk, skb, from, skb_put(skb, copy), | ||
1418 | copy, offset); | ||
1419 | if (err) | ||
1420 | __skb_trim(skb, offset); | ||
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, page_address(page) + off, | ||
1433 | copy, skb->len); | ||
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) |