diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 54 | 
1 files changed, 51 insertions, 3 deletions
diff --git a/net/socket.c b/net/socket.c index 9a0e720f0859..682969deaed3 100644 --- a/net/socket.c +++ b/net/socket.c @@ -592,10 +592,12 @@ static int sockfs_setattr(struct mnt_idmap *idmap,  	if (!err && (iattr->ia_valid & ATTR_UID)) {  		struct socket *sock = SOCKET_I(d_inode(dentry)); -		if (sock->sk) -			sock->sk->sk_uid = iattr->ia_uid; -		else +		if (sock->sk) { +			/* Paired with READ_ONCE() in sk_uid() */ +			WRITE_ONCE(sock->sk->sk_uid, iattr->ia_uid); +		} else {  			err = -ENOENT; +		}  	}  	return err; @@ -843,6 +845,52 @@ static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,  		 sizeof(ts_pktinfo), &ts_pktinfo);  } +bool skb_has_tx_timestamp(struct sk_buff *skb, const struct sock *sk) +{ +	const struct sock_exterr_skb *serr = SKB_EXT_ERR(skb); +	u32 tsflags = READ_ONCE(sk->sk_tsflags); + +	if (serr->ee.ee_errno != ENOMSG || +	   serr->ee.ee_origin != SO_EE_ORIGIN_TIMESTAMPING) +		return false; + +	/* software time stamp available and wanted */ +	if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && skb->tstamp) +		return true; +	/* hardware time stamps available and wanted */ +	return (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && +		skb_hwtstamps(skb)->hwtstamp; +} + +int skb_get_tx_timestamp(struct sk_buff *skb, struct sock *sk, +			  struct timespec64 *ts) +{ +	u32 tsflags = READ_ONCE(sk->sk_tsflags); +	ktime_t hwtstamp; +	int if_index = 0; + +	if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && +	    ktime_to_timespec64_cond(skb->tstamp, ts)) +		return SOF_TIMESTAMPING_TX_SOFTWARE; + +	if (!(tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) || +	    skb_is_swtx_tstamp(skb, false)) +		return -ENOENT; + +	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV) +		hwtstamp = get_timestamp(sk, skb, &if_index); +	else +		hwtstamp = skb_hwtstamps(skb)->hwtstamp; + +	if (tsflags & SOF_TIMESTAMPING_BIND_PHC) +		hwtstamp = ptp_convert_timestamp(&hwtstamp, +						READ_ONCE(sk->sk_bind_phc)); +	if (!ktime_to_timespec64_cond(hwtstamp, ts)) +		return -ENOENT; + +	return SOF_TIMESTAMPING_TX_HARDWARE; +} +  /*   * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)   */  | 
