diff options
Diffstat (limited to 'net/core/sock.c')
| -rw-r--r-- | net/core/sock.c | 156 | 
1 files changed, 104 insertions, 52 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 0b39e7ae438..026e01f7027 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -145,6 +145,55 @@  static DEFINE_MUTEX(proto_list_mutex);  static LIST_HEAD(proto_list); +/** + * sk_ns_capable - General socket capability test + * @sk: Socket to use a capability on or through + * @user_ns: The user namespace of the capability to use + * @cap: The capability to use + * + * Test to see if the opener of the socket had when the socket was + * created and the current process has the capability @cap in the user + * namespace @user_ns. + */ +bool sk_ns_capable(const struct sock *sk, +		   struct user_namespace *user_ns, int cap) +{ +	return file_ns_capable(sk->sk_socket->file, user_ns, cap) && +		ns_capable(user_ns, cap); +} +EXPORT_SYMBOL(sk_ns_capable); + +/** + * sk_capable - Socket global capability test + * @sk: Socket to use a capability on or through + * @cap: The global capbility to use + * + * Test to see if the opener of the socket had when the socket was + * created and the current process has the capability @cap in all user + * namespaces. + */ +bool sk_capable(const struct sock *sk, int cap) +{ +	return sk_ns_capable(sk, &init_user_ns, cap); +} +EXPORT_SYMBOL(sk_capable); + +/** + * sk_net_capable - Network namespace socket capability test + * @sk: Socket to use a capability on or through + * @cap: The capability to use + * + * Test to see if the opener of the socket had when the socke was created + * and the current process has the capability @cap over the network namespace + * the socket is a member of. + */ +bool sk_net_capable(const struct sock *sk, int cap) +{ +	return sk_ns_capable(sk, sock_net(sk)->user_ns, cap); +} +EXPORT_SYMBOL(sk_net_capable); + +  #ifdef CONFIG_MEMCG_KMEM  int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss)  { @@ -428,7 +477,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)  	spin_unlock_irqrestore(&list->lock, flags);  	if (!sock_flag(sk, SOCK_DEAD)) -		sk->sk_data_ready(sk, skb_len); +		sk->sk_data_ready(sk);  	return 0;  }  EXPORT_SYMBOL(sock_queue_rcv_skb); @@ -475,12 +524,6 @@ discard_and_relse:  }  EXPORT_SYMBOL(sk_receive_skb); -void sk_reset_txq(struct sock *sk) -{ -	sk_tx_queue_clear(sk); -} -EXPORT_SYMBOL(sk_reset_txq); -  struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)  {  	struct dst_entry *dst = __sk_dst_get(sk); @@ -741,7 +784,7 @@ set_rcvbuf:  		break;  	case SO_NO_CHECK: -		sk->sk_no_check = valbool; +		sk->sk_no_check_tx = valbool;  		break;  	case SO_PRIORITY: @@ -888,7 +931,7 @@ set_rcvbuf:  	case SO_PEEK_OFF:  		if (sock->ops->set_peek_off) -			sock->ops->set_peek_off(sk, val); +			ret = sock->ops->set_peek_off(sk, val);  		else  			ret = -EOPNOTSUPP;  		break; @@ -914,6 +957,13 @@ set_rcvbuf:  		}  		break;  #endif + +	case SO_MAX_PACING_RATE: +		sk->sk_max_pacing_rate = val; +		sk->sk_pacing_rate = min(sk->sk_pacing_rate, +					 sk->sk_max_pacing_rate); +		break; +  	default:  		ret = -ENOPROTOOPT;  		break; @@ -924,8 +974,8 @@ set_rcvbuf:  EXPORT_SYMBOL(sock_setsockopt); -void cred_to_ucred(struct pid *pid, const struct cred *cred, -		   struct ucred *ucred) +static void cred_to_ucred(struct pid *pid, const struct cred *cred, +			  struct ucred *ucred)  {  	ucred->pid = pid_vnr(pid);  	ucred->uid = ucred->gid = -1; @@ -936,7 +986,6 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred,  		ucred->gid = from_kgid_munged(current_ns, cred->egid);  	}  } -EXPORT_SYMBOL_GPL(cred_to_ucred);  int sock_getsockopt(struct socket *sock, int level, int optname,  		    char __user *optval, int __user *optlen) @@ -1015,7 +1064,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,  		break;  	case SO_NO_CHECK: -		v.val = sk->sk_no_check; +		v.val = sk->sk_no_check_tx;  		break;  	case SO_PRIORITY: @@ -1167,6 +1216,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,  		v.val = sock_flag(sk, SOCK_FILTER_LOCKED);  		break; +	case SO_BPF_EXTENSIONS: +		v.val = bpf_tell_extensions(); +		break; +  	case SO_SELECT_ERR_QUEUE:  		v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);  		break; @@ -1177,6 +1230,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,  		break;  #endif +	case SO_MAX_PACING_RATE: +		v.val = sk->sk_max_pacing_rate; +		break; +  	default:  		return -ENOPROTOOPT;  	} @@ -1303,19 +1360,7 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)  	module_put(owner);  } -#if IS_ENABLED(CONFIG_NET_CLS_CGROUP) -void sock_update_classid(struct sock *sk) -{ -	u32 classid; - -	classid = task_cls_classid(current); -	if (classid != sk->sk_classid) -		sk->sk_classid = classid; -} -EXPORT_SYMBOL(sock_update_classid); -#endif - -#if IS_ENABLED(CONFIG_NETPRIO_CGROUP) +#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)  void sock_update_netprioidx(struct sock *sk)  {  	if (in_interrupt()) @@ -1661,22 +1706,6 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,  EXPORT_SYMBOL(sock_wmalloc);  /* - * Allocate a skb from the socket's receive buffer. - */ -struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, -			     gfp_t priority) -{ -	if (force || atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf) { -		struct sk_buff *skb = alloc_skb(size, priority); -		if (skb) { -			skb_set_owner_r(skb, sk); -			return skb; -		} -	} -	return NULL; -} - -/*   * Allocate a memory block from the socket's option memory buffer.   */  void *sock_kmalloc(struct sock *sk, int size, gfp_t priority) @@ -1795,7 +1824,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,  			while (order) {  				if (npages >= 1 << order) {  					page = alloc_pages(sk->sk_allocation | -							   __GFP_COMP | __GFP_NOWARN, +							   __GFP_COMP | +							   __GFP_NOWARN | +							   __GFP_NORETRY,  							   order);  					if (page)  						goto fill_page; @@ -1836,7 +1867,17 @@ EXPORT_SYMBOL(sock_alloc_send_skb);  /* On 32bit arches, an skb frag is limited to 2^15 */  #define SKB_FRAG_PAGE_ORDER	get_order(32768) -bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag) +/** + * skb_page_frag_refill - check that a page_frag contains enough room + * @sz: minimum size of the fragment we want to get + * @pfrag: pointer to page_frag + * @prio: priority for memory allocation + * + * Note: While this allocator tries to use high order pages, there is + * no guarantee that allocations succeed. Therefore, @sz MUST be + * less or equal than PAGE_SIZE. + */ +bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)  {  	int order; @@ -1845,19 +1886,17 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag)  			pfrag->offset = 0;  			return true;  		} -		if (pfrag->offset < pfrag->size) +		if (pfrag->offset + sz <= pfrag->size)  			return true;  		put_page(pfrag->page);  	} -	/* We restrict high order allocations to users that can afford to wait */ -	order = (sk->sk_allocation & __GFP_WAIT) ? SKB_FRAG_PAGE_ORDER : 0; - +	order = SKB_FRAG_PAGE_ORDER;  	do { -		gfp_t gfp = sk->sk_allocation; +		gfp_t gfp = prio;  		if (order) -			gfp |= __GFP_COMP | __GFP_NOWARN; +			gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY;  		pfrag->page = alloc_pages(gfp, order);  		if (likely(pfrag->page)) {  			pfrag->offset = 0; @@ -1866,6 +1905,15 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag)  		}  	} while (--order >= 0); +	return false; +} +EXPORT_SYMBOL(skb_page_frag_refill); + +bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag) +{ +	if (likely(skb_page_frag_refill(32U, pfrag, sk->sk_allocation))) +		return true; +  	sk_enter_memory_pressure(sk);  	sk_stream_moderate_sndbuf(sk);  	return false; @@ -2197,7 +2245,7 @@ static void sock_def_error_report(struct sock *sk)  	rcu_read_unlock();  } -static void sock_def_readable(struct sock *sk, int len) +static void sock_def_readable(struct sock *sk)  {  	struct socket_wq *wq; @@ -2319,6 +2367,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)  	sk->sk_ll_usec		=	sysctl_net_busy_read;  #endif +	sk->sk_max_pacing_rate = ~0U;  	sk->sk_pacing_rate = ~0U;  	/*  	 * Before updating sk_refcnt, we must commit prior changes to memory @@ -2357,10 +2406,13 @@ void release_sock(struct sock *sk)  	if (sk->sk_backlog.tail)  		__release_sock(sk); +	/* Warning : release_cb() might need to release sk ownership, +	 * ie call sock_release_ownership(sk) before us. +	 */  	if (sk->sk_prot->release_cb)  		sk->sk_prot->release_cb(sk); -	sk->sk_lock.owned = 0; +	sock_release_ownership(sk);  	if (waitqueue_active(&sk->sk_lock.wq))  		wake_up(&sk->sk_lock.wq);  	spin_unlock_bh(&sk->sk_lock.slock);  | 
