Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Apr 2020 12:49:48 +0000 (UTC)
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r360299 - in stable/11/sys: kern net sys
Message-ID:  <202004251249.03PCnmBg063449@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kp
Date: Sat Apr 25 12:49:48 2020
New Revision: 360299
URL: https://svnweb.freebsd.org/changeset/base/360299

Log:
  MFC r360068:
  
  ethersubr: Make the mac address generation more robust
  
  If we create two (vnet) jails and create a bridge interface in each we end up
  with the same mac address on both bridge interfaces.
  These very often conflicts, resulting in same mac address in both jails.
  
  Mitigate this problem by including the jail name in the mac address.

Modified:
  stable/11/sys/kern/kern_jail.c
  stable/11/sys/net/if_ethersubr.c
  stable/11/sys/sys/jail.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/kern/kern_jail.c
==============================================================================
--- stable/11/sys/kern/kern_jail.c	Sat Apr 25 12:49:48 2020	(r360298)
+++ stable/11/sys/kern/kern_jail.c	Sat Apr 25 12:49:48 2020	(r360299)
@@ -2936,6 +2936,15 @@ getcredhostid(struct ucred *cred, unsigned long *hosti
 	mtx_unlock(&cred->cr_prison->pr_mtx);
 }
 
+void
+getjailname(struct ucred *cred, char *name, size_t len)
+{
+
+	mtx_lock(&cred->cr_prison->pr_mtx);
+	strlcpy(name, cred->cr_prison->pr_name, len);
+	mtx_unlock(&cred->cr_prison->pr_mtx);
+}
+
 #ifdef VIMAGE
 /*
  * Determine whether the prison represented by cred owns

Modified: stable/11/sys/net/if_ethersubr.c
==============================================================================
--- stable/11/sys/net/if_ethersubr.c	Sat Apr 25 12:49:48 2020	(r360298)
+++ stable/11/sys/net/if_ethersubr.c	Sat Apr 25 12:49:48 2020	(r360299)
@@ -1377,27 +1377,39 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife,
 
 /*
  * Allocate an address from the FreeBSD Foundation OUI.  This uses a
- * cryptographic hash function on the containing jail's UUID and the interface
- * name to attempt to provide a unique but stable address.  Pseudo-interfaces
- * which require a MAC address should use this function to allocate
- * non-locally-administered addresses.
+ * cryptographic hash function on the containing jail's name, UUID and the
+ * interface name to attempt to provide a unique but stable address.
+ * Pseudo-interfaces which require a MAC address should use this function to
+ * allocate non-locally-administered addresses.
  */
 void
 ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr)
 {
-#define	ETHER_GEN_ADDR_BUFSIZ	HOSTUUIDLEN + IFNAMSIZ + 2
 	SHA1_CTX ctx;
-	char buf[ETHER_GEN_ADDR_BUFSIZ];
+	char *buf;
 	char uuid[HOSTUUIDLEN + 1];
 	uint64_t addr;
 	int i, sz;
 	char digest[SHA1_RESULTLEN];
+	char jailname[MAXHOSTNAMELEN];
 
 	getcredhostuuid(curthread->td_ucred, uuid, sizeof(uuid));
-	sz = snprintf(buf, ETHER_GEN_ADDR_BUFSIZ, "%s-%s", uuid, ifp->if_xname);
+	/* If each (vnet) jail would also have a unique hostuuid this would not
+	 * be necessary. */
+	getjailname(curthread->td_ucred, jailname, sizeof(jailname));
+	sz = asprintf(&buf, M_TEMP, "%s-%s-%s", uuid, if_name(ifp),
+	    jailname);
+	if (sz < 0) {
+		/* Fall back to a random mac address. */
+		arc4rand(hwaddr, sizeof(*hwaddr), 0);
+		hwaddr->octet[0] = 0x02;
+		return;
+	}
+
 	SHA1Init(&ctx);
 	SHA1Update(&ctx, buf, sz);
 	SHA1Final(digest, &ctx);
+	free(buf, M_TEMP);
 
 	addr = ((digest[0] << 16) | (digest[1] << 8) | digest[2]) &
 	    OUI_FREEBSD_GENERATED_MASK;

Modified: stable/11/sys/sys/jail.h
==============================================================================
--- stable/11/sys/sys/jail.h	Sat Apr 25 12:49:48 2020	(r360298)
+++ stable/11/sys/sys/jail.h	Sat Apr 25 12:49:48 2020	(r360299)
@@ -367,6 +367,7 @@ void getcredhostname(struct ucred *, char *, size_t);
 void getcreddomainname(struct ucred *, char *, size_t);
 void getcredhostuuid(struct ucred *, char *, size_t);
 void getcredhostid(struct ucred *, unsigned long *);
+void getjailname(struct ucred *cred, char *name, size_t len);
 void prison0_init(void);
 int prison_allow(struct ucred *, unsigned);
 int prison_check(struct ucred *cred1, struct ucred *cred2);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004251249.03PCnmBg063449>