Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
Re: tcp, sysctl: unlock TCPCTL_ROOTONLY and TCPCTL_BADDYNAMIC
To:
Vitaliy Makkoveev <mvs@openbsd.org>
Cc:
tech@openbsd.org
Date:
Mon, 12 May 2025 21:36:17 +0200

Download raw body.

Thread
On Sun, May 11, 2025 at 01:15:08PM +0300, Vitaliy Makkoveev wrote:
> The copy-paste from udp_sysctl(). It is not yet clean, is it reasonable
> to combine this code with udp.

One might consider adding a in_pcbsysctl() function.  But I think
complexity is not worth it.  Just copy the code from udp to tcp.

> Index: sys/netinet/tcp_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
> retrieving revision 1.245
> diff -u -p -r1.245 tcp_usrreq.c
> --- sys/netinet/tcp_usrreq.c	10 Mar 2025 15:11:46 -0000	1.245
> +++ sys/netinet/tcp_usrreq.c	12 May 2025 18:34:34 -0000
> @@ -1419,22 +1419,40 @@ tcp_sysctl(int *name, u_int namelen, voi
>  		return (ENOTDIR);
>  
>  	switch (name[0]) {
> -	case TCPCTL_BADDYNAMIC:
> -		NET_LOCK();
> -		error = sysctl_struct(oldp, oldlenp, newp, newlen,
> -		    baddynamicports.tcp, sizeof(baddynamicports.tcp));
> -		NET_UNLOCK();
> -		return (error);
> -
>  	case TCPCTL_ROOTONLY:
> -		if (newp && securelevel > 0)
> +		if (newp && (int)atomic_load_int(&securelevel) > 0)
>  			return (EPERM);
> -		NET_LOCK();
> +		/* FALLTHROUGH */
> +	case TCPCTL_BADDYNAMIC: {
> +		struct baddynamicports *ports = (name[0] == TCPCTL_ROOTONLY ?
> +		    &rootonlyports : &baddynamicports);
> +		const size_t bufitems = DP_MAPSIZE;
> +		const size_t buflen = bufitems * sizeof(uint32_t);
> +		size_t i;
> +		uint32_t *buf;
> +		int error;
> +
> +		buf = malloc(buflen, M_SYSCTL, M_WAITOK | M_ZERO);
> +
> +		NET_LOCK_SHARED();
> +		for (i = 0; i < bufitems; ++i)
> +			buf[i] = ports->tcp[i];
> +		NET_UNLOCK_SHARED();
> +
>  		error = sysctl_struct(oldp, oldlenp, newp, newlen,
> -		    rootonlyports.tcp, sizeof(rootonlyports.tcp));
> -		NET_UNLOCK();
> -		return (error);
> +		    buf, buflen);
> +
> +		if (error == 0 && newp) {
> +			NET_LOCK();
> +			for (i = 0; i < bufitems; ++i)
> +				ports->tcp[i] = buf[i];
> +			NET_UNLOCK();
> +		}
>  
> +		free(buf, M_SYSCTL, buflen);
> +
> +		return (error);
> +	}
>  	case TCPCTL_IDENT:
>  		return tcp_ident(oldp, oldlenp, newp, newlen, 0);
>