diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/sock.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 6354863b1c68..bbb25be7ddfe 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -631,7 +631,7 @@ set_rcvbuf: | |||
| 631 | 631 | ||
| 632 | case SO_TIMESTAMPING: | 632 | case SO_TIMESTAMPING: |
| 633 | if (val & ~SOF_TIMESTAMPING_MASK) { | 633 | if (val & ~SOF_TIMESTAMPING_MASK) { |
| 634 | ret = EINVAL; | 634 | ret = -EINVAL; |
| 635 | break; | 635 | break; |
| 636 | } | 636 | } |
| 637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, | 637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, |
| @@ -919,13 +919,19 @@ static inline void sock_lock_init(struct sock *sk) | |||
| 919 | af_family_keys + sk->sk_family); | 919 | af_family_keys + sk->sk_family); |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | /* | ||
| 923 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, | ||
| 924 | * even temporarly, because of RCU lookups. sk_node should also be left as is. | ||
| 925 | */ | ||
| 922 | static void sock_copy(struct sock *nsk, const struct sock *osk) | 926 | static void sock_copy(struct sock *nsk, const struct sock *osk) |
| 923 | { | 927 | { |
| 924 | #ifdef CONFIG_SECURITY_NETWORK | 928 | #ifdef CONFIG_SECURITY_NETWORK |
| 925 | void *sptr = nsk->sk_security; | 929 | void *sptr = nsk->sk_security; |
| 926 | #endif | 930 | #endif |
| 927 | 931 | BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) != | |
| 928 | memcpy(nsk, osk, osk->sk_prot->obj_size); | 932 | sizeof(osk->sk_node) + sizeof(osk->sk_refcnt)); |
| 933 | memcpy(&nsk->sk_copy_start, &osk->sk_copy_start, | ||
| 934 | osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start)); | ||
| 929 | #ifdef CONFIG_SECURITY_NETWORK | 935 | #ifdef CONFIG_SECURITY_NETWORK |
| 930 | nsk->sk_security = sptr; | 936 | nsk->sk_security = sptr; |
| 931 | security_sk_clone(osk, nsk); | 937 | security_sk_clone(osk, nsk); |
| @@ -939,8 +945,23 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, | |||
| 939 | struct kmem_cache *slab; | 945 | struct kmem_cache *slab; |
| 940 | 946 | ||
| 941 | slab = prot->slab; | 947 | slab = prot->slab; |
| 942 | if (slab != NULL) | 948 | if (slab != NULL) { |
| 943 | sk = kmem_cache_alloc(slab, priority); | 949 | sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO); |
| 950 | if (!sk) | ||
| 951 | return sk; | ||
| 952 | if (priority & __GFP_ZERO) { | ||
| 953 | /* | ||
| 954 | * caches using SLAB_DESTROY_BY_RCU should let | ||
| 955 | * sk_node.next un-modified. Special care is taken | ||
| 956 | * when initializing object to zero. | ||
| 957 | */ | ||
| 958 | if (offsetof(struct sock, sk_node.next) != 0) | ||
| 959 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
| 960 | memset(&sk->sk_node.pprev, 0, | ||
| 961 | prot->obj_size - offsetof(struct sock, | ||
| 962 | sk_node.pprev)); | ||
| 963 | } | ||
| 964 | } | ||
| 944 | else | 965 | else |
| 945 | sk = kmalloc(prot->obj_size, priority); | 966 | sk = kmalloc(prot->obj_size, priority); |
| 946 | 967 | ||
| @@ -1125,6 +1146,11 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
| 1125 | 1146 | ||
| 1126 | newsk->sk_err = 0; | 1147 | newsk->sk_err = 0; |
| 1127 | newsk->sk_priority = 0; | 1148 | newsk->sk_priority = 0; |
| 1149 | /* | ||
| 1150 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
| 1151 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
| 1152 | */ | ||
| 1153 | smp_wmb(); | ||
| 1128 | atomic_set(&newsk->sk_refcnt, 2); | 1154 | atomic_set(&newsk->sk_refcnt, 2); |
| 1129 | 1155 | ||
| 1130 | /* | 1156 | /* |
| @@ -1840,6 +1866,11 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
| 1840 | 1866 | ||
| 1841 | sk->sk_stamp = ktime_set(-1L, 0); | 1867 | sk->sk_stamp = ktime_set(-1L, 0); |
| 1842 | 1868 | ||
| 1869 | /* | ||
| 1870 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
| 1871 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
| 1872 | */ | ||
| 1873 | smp_wmb(); | ||
| 1843 | atomic_set(&sk->sk_refcnt, 1); | 1874 | atomic_set(&sk->sk_refcnt, 1); |
| 1844 | atomic_set(&sk->sk_wmem_alloc, 1); | 1875 | atomic_set(&sk->sk_wmem_alloc, 1); |
| 1845 | atomic_set(&sk->sk_drops, 0); | 1876 | atomic_set(&sk->sk_drops, 0); |
