diff options
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 101 |
1 files changed, 66 insertions, 35 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index ef30e9d286e7..6e819780c232 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -157,7 +157,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = { | |||
157 | "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , | 157 | "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , |
158 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , | 158 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , |
159 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , | 159 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , |
160 | "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , | 160 | "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" , |
161 | "sk_lock-AF_MAX" | 161 | "sk_lock-AF_MAX" |
162 | }; | 162 | }; |
163 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { | 163 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { |
@@ -173,7 +173,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = { | |||
173 | "slock-27" , "slock-28" , "slock-AF_CAN" , | 173 | "slock-27" , "slock-28" , "slock-AF_CAN" , |
174 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , | 174 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , |
175 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , | 175 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , |
176 | "slock-AF_IEEE802154", "slock-AF_CAIF" , | 176 | "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" , |
177 | "slock-AF_MAX" | 177 | "slock-AF_MAX" |
178 | }; | 178 | }; |
179 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { | 179 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { |
@@ -189,7 +189,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = { | |||
189 | "clock-27" , "clock-28" , "clock-AF_CAN" , | 189 | "clock-27" , "clock-28" , "clock-AF_CAN" , |
190 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , | 190 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , |
191 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , | 191 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , |
192 | "clock-AF_IEEE802154", "clock-AF_CAIF" , | 192 | "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" , |
193 | "clock-AF_MAX" | 193 | "clock-AF_MAX" |
194 | }; | 194 | }; |
195 | 195 | ||
@@ -215,7 +215,7 @@ __u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX; | |||
215 | __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; | 215 | __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; |
216 | __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; | 216 | __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; |
217 | 217 | ||
218 | /* Maximal space eaten by iovec or ancilliary data plus some space */ | 218 | /* Maximal space eaten by iovec or ancillary data plus some space */ |
219 | int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); | 219 | int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); |
220 | EXPORT_SYMBOL(sysctl_optmem_max); | 220 | EXPORT_SYMBOL(sysctl_optmem_max); |
221 | 221 | ||
@@ -992,23 +992,54 @@ static inline void sock_lock_init(struct sock *sk) | |||
992 | /* | 992 | /* |
993 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, | 993 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, |
994 | * even temporarly, because of RCU lookups. sk_node should also be left as is. | 994 | * even temporarly, because of RCU lookups. sk_node should also be left as is. |
995 | * We must not copy fields between sk_dontcopy_begin and sk_dontcopy_end | ||
995 | */ | 996 | */ |
996 | static void sock_copy(struct sock *nsk, const struct sock *osk) | 997 | static void sock_copy(struct sock *nsk, const struct sock *osk) |
997 | { | 998 | { |
998 | #ifdef CONFIG_SECURITY_NETWORK | 999 | #ifdef CONFIG_SECURITY_NETWORK |
999 | void *sptr = nsk->sk_security; | 1000 | void *sptr = nsk->sk_security; |
1000 | #endif | 1001 | #endif |
1001 | BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) != | 1002 | memcpy(nsk, osk, offsetof(struct sock, sk_dontcopy_begin)); |
1002 | sizeof(osk->sk_node) + sizeof(osk->sk_refcnt) + | 1003 | |
1003 | sizeof(osk->sk_tx_queue_mapping)); | 1004 | memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end, |
1004 | memcpy(&nsk->sk_copy_start, &osk->sk_copy_start, | 1005 | osk->sk_prot->obj_size - offsetof(struct sock, sk_dontcopy_end)); |
1005 | osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start)); | 1006 | |
1006 | #ifdef CONFIG_SECURITY_NETWORK | 1007 | #ifdef CONFIG_SECURITY_NETWORK |
1007 | nsk->sk_security = sptr; | 1008 | nsk->sk_security = sptr; |
1008 | security_sk_clone(osk, nsk); | 1009 | security_sk_clone(osk, nsk); |
1009 | #endif | 1010 | #endif |
1010 | } | 1011 | } |
1011 | 1012 | ||
1013 | /* | ||
1014 | * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes | ||
1015 | * un-modified. Special care is taken when initializing object to zero. | ||
1016 | */ | ||
1017 | static inline void sk_prot_clear_nulls(struct sock *sk, int size) | ||
1018 | { | ||
1019 | if (offsetof(struct sock, sk_node.next) != 0) | ||
1020 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
1021 | memset(&sk->sk_node.pprev, 0, | ||
1022 | size - offsetof(struct sock, sk_node.pprev)); | ||
1023 | } | ||
1024 | |||
1025 | void sk_prot_clear_portaddr_nulls(struct sock *sk, int size) | ||
1026 | { | ||
1027 | unsigned long nulls1, nulls2; | ||
1028 | |||
1029 | nulls1 = offsetof(struct sock, __sk_common.skc_node.next); | ||
1030 | nulls2 = offsetof(struct sock, __sk_common.skc_portaddr_node.next); | ||
1031 | if (nulls1 > nulls2) | ||
1032 | swap(nulls1, nulls2); | ||
1033 | |||
1034 | if (nulls1 != 0) | ||
1035 | memset((char *)sk, 0, nulls1); | ||
1036 | memset((char *)sk + nulls1 + sizeof(void *), 0, | ||
1037 | nulls2 - nulls1 - sizeof(void *)); | ||
1038 | memset((char *)sk + nulls2 + sizeof(void *), 0, | ||
1039 | size - nulls2 - sizeof(void *)); | ||
1040 | } | ||
1041 | EXPORT_SYMBOL(sk_prot_clear_portaddr_nulls); | ||
1042 | |||
1012 | static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, | 1043 | static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, |
1013 | int family) | 1044 | int family) |
1014 | { | 1045 | { |
@@ -1021,19 +1052,12 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, | |||
1021 | if (!sk) | 1052 | if (!sk) |
1022 | return sk; | 1053 | return sk; |
1023 | if (priority & __GFP_ZERO) { | 1054 | if (priority & __GFP_ZERO) { |
1024 | /* | 1055 | if (prot->clear_sk) |
1025 | * caches using SLAB_DESTROY_BY_RCU should let | 1056 | prot->clear_sk(sk, prot->obj_size); |
1026 | * sk_node.next un-modified. Special care is taken | 1057 | else |
1027 | * when initializing object to zero. | 1058 | sk_prot_clear_nulls(sk, prot->obj_size); |
1028 | */ | ||
1029 | if (offsetof(struct sock, sk_node.next) != 0) | ||
1030 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
1031 | memset(&sk->sk_node.pprev, 0, | ||
1032 | prot->obj_size - offsetof(struct sock, | ||
1033 | sk_node.pprev)); | ||
1034 | } | 1059 | } |
1035 | } | 1060 | } else |
1036 | else | ||
1037 | sk = kmalloc(prot->obj_size, priority); | 1061 | sk = kmalloc(prot->obj_size, priority); |
1038 | 1062 | ||
1039 | if (sk != NULL) { | 1063 | if (sk != NULL) { |
@@ -1078,8 +1102,11 @@ static void sk_prot_free(struct proto *prot, struct sock *sk) | |||
1078 | #ifdef CONFIG_CGROUPS | 1102 | #ifdef CONFIG_CGROUPS |
1079 | void sock_update_classid(struct sock *sk) | 1103 | void sock_update_classid(struct sock *sk) |
1080 | { | 1104 | { |
1081 | u32 classid = task_cls_classid(current); | 1105 | u32 classid; |
1082 | 1106 | ||
1107 | rcu_read_lock(); /* doing current task, which cannot vanish. */ | ||
1108 | classid = task_cls_classid(current); | ||
1109 | rcu_read_unlock(); | ||
1083 | if (classid && classid != sk->sk_classid) | 1110 | if (classid && classid != sk->sk_classid) |
1084 | sk->sk_classid = classid; | 1111 | sk->sk_classid = classid; |
1085 | } | 1112 | } |
@@ -1148,7 +1175,7 @@ static void __sk_free(struct sock *sk) | |||
1148 | void sk_free(struct sock *sk) | 1175 | void sk_free(struct sock *sk) |
1149 | { | 1176 | { |
1150 | /* | 1177 | /* |
1151 | * We substract one from sk_wmem_alloc and can know if | 1178 | * We subtract one from sk_wmem_alloc and can know if |
1152 | * some packets are still in some tx queue. | 1179 | * some packets are still in some tx queue. |
1153 | * If not null, sock_wfree() will call __sk_free(sk) later | 1180 | * If not null, sock_wfree() will call __sk_free(sk) later |
1154 | */ | 1181 | */ |
@@ -1158,10 +1185,10 @@ void sk_free(struct sock *sk) | |||
1158 | EXPORT_SYMBOL(sk_free); | 1185 | EXPORT_SYMBOL(sk_free); |
1159 | 1186 | ||
1160 | /* | 1187 | /* |
1161 | * Last sock_put should drop referrence to sk->sk_net. It has already | 1188 | * Last sock_put should drop reference to sk->sk_net. It has already |
1162 | * been dropped in sk_change_net. Taking referrence to stopping namespace | 1189 | * been dropped in sk_change_net. Taking reference to stopping namespace |
1163 | * is not an option. | 1190 | * is not an option. |
1164 | * Take referrence to a socket to remove it from hash _alive_ and after that | 1191 | * Take reference to a socket to remove it from hash _alive_ and after that |
1165 | * destroy it in the context of init_net. | 1192 | * destroy it in the context of init_net. |
1166 | */ | 1193 | */ |
1167 | void sk_release_kernel(struct sock *sk) | 1194 | void sk_release_kernel(struct sock *sk) |
@@ -1222,7 +1249,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1222 | sock_reset_flag(newsk, SOCK_DONE); | 1249 | sock_reset_flag(newsk, SOCK_DONE); |
1223 | skb_queue_head_init(&newsk->sk_error_queue); | 1250 | skb_queue_head_init(&newsk->sk_error_queue); |
1224 | 1251 | ||
1225 | filter = newsk->sk_filter; | 1252 | filter = rcu_dereference_protected(newsk->sk_filter, 1); |
1226 | if (filter != NULL) | 1253 | if (filter != NULL) |
1227 | sk_filter_charge(newsk, filter); | 1254 | sk_filter_charge(newsk, filter); |
1228 | 1255 | ||
@@ -1557,6 +1584,8 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, | |||
1557 | EXPORT_SYMBOL(sock_alloc_send_skb); | 1584 | EXPORT_SYMBOL(sock_alloc_send_skb); |
1558 | 1585 | ||
1559 | static void __lock_sock(struct sock *sk) | 1586 | static void __lock_sock(struct sock *sk) |
1587 | __releases(&sk->sk_lock.slock) | ||
1588 | __acquires(&sk->sk_lock.slock) | ||
1560 | { | 1589 | { |
1561 | DEFINE_WAIT(wait); | 1590 | DEFINE_WAIT(wait); |
1562 | 1591 | ||
@@ -1573,6 +1602,8 @@ static void __lock_sock(struct sock *sk) | |||
1573 | } | 1602 | } |
1574 | 1603 | ||
1575 | static void __release_sock(struct sock *sk) | 1604 | static void __release_sock(struct sock *sk) |
1605 | __releases(&sk->sk_lock.slock) | ||
1606 | __acquires(&sk->sk_lock.slock) | ||
1576 | { | 1607 | { |
1577 | struct sk_buff *skb = sk->sk_backlog.head; | 1608 | struct sk_buff *skb = sk->sk_backlog.head; |
1578 | 1609 | ||
@@ -1646,10 +1677,10 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) | |||
1646 | { | 1677 | { |
1647 | struct proto *prot = sk->sk_prot; | 1678 | struct proto *prot = sk->sk_prot; |
1648 | int amt = sk_mem_pages(size); | 1679 | int amt = sk_mem_pages(size); |
1649 | int allocated; | 1680 | long allocated; |
1650 | 1681 | ||
1651 | sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; | 1682 | sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; |
1652 | allocated = atomic_add_return(amt, prot->memory_allocated); | 1683 | allocated = atomic_long_add_return(amt, prot->memory_allocated); |
1653 | 1684 | ||
1654 | /* Under limit. */ | 1685 | /* Under limit. */ |
1655 | if (allocated <= prot->sysctl_mem[0]) { | 1686 | if (allocated <= prot->sysctl_mem[0]) { |
@@ -1707,7 +1738,7 @@ suppress_allocation: | |||
1707 | 1738 | ||
1708 | /* Alas. Undo changes. */ | 1739 | /* Alas. Undo changes. */ |
1709 | sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; | 1740 | sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; |
1710 | atomic_sub(amt, prot->memory_allocated); | 1741 | atomic_long_sub(amt, prot->memory_allocated); |
1711 | return 0; | 1742 | return 0; |
1712 | } | 1743 | } |
1713 | EXPORT_SYMBOL(__sk_mem_schedule); | 1744 | EXPORT_SYMBOL(__sk_mem_schedule); |
@@ -1720,12 +1751,12 @@ void __sk_mem_reclaim(struct sock *sk) | |||
1720 | { | 1751 | { |
1721 | struct proto *prot = sk->sk_prot; | 1752 | struct proto *prot = sk->sk_prot; |
1722 | 1753 | ||
1723 | atomic_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, | 1754 | atomic_long_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, |
1724 | prot->memory_allocated); | 1755 | prot->memory_allocated); |
1725 | sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1; | 1756 | sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1; |
1726 | 1757 | ||
1727 | if (prot->memory_pressure && *prot->memory_pressure && | 1758 | if (prot->memory_pressure && *prot->memory_pressure && |
1728 | (atomic_read(prot->memory_allocated) < prot->sysctl_mem[0])) | 1759 | (atomic_long_read(prot->memory_allocated) < prot->sysctl_mem[0])) |
1729 | *prot->memory_pressure = 0; | 1760 | *prot->memory_pressure = 0; |
1730 | } | 1761 | } |
1731 | EXPORT_SYMBOL(__sk_mem_reclaim); | 1762 | EXPORT_SYMBOL(__sk_mem_reclaim); |
@@ -1877,7 +1908,7 @@ static void sock_def_readable(struct sock *sk, int len) | |||
1877 | rcu_read_lock(); | 1908 | rcu_read_lock(); |
1878 | wq = rcu_dereference(sk->sk_wq); | 1909 | wq = rcu_dereference(sk->sk_wq); |
1879 | if (wq_has_sleeper(wq)) | 1910 | if (wq_has_sleeper(wq)) |
1880 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | | 1911 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI | |
1881 | POLLRDNORM | POLLRDBAND); | 1912 | POLLRDNORM | POLLRDBAND); |
1882 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 1913 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
1883 | rcu_read_unlock(); | 1914 | rcu_read_unlock(); |
@@ -2445,12 +2476,12 @@ static char proto_method_implemented(const void *method) | |||
2445 | 2476 | ||
2446 | static void proto_seq_printf(struct seq_file *seq, struct proto *proto) | 2477 | static void proto_seq_printf(struct seq_file *seq, struct proto *proto) |
2447 | { | 2478 | { |
2448 | seq_printf(seq, "%-9s %4u %6d %6d %-3s %6u %-3s %-10s " | 2479 | seq_printf(seq, "%-9s %4u %6d %6ld %-3s %6u %-3s %-10s " |
2449 | "%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n", | 2480 | "%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n", |
2450 | proto->name, | 2481 | proto->name, |
2451 | proto->obj_size, | 2482 | proto->obj_size, |
2452 | sock_prot_inuse_get(seq_file_net(seq), proto), | 2483 | sock_prot_inuse_get(seq_file_net(seq), proto), |
2453 | proto->memory_allocated != NULL ? atomic_read(proto->memory_allocated) : -1, | 2484 | proto->memory_allocated != NULL ? atomic_long_read(proto->memory_allocated) : -1L, |
2454 | proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI", | 2485 | proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI", |
2455 | proto->max_header, | 2486 | proto->max_header, |
2456 | proto->slab == NULL ? "no" : "yes", | 2487 | proto->slab == NULL ? "no" : "yes", |