Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
Re: sysctl(2): push locking down to udp_sysctl()
To:
Vitaliy Makkoveev <mvs@openbsd.org>
Cc:
tech@openbsd.org
Date:
Wed, 4 Dec 2024 23:32:27 +0100

Download raw body.

Thread
On Wed, Dec 04, 2024 at 11:36:24PM +0300, Vitaliy Makkoveev wrote:
> Mostly to deliver protocol statistics lockless. Atomically accessed
> `udpctl_vars' variables are already moved from net lock, sysctl(2)
> related locks are useless for them. Complicated UDPCTL_BADDYNAMIC and
> UDPCTL_ROOTONLY cases were left as is.

OK bluhm@

> Index: sys/netinet/in_proto.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/in_proto.c,v
> diff -u -p -r1.113 in_proto.c
> --- sys/netinet/in_proto.c	22 Aug 2024 10:58:31 -0000	1.113
> +++ sys/netinet/in_proto.c	4 Dec 2024 20:19:32 -0000
> @@ -185,7 +185,8 @@ const struct protosw inetsw[] = {
>    .pr_type	= SOCK_DGRAM,
>    .pr_domain	= &inetdomain,
>    .pr_protocol	= IPPROTO_UDP,
> -  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET,
> +  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET|
> +		      PR_MPSYSCTL,
>    .pr_input	= udp_input,
>    .pr_ctlinput	= udp_ctlinput,
>    .pr_ctloutput	= ip_ctloutput,
> Index: sys/netinet/udp_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
> diff -u -p -r1.327 udp_usrreq.c
> --- sys/netinet/udp_usrreq.c	5 Nov 2024 22:44:20 -0000	1.327
> +++ sys/netinet/udp_usrreq.c	4 Dec 2024 20:19:32 -0000
> @@ -172,6 +172,7 @@ void	udp_sbappend(struct inpcb *, struct
>  	    u_int32_t);
>  int	udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *);
>  void	udp_notify(struct inpcb *, int);
> +int	udp_sysctl_locked(int *, u_int, void *, size_t *, void *, size_t);
>  int	udp_sysctl_udpstat(void *, size_t *, void *);
>  
>  #ifndef	UDB_INITIAL_HASH_SIZE
> @@ -1259,19 +1260,50 @@ int
>  udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
>      size_t newlen)
>  {
> -	int error;
> -
>  	/* All sysctl names at this level are terminal. */
>  	if (namelen != 1)
>  		return (ENOTDIR);
>  
>  	switch (name[0]) {
>  	case UDPCTL_BADDYNAMIC:
> +	case UDPCTL_ROOTONLY: {
> +		size_t savelen = *oldlenp;
> +		int error;
> +
> +		if ((error = sysctl_vslock(oldp, savelen)))
> +			return (error);
> +		error = udp_sysctl_locked(name, namelen, oldp, oldlenp,
> +		    newp, newlen);	
> +		sysctl_vsunlock(oldp, savelen);
> +
> +		return (error);
> +	}
> +	case UDPCTL_STATS:
> +		if (newp != NULL)
> +			return (EPERM);
> +
> +		return (udp_sysctl_udpstat(oldp, oldlenp, newp));
> +
> +	default:
> +		return (sysctl_bounded_arr(udpctl_vars, nitems(udpctl_vars),
> +		    name, namelen, oldp, oldlenp, newp, newlen));
> +	}
> +	/* NOTREACHED */
> +}
> +
> +int
> +udp_sysctl_locked(int *name, u_int namelen, void *oldp, size_t *oldlenp,
> +    void *newp, size_t newlen)
> +{
> +	int error = ENOPROTOOPT;
> +
> +	switch (name[0]) {
> +	case UDPCTL_BADDYNAMIC:
>  		NET_LOCK();
>  		error = sysctl_struct(oldp, oldlenp, newp, newlen,
>  		    baddynamicports.udp, sizeof(baddynamicports.udp));
>  		NET_UNLOCK();
> -		return (error);
> +		break;
>  
>  	case UDPCTL_ROOTONLY:
>  		if (newp && securelevel > 0)
> @@ -1280,20 +1312,10 @@ udp_sysctl(int *name, u_int namelen, voi
>  		error = sysctl_struct(oldp, oldlenp, newp, newlen,
>  		    rootonlyports.udp, sizeof(rootonlyports.udp));
>  		NET_UNLOCK();
> -		return (error);
> -
> -	case UDPCTL_STATS:
> -		if (newp != NULL)
> -			return (EPERM);
> -
> -		return (udp_sysctl_udpstat(oldp, oldlenp, newp));
> -
> -	default:
> -		error = sysctl_bounded_arr(udpctl_vars, nitems(udpctl_vars),
> -		    name, namelen, oldp, oldlenp, newp, newlen);
> -		return (error);
> +		break;
>  	}
> -	/* NOTREACHED */
> +
> +	return (error);
>  }
>  
>  int
> Index: sys/netinet6/in6_proto.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6_proto.c,v
> diff -u -p -r1.119 in6_proto.c
> --- sys/netinet6/in6_proto.c	20 Aug 2024 07:46:27 -0000	1.119
> +++ sys/netinet6/in6_proto.c	4 Dec 2024 20:19:32 -0000
> @@ -136,7 +136,8 @@ const struct protosw inet6sw[] = {
>    .pr_type	= SOCK_DGRAM,
>    .pr_domain	= &inet6domain,
>    .pr_protocol	= IPPROTO_UDP,
> -  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET,
> +  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET|
> +		      PR_MPSYSCTL,
>    .pr_input	= udp_input,
>    .pr_ctlinput	= udp6_ctlinput,
>    .pr_ctloutput	= ip6_ctloutput,