Date: Mon, 11 Oct 2004 16:31:57 -0400 (EDT) From: Robert Watson <rwatson@freebsd.org> To: swp@swp.pp.ru Cc: csjp@freebsd.org Subject: Re: IP options broken for raw sockets on cred downgrade (was: Re: why required root privileges to set multicast options now?) Message-ID: <Pine.NEB.3.96L.1041011163050.31040a-100000@fledge.watson.org> In-Reply-To: <Pine.NEB.3.96L.1041011151504.31040X-100000@fledge.watson.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 11 Oct 2004, Robert Watson wrote: > > This appears to have been introduced as a result of changes to permit > > root to bind raw sockets in jail. In particular, the likely control > > flow path to get the above errors was to perform setsockopt() on a UDP > > socket, which probaly works its way down to in_control() to > > ip_ctloutput(). This would also explain why sdr stopped working for me > > a little while ago (I figured it was a bad package build). I've CC'd > > Christian as he might have some insight into how to clean this up. > > The bug is now neatly illustrated by the ipsockopt regression test: ... > The socket option operation works fine except in the case where a raw > socket was created as root, and then privilege was downgraded to the > normal user, at which point the process tries a socket option operation > (apparently of any sort, not just multicast). I'm surprised more things > haven't broken, such as aspects of ping(8). Maybe they have and nobody > has noticed :-). Could you try the attached patch? Thanks, Robert N M Watson FreeBSD Core Team, TrustedBSD Projects robert@fledge.watson.org Principal Research Scientist, McAfee Research Index: raw_ip.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.144 diff -u -r1.144 raw_ip.c --- raw_ip.c 5 Sep 2004 02:34:12 -0000 1.144 +++ raw_ip.c 11 Oct 2004 20:08:25 -0000 @@ -326,15 +326,14 @@ /* * Raw IP socket option processing. * - * Note that access to all of the IP administrative functions here is - * implicitly protected by suser() as gaining access to a raw socket - * requires either that the thread pass a suser() check, or that it be - * passed a raw socket by another thread that has passed a suser() check. - * If FreeBSD moves to a more fine-grained access control mechanism, - * additional checks will need to be placed here if the raw IP attachment - * check is not equivilent the the check required for these - * administrative operations; in some cases, these checks are already - * present. + * NOTE: Regarding access control. Raw sockets may only be created by + * privileged processes; however, as a result of jailed processes and the + * ability for processes to downgrade privilege yet retain a reference to the + * raw socket. As such, explicit access control is required here, or when + * unimplemented requests are passed to ip_ctloutput(), are required there. + * + * When adding new socket options here, make sure to add access control if + * necessary. */ int rip_ctloutput(struct socket *so, struct sockopt *sopt) @@ -345,18 +344,7 @@ if (sopt->sopt_level != IPPROTO_IP) return (EINVAL); - /* - * Even though super-user is required to create a raw socket, the - * calling cred could be prison root. If so we want to restrict the - * access to IP_HDRINCL only. - */ - if (sopt->sopt_name != IP_HDRINCL) { - error = suser(curthread); - if (error != 0) - return (error); - } error = 0; - switch (sopt->sopt_dir) { case SOPT_GET: switch (sopt->sopt_name) { @@ -369,6 +357,9 @@ case IP_FW_GET: case IP_FW_TABLE_GETSIZE: case IP_FW_TABLE_LIST: + error = suser(curthread); + if (error != 0) + return (error); if (ip_fw_ctl_ptr != NULL) error = ip_fw_ctl_ptr(sopt); else @@ -376,6 +367,9 @@ break; case IP_DUMMYNET_GET: + error = suser(curthread); + if (error != 0) + return (error); if (ip_dn_ctl_ptr != NULL) error = ip_dn_ctl_ptr(sopt); else @@ -394,6 +388,9 @@ case MRT_API_CONFIG: case MRT_ADD_BW_UPCALL: case MRT_DEL_BW_UPCALL: + error = suser(curthread); + if (error != 0) + return (error); error = ip_mrouter_get ? ip_mrouter_get(so, sopt) : EOPNOTSUPP; break; @@ -425,6 +422,9 @@ case IP_FW_TABLE_ADD: case IP_FW_TABLE_DEL: case IP_FW_TABLE_FLUSH: + error = suser(curthread); + if (error != 0) + return (error); if (ip_fw_ctl_ptr != NULL) error = ip_fw_ctl_ptr(sopt); else @@ -434,6 +434,9 @@ case IP_DUMMYNET_CONFIGURE: case IP_DUMMYNET_DEL: case IP_DUMMYNET_FLUSH: + error = suser(curthread); + if (error != 0) + return (error); if (ip_dn_ctl_ptr != NULL) error = ip_dn_ctl_ptr(sopt); else @@ -441,15 +444,24 @@ break ; case IP_RSVP_ON: + error = suser(curthread); + if (error != 0) + return (error); error = ip_rsvp_init(so); break; case IP_RSVP_OFF: + error = suser(curthread); + if (error != 0) + return (error); error = ip_rsvp_done(); break; case IP_RSVP_VIF_ON: case IP_RSVP_VIF_OFF: + error = suser(curthread); + if (error != 0) + return (error); error = ip_rsvp_vif ? ip_rsvp_vif(so, sopt) : EINVAL; break; @@ -466,6 +478,9 @@ case MRT_API_CONFIG: case MRT_ADD_BW_UPCALL: case MRT_DEL_BW_UPCALL: + error = suser(curthread); + if (error != 0) + return (error); error = ip_mrouter_set ? ip_mrouter_set(so, sopt) : EOPNOTSUPP; break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96L.1041011163050.31040a-100000>