Permalink
Browse files

In IPv6 and NetATM, stop SIOCSIFADDR, SIOCSIFBRDADDR, SIOCSIFDSTADDR

and SIOCSIFNETMASK at the socket layer rather than pass them on to the
link layer without validation or credential checks.  [SA-13:12]

Prevent cross-mount hardlinks between different nullfs mounts of the
same underlying filesystem.  [SA-13:13]

Security:	CVE-2013-5691
Security:	FreeBSD-SA-13:12.ifioctl
Security:	CVE-2013-5710
Security:	FreeBSD-SA-13:13.nullfs
Approved by:	re
  • Loading branch information...
1 parent c31d215 commit 290b528387ae508e18bfc170402722f4fcee6a84 @dag-erling dag-erling committed Sep 10, 2013
Showing with 54 additions and 3 deletions.
  1. +1 −1 sys/conf/newvers.sh
  2. +10 −0 sys/fs/nullfs/null_vnops.c
  3. +16 −2 sys/net/if.c
  4. +12 −0 sys/netinet6/in6.c
  5. +15 −0 sys/netnatm/natm.c
View
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="9.2"
-BRANCH="RC3"
+BRANCH="RC3-p1"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi
@@ -858,6 +858,15 @@ null_vptocnp(struct vop_vptocnp_args *ap)
return (error);
}
+static int
+null_link(struct vop_link_args *ap)
+{
+
+ if (ap->a_tdvp->v_mount != ap->a_vp->v_mount)
+ return (EXDEV);
+ return (null_bypass((struct vop_generic_args *)ap));
+}
+
/*
* Global vfs data structures
*/
@@ -871,6 +880,7 @@ struct vop_vector null_vnodeops = {
.vop_getwritemount = null_getwritemount,
.vop_inactive = null_inactive,
.vop_islocked = vop_stdislocked,
+ .vop_link = null_link,
.vop_lock1 = null_lock,
.vop_lookup = null_lookup,
.vop_open = null_open,
View
@@ -2555,11 +2555,23 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
CURVNET_RESTORE();
return (EOPNOTSUPP);
}
+
+ /*
+ * Pass the request on to the socket control method, and if the
+ * latter returns EOPNOTSUPP, directly to the interface.
+ *
+ * Make an exception for the legacy SIOCSIF* requests. Drivers
+ * trust SIOCSIFADDR et al to come from an already privileged
+ * layer, and do not perform any credentials checks or input
+ * validation.
+ */
#ifndef COMPAT_43
error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
data,
ifp, td));
- if (error == EOPNOTSUPP && ifp != NULL && ifp->if_ioctl != NULL)
+ if (error == EOPNOTSUPP && ifp != NULL && ifp->if_ioctl != NULL &&
+ cmd != SIOCSIFADDR && cmd != SIOCSIFBRDADDR &&
+ cmd != SIOCSIFDSTADDR && cmd != SIOCSIFNETMASK)
error = (*ifp->if_ioctl)(ifp, cmd, data);
#else
{
@@ -2603,7 +2615,9 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
data,
ifp, td));
if (error == EOPNOTSUPP && ifp != NULL &&
- ifp->if_ioctl != NULL)
+ ifp->if_ioctl != NULL &&
+ cmd != SIOCSIFADDR && cmd != SIOCSIFBRDADDR &&
+ cmd != SIOCSIFDSTADDR && cmd != SIOCSIFNETMASK)
error = (*ifp->if_ioctl)(ifp, cmd, data);
switch (ocmd) {
View
@@ -422,6 +422,18 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
case SIOCGIFSTAT_ICMP6:
sa6 = &ifr->ifr_addr;
break;
+ case SIOCSIFADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFNETMASK:
+ /*
+ * Although we should pass any non-INET6 ioctl requests
+ * down to driver, we filter some legacy INET requests.
+ * Drivers trust SIOCSIFADDR et al to come from an already
+ * privileged layer, and do not perform any credentials
+ * checks or input validation.
+ */
+ return (EINVAL);
default:
sa6 = NULL;
break;
View
@@ -339,6 +339,21 @@ natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFNETMASK:
+ /*
+ * Although we should pass any non-ATM ioctl requests
+ * down to driver, we filter some legacy INET requests.
+ * Drivers trust SIOCSIFADDR et al to come from an already
+ * privileged layer, and do not perform any credentials
+ * checks or input validation.
+ */
+ return (EINVAL);
+ }
+
if (ifp == NULL || ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
return ((*ifp->if_ioctl)(ifp, cmd, arg));

0 comments on commit 290b528

Please sign in to comment.