diff options
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index d57b0cc995a0..545fac19a711 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1992,6 +1992,19 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | |||
1992 | } | 1992 | } |
1993 | EXPORT_SYMBOL(skb_set_owner_w); | 1993 | EXPORT_SYMBOL(skb_set_owner_w); |
1994 | 1994 | ||
1995 | static bool can_skb_orphan_partial(const struct sk_buff *skb) | ||
1996 | { | ||
1997 | #ifdef CONFIG_TLS_DEVICE | ||
1998 | /* Drivers depend on in-order delivery for crypto offload, | ||
1999 | * partial orphan breaks out-of-order-OK logic. | ||
2000 | */ | ||
2001 | if (skb->decrypted) | ||
2002 | return false; | ||
2003 | #endif | ||
2004 | return (skb->destructor == sock_wfree || | ||
2005 | (IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree)); | ||
2006 | } | ||
2007 | |||
1995 | /* This helper is used by netem, as it can hold packets in its | 2008 | /* This helper is used by netem, as it can hold packets in its |
1996 | * delay queue. We want to allow the owner socket to send more | 2009 | * delay queue. We want to allow the owner socket to send more |
1997 | * packets, as if they were already TX completed by a typical driver. | 2010 | * packets, as if they were already TX completed by a typical driver. |
@@ -2003,11 +2016,7 @@ void skb_orphan_partial(struct sk_buff *skb) | |||
2003 | if (skb_is_tcp_pure_ack(skb)) | 2016 | if (skb_is_tcp_pure_ack(skb)) |
2004 | return; | 2017 | return; |
2005 | 2018 | ||
2006 | if (skb->destructor == sock_wfree | 2019 | if (can_skb_orphan_partial(skb)) { |
2007 | #ifdef CONFIG_INET | ||
2008 | || skb->destructor == tcp_wfree | ||
2009 | #endif | ||
2010 | ) { | ||
2011 | struct sock *sk = skb->sk; | 2020 | struct sock *sk = skb->sk; |
2012 | 2021 | ||
2013 | if (refcount_inc_not_zero(&sk->sk_refcnt)) { | 2022 | if (refcount_inc_not_zero(&sk->sk_refcnt)) { |
@@ -3278,16 +3287,17 @@ static __init int net_inuse_init(void) | |||
3278 | 3287 | ||
3279 | core_initcall(net_inuse_init); | 3288 | core_initcall(net_inuse_init); |
3280 | 3289 | ||
3281 | static void assign_proto_idx(struct proto *prot) | 3290 | static int assign_proto_idx(struct proto *prot) |
3282 | { | 3291 | { |
3283 | prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR); | 3292 | prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR); |
3284 | 3293 | ||
3285 | if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) { | 3294 | if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) { |
3286 | pr_err("PROTO_INUSE_NR exhausted\n"); | 3295 | pr_err("PROTO_INUSE_NR exhausted\n"); |
3287 | return; | 3296 | return -ENOSPC; |
3288 | } | 3297 | } |
3289 | 3298 | ||
3290 | set_bit(prot->inuse_idx, proto_inuse_idx); | 3299 | set_bit(prot->inuse_idx, proto_inuse_idx); |
3300 | return 0; | ||
3291 | } | 3301 | } |
3292 | 3302 | ||
3293 | static void release_proto_idx(struct proto *prot) | 3303 | static void release_proto_idx(struct proto *prot) |
@@ -3296,8 +3306,9 @@ static void release_proto_idx(struct proto *prot) | |||
3296 | clear_bit(prot->inuse_idx, proto_inuse_idx); | 3306 | clear_bit(prot->inuse_idx, proto_inuse_idx); |
3297 | } | 3307 | } |
3298 | #else | 3308 | #else |
3299 | static inline void assign_proto_idx(struct proto *prot) | 3309 | static inline int assign_proto_idx(struct proto *prot) |
3300 | { | 3310 | { |
3311 | return 0; | ||
3301 | } | 3312 | } |
3302 | 3313 | ||
3303 | static inline void release_proto_idx(struct proto *prot) | 3314 | static inline void release_proto_idx(struct proto *prot) |
@@ -3346,6 +3357,8 @@ static int req_prot_init(const struct proto *prot) | |||
3346 | 3357 | ||
3347 | int proto_register(struct proto *prot, int alloc_slab) | 3358 | int proto_register(struct proto *prot, int alloc_slab) |
3348 | { | 3359 | { |
3360 | int ret = -ENOBUFS; | ||
3361 | |||
3349 | if (alloc_slab) { | 3362 | if (alloc_slab) { |
3350 | prot->slab = kmem_cache_create_usercopy(prot->name, | 3363 | prot->slab = kmem_cache_create_usercopy(prot->name, |
3351 | prot->obj_size, 0, | 3364 | prot->obj_size, 0, |
@@ -3382,20 +3395,27 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
3382 | } | 3395 | } |
3383 | 3396 | ||
3384 | mutex_lock(&proto_list_mutex); | 3397 | mutex_lock(&proto_list_mutex); |
3398 | ret = assign_proto_idx(prot); | ||
3399 | if (ret) { | ||
3400 | mutex_unlock(&proto_list_mutex); | ||
3401 | goto out_free_timewait_sock_slab_name; | ||
3402 | } | ||
3385 | list_add(&prot->node, &proto_list); | 3403 | list_add(&prot->node, &proto_list); |
3386 | assign_proto_idx(prot); | ||
3387 | mutex_unlock(&proto_list_mutex); | 3404 | mutex_unlock(&proto_list_mutex); |
3388 | return 0; | 3405 | return ret; |
3389 | 3406 | ||
3390 | out_free_timewait_sock_slab_name: | 3407 | out_free_timewait_sock_slab_name: |
3391 | kfree(prot->twsk_prot->twsk_slab_name); | 3408 | if (alloc_slab && prot->twsk_prot) |
3409 | kfree(prot->twsk_prot->twsk_slab_name); | ||
3392 | out_free_request_sock_slab: | 3410 | out_free_request_sock_slab: |
3393 | req_prot_cleanup(prot->rsk_prot); | 3411 | if (alloc_slab) { |
3412 | req_prot_cleanup(prot->rsk_prot); | ||
3394 | 3413 | ||
3395 | kmem_cache_destroy(prot->slab); | 3414 | kmem_cache_destroy(prot->slab); |
3396 | prot->slab = NULL; | 3415 | prot->slab = NULL; |
3416 | } | ||
3397 | out: | 3417 | out: |
3398 | return -ENOBUFS; | 3418 | return ret; |
3399 | } | 3419 | } |
3400 | EXPORT_SYMBOL(proto_register); | 3420 | EXPORT_SYMBOL(proto_register); |
3401 | 3421 | ||