All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4.4 0/5] CVE fixes for stable 4.4
@ 2016-10-26 15:00 Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 1/5] brcmfmac: avoid potential stack overflow in brcmf_cfg80211_start_ap() Juerg Haefliger
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Juerg Haefliger @ 2016-10-26 15:00 UTC (permalink / raw)
  To: stable, gregkh

This series fixes the following CVEs:
  1/5: CVE-2016-8658
  2/5: CVE-2016-7097
  4/5: CVE-2016-8666

3-5 is a patch series that also fixes a performance issue with GRO
encapsulation.


Arend Van Spriel (1):
  brcmfmac: avoid potential stack overflow in brcmf_cfg80211_start_ap()

Jan Kara (1):
  posix_acl: Clear SGID bit when setting file permissions

Jesse Gross (3):
  ipip: Properly mark ipip GRO packets as encapsulated.
  tunnels: Don't apply GRO to multiple layers of encapsulation.
  tunnels: Remove encapsulation offloads on decap.

 drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c |  2 +-
 fs/9p/acl.c                                        | 40 +++++++++-------------
 fs/btrfs/acl.c                                     |  6 ++--
 fs/ceph/acl.c                                      |  6 ++--
 fs/ext2/acl.c                                      | 12 +++----
 fs/ext4/acl.c                                      | 12 +++----
 fs/f2fs/acl.c                                      |  6 ++--
 fs/gfs2/acl.c                                      | 12 ++-----
 fs/hfsplus/posix_acl.c                             |  4 +--
 fs/jffs2/acl.c                                     |  9 +++--
 fs/jfs/acl.c                                       |  6 ++--
 fs/ocfs2/acl.c                                     | 10 +++---
 fs/posix_acl.c                                     | 31 +++++++++++++++++
 fs/reiserfs/xattr_acl.c                            |  8 ++---
 fs/xfs/xfs_acl.c                                   | 13 +++----
 include/linux/netdevice.h                          |  4 +--
 include/linux/posix_acl.h                          |  1 +
 include/net/ip_tunnels.h                           | 16 +++++++++
 net/core/dev.c                                     |  2 +-
 net/ipv4/af_inet.c                                 | 24 +++++++++++--
 net/ipv4/fou.c                                     | 13 +++++--
 net/ipv4/gre_offload.c                             |  5 +++
 net/ipv4/ip_tunnel_core.c                          |  3 +-
 net/ipv4/udp_offload.c                             |  6 ++--
 net/ipv6/ip6_offload.c                             | 15 +++++++-
 net/ipv6/sit.c                                     |  5 +--
 26 files changed, 164 insertions(+), 107 deletions(-)

-- 
2.9.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4.4 1/5] brcmfmac: avoid potential stack overflow in brcmf_cfg80211_start_ap()
  2016-10-26 15:00 [PATCH 4.4 0/5] CVE fixes for stable 4.4 Juerg Haefliger
@ 2016-10-26 15:00 ` Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 2/5] posix_acl: Clear SGID bit when setting file permissions Juerg Haefliger
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Juerg Haefliger @ 2016-10-26 15:00 UTC (permalink / raw)
  To: stable, gregkh

From: Arend Van Spriel <arend.vanspriel@broadcom.com>

commit ded89912156b1a47d940a0c954c43afbabd0c42c upstream

User-space can choose to omit NL80211_ATTR_SSID and only provide raw
IE TLV data. When doing so it can provide SSID IE with length exceeding
the allowed size. The driver further processes this IE copying it
into a local variable without checking the length. Hence stack can be
corrupted and used as exploit.

Cc: stable@vger.kernel.org # v4.4, v4.1
Reported-by: Daxing Guo <freener.gdx@gmail.com>
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Juerg Haefliger <juerg.haefliger@hpe.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
index 71493d2af912..70a6985334d5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
@@ -4102,7 +4102,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
 				(u8 *)&settings->beacon.head[ie_offset],
 				settings->beacon.head_len - ie_offset,
 				WLAN_EID_SSID);
-		if (!ssid_ie)
+		if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN)
 			return -EINVAL;
 
 		memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4.4 2/5] posix_acl: Clear SGID bit when setting file permissions
  2016-10-26 15:00 [PATCH 4.4 0/5] CVE fixes for stable 4.4 Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 1/5] brcmfmac: avoid potential stack overflow in brcmf_cfg80211_start_ap() Juerg Haefliger
@ 2016-10-26 15:00 ` Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 3/5] ipip: Properly mark ipip GRO packets as encapsulated Juerg Haefliger
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Juerg Haefliger @ 2016-10-26 15:00 UTC (permalink / raw)
  To: stable, gregkh

From: Jan Kara <jack@suse.cz>

commit 073931017b49d9458aa351605b43a7e34598caef upstream.

When file permissions are modified via chmod(2) and the user is not in
the owning group or capable of CAP_FSETID, the setgid bit is cleared in
inode_change_ok().  Setting a POSIX ACL via setxattr(2) sets the file
permissions as well as the new ACL, but doesn't clear the setgid bit in
a similar way; this allows to bypass the check in chmod(2).  Fix that.

References: CVE-2016-7097
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Juerg Haefliger <juerg.haefliger@hpe.com>
---
 fs/9p/acl.c               | 40 +++++++++++++++++-----------------------
 fs/btrfs/acl.c            |  6 ++----
 fs/ceph/acl.c             |  6 ++----
 fs/ext2/acl.c             | 12 ++++--------
 fs/ext4/acl.c             | 12 ++++--------
 fs/f2fs/acl.c             |  6 ++----
 fs/gfs2/acl.c             | 12 +++---------
 fs/hfsplus/posix_acl.c    |  4 ++--
 fs/jffs2/acl.c            |  9 ++++-----
 fs/jfs/acl.c              |  6 ++----
 fs/ocfs2/acl.c            | 10 ++++------
 fs/posix_acl.c            | 31 +++++++++++++++++++++++++++++++
 fs/reiserfs/xattr_acl.c   |  8 ++------
 fs/xfs/xfs_acl.c          | 13 ++++---------
 include/linux/posix_acl.h |  1 +
 15 files changed, 84 insertions(+), 92 deletions(-)

diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index a7e28890f5ef..929b618da43b 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -282,32 +282,26 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
 	switch (handler->flags) {
 	case ACL_TYPE_ACCESS:
 		if (acl) {
-			umode_t mode = inode->i_mode;
-			retval = posix_acl_equiv_mode(acl, &mode);
-			if (retval < 0)
+			struct iattr iattr;
+
+			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
+			if (retval)
 				goto err_out;
-			else {
-				struct iattr iattr;
-				if (retval == 0) {
-					/*
-					 * ACL can be represented
-					 * by the mode bits. So don't
-					 * update ACL.
-					 */
-					acl = NULL;
-					value = NULL;
-					size = 0;
-				}
-				/* Updte the mode bits */
-				iattr.ia_mode = ((mode & S_IALLUGO) |
-						 (inode->i_mode & ~S_IALLUGO));
-				iattr.ia_valid = ATTR_MODE;
-				/* FIXME should we update ctime ?
-				 * What is the following setxattr update the
-				 * mode ?
+			if (!acl) {
+				/*
+				 * ACL can be represented
+				 * by the mode bits. So don't
+				 * update ACL.
 				 */
-				v9fs_vfs_setattr_dotl(dentry, &iattr);
+				value = NULL;
+				size = 0;
 			}
+			iattr.ia_valid = ATTR_MODE;
+			/* FIXME should we update ctime ?
+			 * What is the following setxattr update the
+			 * mode ?
+			 */
+			v9fs_vfs_setattr_dotl(dentry, &iattr);
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 9a0124a95851..fb3e64d37cb4 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -83,11 +83,9 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			ret = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (ret < 0)
+			ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (ret)
 				return ret;
-			if (ret == 0)
-				acl = NULL;
 		}
 		ret = 0;
 		break;
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 8f84646f10e9..4d8caeb94a11 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -94,11 +94,9 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			ret = posix_acl_equiv_mode(acl, &new_mode);
-			if (ret < 0)
+			ret = posix_acl_update_mode(inode, &new_mode, &acl);
+			if (ret)
 				goto out;
-			if (ret == 0)
-				acl = NULL;
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 27695e6f4e46..d6aeb84e90b6 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -193,15 +193,11 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 		case ACL_TYPE_ACCESS:
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
 			if (acl) {
-				error = posix_acl_equiv_mode(acl, &inode->i_mode);
-				if (error < 0)
+				error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+				if (error)
 					return error;
-				else {
-					inode->i_ctime = CURRENT_TIME_SEC;
-					mark_inode_dirty(inode);
-					if (error == 0)
-						acl = NULL;
-				}
+				inode->i_ctime = CURRENT_TIME_SEC;
+				mark_inode_dirty(inode);
 			}
 			break;
 
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 69b1e73026a5..c3fe1e323951 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -196,15 +196,11 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type,
 	case ACL_TYPE_ACCESS:
 		name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
 		if (acl) {
-			error = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (error < 0)
+			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (error)
 				return error;
-			else {
-				inode->i_ctime = ext4_current_time(inode);
-				ext4_mark_inode_dirty(handle, inode);
-				if (error == 0)
-					acl = NULL;
-			}
+			inode->i_ctime = ext4_current_time(inode);
+			ext4_mark_inode_dirty(handle, inode);
 		}
 		break;
 
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index c8f25f7241f0..e9a8d676c6bc 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -214,12 +214,10 @@ static int __f2fs_set_acl(struct inode *inode, int type,
 	case ACL_TYPE_ACCESS:
 		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
 		if (acl) {
-			error = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (error < 0)
+			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (error)
 				return error;
 			set_acl_inode(fi, inode->i_mode);
-			if (error == 0)
-				acl = NULL;
 		}
 		break;
 
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 1be3b061c05c..ff0ac96a8e7b 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -79,17 +79,11 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 	if (type == ACL_TYPE_ACCESS) {
 		umode_t mode = inode->i_mode;
 
-		error = posix_acl_equiv_mode(acl, &mode);
-		if (error < 0)
+		error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+		if (error)
 			return error;
-
-		if (error == 0)
-			acl = NULL;
-
-		if (mode != inode->i_mode) {
-			inode->i_mode = mode;
+		if (mode != inode->i_mode)
 			mark_inode_dirty(inode);
-		}
 	}
 
 	if (acl) {
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
index df0c9af68d05..71b3087b7e32 100644
--- a/fs/hfsplus/posix_acl.c
+++ b/fs/hfsplus/posix_acl.c
@@ -68,8 +68,8 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
 	case ACL_TYPE_ACCESS:
 		xattr_name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			err = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (err < 0)
+			err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (err)
 				return err;
 		}
 		err = 0;
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 2f7a3c090489..f9f86f87d32b 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -235,9 +235,10 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 	case ACL_TYPE_ACCESS:
 		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
 		if (acl) {
-			umode_t mode = inode->i_mode;
-			rc = posix_acl_equiv_mode(acl, &mode);
-			if (rc < 0)
+			umode_t mode;
+
+			rc = posix_acl_update_mode(inode, &mode, &acl);
+			if (rc)
 				return rc;
 			if (inode->i_mode != mode) {
 				struct iattr attr;
@@ -249,8 +250,6 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 				if (rc < 0)
 					return rc;
 			}
-			if (rc == 0)
-				acl = NULL;
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 0c8ca830b113..9fad9f4fe883 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -84,13 +84,11 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
 	case ACL_TYPE_ACCESS:
 		ea_name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			rc = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (rc < 0)
+			rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (rc)
 				return rc;
 			inode->i_ctime = CURRENT_TIME;
 			mark_inode_dirty(inode);
-			if (rc == 0)
-				acl = NULL;
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 2162434728c0..164307b99405 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -241,13 +241,11 @@ int ocfs2_set_acl(handle_t *handle,
 	case ACL_TYPE_ACCESS:
 		name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
 		if (acl) {
-			umode_t mode = inode->i_mode;
-			ret = posix_acl_equiv_mode(acl, &mode);
-			if (ret < 0)
-				return ret;
+			umode_t mode;
 
-			if (ret == 0)
-				acl = NULL;
+			ret = posix_acl_update_mode(inode, &mode, &acl);
+			if (ret)
+				return ret;
 
 			ret = ocfs2_acl_set_mode(inode, di_bh,
 						 handle, mode);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 34bd1bd354e6..a60d3cc5b55d 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -592,6 +592,37 @@ no_mem:
 }
 EXPORT_SYMBOL_GPL(posix_acl_create);
 
+/**
+ * posix_acl_update_mode  -  update mode in set_acl
+ *
+ * Update the file mode when setting an ACL: compute the new file permission
+ * bits based on the ACL.  In addition, if the ACL is equivalent to the new
+ * file mode, set *acl to NULL to indicate that no ACL should be set.
+ *
+ * As with chmod, clear the setgit bit if the caller is not in the owning group
+ * or capable of CAP_FSETID (see inode_change_ok).
+ *
+ * Called from set_acl inode operations.
+ */
+int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
+			  struct posix_acl **acl)
+{
+	umode_t mode = inode->i_mode;
+	int error;
+
+	error = posix_acl_equiv_mode(*acl, &mode);
+	if (error < 0)
+		return error;
+	if (error == 0)
+		*acl = NULL;
+	if (!in_group_p(inode->i_gid) &&
+	    !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+		mode &= ~S_ISGID;
+	*mode_p = mode;
+	return 0;
+}
+EXPORT_SYMBOL(posix_acl_update_mode);
+
 /*
  * Fix up the uids and gids in posix acl extended attributes in place.
  */
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 4b34b9dc03dd..9b1824f35501 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -246,13 +246,9 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
 	case ACL_TYPE_ACCESS:
 		name = POSIX_ACL_XATTR_ACCESS;
 		if (acl) {
-			error = posix_acl_equiv_mode(acl, &inode->i_mode);
-			if (error < 0)
+			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+			if (error)
 				return error;
-			else {
-				if (error == 0)
-					acl = NULL;
-			}
 		}
 		break;
 	case ACL_TYPE_DEFAULT:
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 6bb470fbb8e8..c5101a3295d8 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -288,16 +288,11 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 		return error;
 
 	if (type == ACL_TYPE_ACCESS) {
-		umode_t mode = inode->i_mode;
-		error = posix_acl_equiv_mode(acl, &mode);
-
-		if (error <= 0) {
-			acl = NULL;
-
-			if (error < 0)
-				return error;
-		}
+		umode_t mode;
 
+		error = posix_acl_update_mode(inode, &mode, &acl);
+		if (error)
+			return error;
 		error = xfs_set_mode(inode, mode);
 		if (error)
 			return error;
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 3e96a6a76103..d1a8ad7e5ae4 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -95,6 +95,7 @@ extern int set_posix_acl(struct inode *, int, struct posix_acl *);
 extern int posix_acl_chmod(struct inode *, umode_t);
 extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
 		struct posix_acl **);
+extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **);
 
 extern int simple_set_acl(struct inode *, struct posix_acl *, int);
 extern int simple_acl_create(struct inode *, struct inode *);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4.4 3/5] ipip: Properly mark ipip GRO packets as encapsulated.
  2016-10-26 15:00 [PATCH 4.4 0/5] CVE fixes for stable 4.4 Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 1/5] brcmfmac: avoid potential stack overflow in brcmf_cfg80211_start_ap() Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 2/5] posix_acl: Clear SGID bit when setting file permissions Juerg Haefliger
@ 2016-10-26 15:00 ` Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 4/5] tunnels: Don't apply GRO to multiple layers of encapsulation Juerg Haefliger
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Juerg Haefliger @ 2016-10-26 15:00 UTC (permalink / raw)
  To: stable, gregkh

From: Jesse Gross <jesse@kernel.org>

commit b8cba75bdf6a48ea4811bbefb11a94a5c7281b68 upstream.

ipip encapsulated packets can be merged together by GRO but the result
does not have the proper GSO type set or even marked as being
encapsulated at all. Later retransmission of these packets will likely
fail if the device does not support ipip offloads. This is similar to
the issue resolved in IPv6 sit in feec0cb3
("ipv6: gro: support sit protocol").

Reported-by: Patrick Boutilier <boutilpj@ednet.ns.ca>
Fixes: 9667e9bb ("ipip: Add gro callbacks to ipip offload")
Tested-by: Patrick Boutilier <boutilpj@ednet.ns.ca>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jesse Gross <jesse@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Juerg Haefliger <juerg.haefliger@hpe.com>
---
 net/ipv4/af_inet.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 5c5db6636704..71be86e965e2 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1425,6 +1425,13 @@ out_unlock:
 	return err;
 }
 
+static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
+{
+	skb->encapsulation = 1;
+	skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
+	return inet_gro_complete(skb, nhoff);
+}
+
 int inet_ctl_sock_create(struct sock **sk, unsigned short family,
 			 unsigned short type, unsigned char protocol,
 			 struct net *net)
@@ -1653,7 +1660,7 @@ static const struct net_offload ipip_offload = {
 	.callbacks = {
 		.gso_segment	= inet_gso_segment,
 		.gro_receive	= inet_gro_receive,
-		.gro_complete	= inet_gro_complete,
+		.gro_complete	= ipip_gro_complete,
 	},
 };
 
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4.4 4/5] tunnels: Don't apply GRO to multiple layers of encapsulation.
  2016-10-26 15:00 [PATCH 4.4 0/5] CVE fixes for stable 4.4 Juerg Haefliger
                   ` (2 preceding siblings ...)
  2016-10-26 15:00 ` [PATCH 4.4 3/5] ipip: Properly mark ipip GRO packets as encapsulated Juerg Haefliger
@ 2016-10-26 15:00 ` Juerg Haefliger
  2016-10-26 15:00 ` [PATCH 4.4 5/5] tunnels: Remove encapsulation offloads on decap Juerg Haefliger
  2016-10-26 15:36 ` [PATCH 4.4 0/5] CVE fixes for stable 4.4 Greg KH
  5 siblings, 0 replies; 9+ messages in thread
From: Juerg Haefliger @ 2016-10-26 15:00 UTC (permalink / raw)
  To: stable, gregkh

From: Jesse Gross <jesse@kernel.org>

commit fac8e0f579695a3ecbc4d3cac369139d7f819971 upstream.

When drivers express support for TSO of encapsulated packets, they
only mean that they can do it for one layer of encapsulation.
Supporting additional levels would mean updating, at a minimum,
more IP length fields and they are unaware of this.

No encapsulation device expresses support for handling offloaded
encapsulated packets, so we won't generate these types of frames
in the transmit path. However, GRO doesn't have a check for
multiple levels of encapsulation and will attempt to build them.

UDP tunnel GRO actually does prevent this situation but it only
handles multiple UDP tunnels stacked on top of each other. This
generalizes that solution to prevent any kind of tunnel stacking
that would cause problems.

Fixes: bf5a755f ("net-gre-gro: Add GRE support to the GRO stack")
Signed-off-by: Jesse Gross <jesse@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Juerg Haefliger <juerg.haefliger@hpe.com>
---
 include/linux/netdevice.h |  4 ++--
 net/core/dev.c            |  2 +-
 net/ipv4/af_inet.c        | 15 ++++++++++++++-
 net/ipv4/gre_offload.c    |  5 +++++
 net/ipv4/udp_offload.c    |  6 +++---
 net/ipv6/ip6_offload.c    | 15 ++++++++++++++-
 6 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4e9c75226f07..12b4d54a8ffa 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1986,8 +1986,8 @@ struct napi_gro_cb {
 	/* This is non-zero if the packet may be of the same flow. */
 	u8	same_flow:1;
 
-	/* Used in udp_gro_receive */
-	u8	udp_mark:1;
+	/* Used in tunnel GRO receive */
+	u8	encap_mark:1;
 
 	/* GRO checksum is valid */
 	u8	csum_valid:1;
diff --git a/net/core/dev.c b/net/core/dev.c
index de4ed2b5a221..0989fea88c44 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4239,7 +4239,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
 		NAPI_GRO_CB(skb)->same_flow = 0;
 		NAPI_GRO_CB(skb)->flush = 0;
 		NAPI_GRO_CB(skb)->free = 0;
-		NAPI_GRO_CB(skb)->udp_mark = 0;
+		NAPI_GRO_CB(skb)->encap_mark = 0;
 		NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
 
 		/* Setup for GRO checksum validation */
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 71be86e965e2..1a5c1ca3ad3c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1383,6 +1383,19 @@ out:
 	return pp;
 }
 
+static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
+					 struct sk_buff *skb)
+{
+	if (NAPI_GRO_CB(skb)->encap_mark) {
+		NAPI_GRO_CB(skb)->flush = 1;
+		return NULL;
+	}
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
+	return inet_gro_receive(head, skb);
+}
+
 int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
 	if (sk->sk_family == AF_INET)
@@ -1659,7 +1672,7 @@ static struct packet_offload ip_packet_offload __read_mostly = {
 static const struct net_offload ipip_offload = {
 	.callbacks = {
 		.gso_segment	= inet_gso_segment,
-		.gro_receive	= inet_gro_receive,
+		.gro_receive	= ipip_gro_receive,
 		.gro_complete	= ipip_gro_complete,
 	},
 };
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index 5a8ee3282550..e603004c1af8 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -128,6 +128,11 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
 	struct packet_offload *ptype;
 	__be16 type;
 
+	if (NAPI_GRO_CB(skb)->encap_mark)
+		goto out;
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
 	off = skb_gro_offset(skb);
 	hlen = off + sizeof(*greh);
 	greh = skb_gro_header_fast(skb, off);
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index f9386160cbee..0e36e56dfd22 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -299,14 +299,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
 	unsigned int off = skb_gro_offset(skb);
 	int flush = 1;
 
-	if (NAPI_GRO_CB(skb)->udp_mark ||
+	if (NAPI_GRO_CB(skb)->encap_mark ||
 	    (skb->ip_summed != CHECKSUM_PARTIAL &&
 	     NAPI_GRO_CB(skb)->csum_cnt == 0 &&
 	     !NAPI_GRO_CB(skb)->csum_valid))
 		goto out;
 
-	/* mark that this skb passed once through the udp gro layer */
-	NAPI_GRO_CB(skb)->udp_mark = 1;
+	/* mark that this skb passed once through the tunnel gro layer */
+	NAPI_GRO_CB(skb)->encap_mark = 1;
 
 	rcu_read_lock();
 	uo_priv = rcu_dereference(udp_offload_base);
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index eeca943f12dc..82e9f3076028 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -258,6 +258,19 @@ out:
 	return pp;
 }
 
+static struct sk_buff **sit_gro_receive(struct sk_buff **head,
+					struct sk_buff *skb)
+{
+	if (NAPI_GRO_CB(skb)->encap_mark) {
+		NAPI_GRO_CB(skb)->flush = 1;
+		return NULL;
+	}
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
+	return ipv6_gro_receive(head, skb);
+}
+
 static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
 {
 	const struct net_offload *ops;
@@ -302,7 +315,7 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
 static const struct net_offload sit_offload = {
 	.callbacks = {
 		.gso_segment	= ipv6_gso_segment,
-		.gro_receive    = ipv6_gro_receive,
+		.gro_receive    = sit_gro_receive,
 		.gro_complete   = sit_gro_complete,
 	},
 };
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4.4 5/5] tunnels: Remove encapsulation offloads on decap.
  2016-10-26 15:00 [PATCH 4.4 0/5] CVE fixes for stable 4.4 Juerg Haefliger
                   ` (3 preceding siblings ...)
  2016-10-26 15:00 ` [PATCH 4.4 4/5] tunnels: Don't apply GRO to multiple layers of encapsulation Juerg Haefliger
@ 2016-10-26 15:00 ` Juerg Haefliger
  2016-10-26 15:36 ` [PATCH 4.4 0/5] CVE fixes for stable 4.4 Greg KH
  5 siblings, 0 replies; 9+ messages in thread
From: Juerg Haefliger @ 2016-10-26 15:00 UTC (permalink / raw)
  To: stable, gregkh

From: Jesse Gross <jesse@kernel.org>

commit a09a4c8dd1ec7f830e1fb9e59eb72bddc965d168 upstream.

If a packet is either locally encapsulated or processed through GRO
it is marked with the offloads that it requires. However, when it is
decapsulated these tunnel offload indications are not removed. This
means that if we receive an encapsulated TCP packet, aggregate it with
GRO, decapsulate, and retransmit the resulting frame on a NIC that does
not support encapsulation, we won't be able to take advantage of hardware
offloads even though it is just a simple TCP packet at this point.

This fixes the problem by stripping off encapsulation offload indications
when packets are decapsulated.

The performance impacts of this bug are significant. In a test where a
Geneve encapsulated TCP stream is sent to a hypervisor, GRO'ed, decapsulated,
and bridged to a VM performance is improved by 60% (5Gbps->8Gbps) as a
result of avoiding unnecessary segmentation at the VM tap interface.

Reported-by: Ramu Ramamurthy <sramamur@linux.vnet.ibm.com>
Fixes: 68c33163 ("v4 GRE: Add TCP segmentation offload for GRE")
Signed-off-by: Jesse Gross <jesse@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

(backported from commit a09a4c8dd1ec7f830e1fb9e59eb72bddc965d168)
[adapt iptunnel_pull_header arguments, avoid 7f290c9]
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>

Signed-off-by: Juerg Haefliger <juerg.haefliger@hpe.com>
---
 include/net/ip_tunnels.h  | 16 ++++++++++++++++
 net/ipv4/fou.c            | 13 +++++++++++--
 net/ipv4/ip_tunnel_core.c |  3 ++-
 net/ipv6/sit.c            |  5 +++--
 4 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index af40bc586a1b..86a7bdd61d1a 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -283,6 +283,22 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
 struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
 					 int gso_type_mask);
 
+static inline int iptunnel_pull_offloads(struct sk_buff *skb)
+{
+	if (skb_is_gso(skb)) {
+		int err;
+
+		err = skb_unclone(skb, GFP_ATOMIC);
+		if (unlikely(err))
+			return err;
+		skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >>
+					       NETIF_F_GSO_SHIFT);
+	}
+
+	skb->encapsulation = 0;
+	return 0;
+}
+
 static inline void iptunnel_xmit_stats(int err,
 				       struct net_device_stats *err_stats,
 				       struct pcpu_sw_netstats __percpu *stats)
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index bd903fe0f750..08d7de55e57e 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -48,7 +48,7 @@ static inline struct fou *fou_from_sock(struct sock *sk)
 	return sk->sk_user_data;
 }
 
-static void fou_recv_pull(struct sk_buff *skb, size_t len)
+static int fou_recv_pull(struct sk_buff *skb, size_t len)
 {
 	struct iphdr *iph = ip_hdr(skb);
 
@@ -59,6 +59,7 @@ static void fou_recv_pull(struct sk_buff *skb, size_t len)
 	__skb_pull(skb, len);
 	skb_postpull_rcsum(skb, udp_hdr(skb), len);
 	skb_reset_transport_header(skb);
+	return iptunnel_pull_offloads(skb);
 }
 
 static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
@@ -68,9 +69,14 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
 	if (!fou)
 		return 1;
 
-	fou_recv_pull(skb, sizeof(struct udphdr));
+	if (fou_recv_pull(skb, sizeof(struct udphdr)))
+		goto drop;
 
 	return -fou->protocol;
+
+drop:
+	kfree_skb(skb);
+	return 0;
 }
 
 static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
@@ -170,6 +176,9 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
 	__skb_pull(skb, sizeof(struct udphdr) + hdrlen);
 	skb_reset_transport_header(skb);
 
+	if (iptunnel_pull_offloads(skb))
+		goto drop;
+
 	return -guehdr->proto_ctype;
 
 drop:
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 6cb9009c3d96..dbda0565781c 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -116,7 +116,8 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
 	skb->vlan_tci = 0;
 	skb_set_queue_mapping(skb, 0);
 	skb->pkt_type = PACKET_HOST;
-	return 0;
+
+	return iptunnel_pull_offloads(skb);
 }
 EXPORT_SYMBOL_GPL(iptunnel_pull_header);
 
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index ba3d2f3d66d2..3da2b16356eb 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -681,14 +681,15 @@ static int ipip6_rcv(struct sk_buff *skb)
 		skb->mac_header = skb->network_header;
 		skb_reset_network_header(skb);
 		IPCB(skb)->flags = 0;
-		skb->protocol = htons(ETH_P_IPV6);
+		skb->dev = tunnel->dev;
 
 		if (packet_is_spoofed(skb, iph, tunnel)) {
 			tunnel->dev->stats.rx_errors++;
 			goto out;
 		}
 
-		__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
+		if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6)))
+			goto out;
 
 		err = IP_ECN_decapsulate(iph, skb);
 		if (unlikely(err)) {
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 4.4 0/5] CVE fixes for stable 4.4
  2016-10-26 15:00 [PATCH 4.4 0/5] CVE fixes for stable 4.4 Juerg Haefliger
                   ` (4 preceding siblings ...)
  2016-10-26 15:00 ` [PATCH 4.4 5/5] tunnels: Remove encapsulation offloads on decap Juerg Haefliger
@ 2016-10-26 15:36 ` Greg KH
  2016-10-26 17:14   ` Juerg Haefliger
  2016-10-28 15:48   ` Greg KH
  5 siblings, 2 replies; 9+ messages in thread
From: Greg KH @ 2016-10-26 15:36 UTC (permalink / raw)
  To: Juerg Haefliger; +Cc: stable

On Wed, Oct 26, 2016 at 05:00:31PM +0200, Juerg Haefliger wrote:
> This series fixes the following CVEs:
>   1/5: CVE-2016-8658
>   2/5: CVE-2016-7097
>   4/5: CVE-2016-8666
> 
> 3-5 is a patch series that also fixes a performance issue with GRO
> encapsulation.

Thanks for these, I'll apply them in the next round of kernels after
this one.

Just curious, why all of the interest in the 4.4-stable kernel tree?
I'm not complaining, as it is really helpful...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4.4 0/5] CVE fixes for stable 4.4
  2016-10-26 15:36 ` [PATCH 4.4 0/5] CVE fixes for stable 4.4 Greg KH
@ 2016-10-26 17:14   ` Juerg Haefliger
  2016-10-28 15:48   ` Greg KH
  1 sibling, 0 replies; 9+ messages in thread
From: Juerg Haefliger @ 2016-10-26 17:14 UTC (permalink / raw)
  To: Greg KH; +Cc: stable


[-- Attachment #1.1: Type: text/plain, Size: 790 bytes --]

On 10/26/2016 05:36 PM, Greg KH wrote:
> On Wed, Oct 26, 2016 at 05:00:31PM +0200, Juerg Haefliger wrote:
>> This series fixes the following CVEs:
>>   1/5: CVE-2016-8658
>>   2/5: CVE-2016-7097
>>   4/5: CVE-2016-8666
>>
>> 3-5 is a patch series that also fixes a performance issue with GRO
>> encapsulation.
> 
> Thanks for these, I'll apply them in the next round of kernels after
> this one.
> 
> Just curious, why all of the interest in the 4.4-stable kernel tree?
> I'm not complaining, as it is really helpful...

4.4 is our current kernel in HPE Linux, until we switch to the next LTS version. I've just finally
found the time to push local patches upstream. I'd rather consume them directly from your tree :-)

...Juerg



> thanks,
> 
> greg k-h
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4.4 0/5] CVE fixes for stable 4.4
  2016-10-26 15:36 ` [PATCH 4.4 0/5] CVE fixes for stable 4.4 Greg KH
  2016-10-26 17:14   ` Juerg Haefliger
@ 2016-10-28 15:48   ` Greg KH
  1 sibling, 0 replies; 9+ messages in thread
From: Greg KH @ 2016-10-28 15:48 UTC (permalink / raw)
  To: Juerg Haefliger; +Cc: stable

On Wed, Oct 26, 2016 at 05:36:32PM +0200, Greg KH wrote:
> On Wed, Oct 26, 2016 at 05:00:31PM +0200, Juerg Haefliger wrote:
> > This series fixes the following CVEs:
> >   1/5: CVE-2016-8658
> >   2/5: CVE-2016-7097
> >   4/5: CVE-2016-8666
> > 
> > 3-5 is a patch series that also fixes a performance issue with GRO
> > encapsulation.
> 
> Thanks for these, I'll apply them in the next round of kernels after
> this one.

All now applied, thanks a lot for the backports.

greg k-h

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-10-28 15:48 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-26 15:00 [PATCH 4.4 0/5] CVE fixes for stable 4.4 Juerg Haefliger
2016-10-26 15:00 ` [PATCH 4.4 1/5] brcmfmac: avoid potential stack overflow in brcmf_cfg80211_start_ap() Juerg Haefliger
2016-10-26 15:00 ` [PATCH 4.4 2/5] posix_acl: Clear SGID bit when setting file permissions Juerg Haefliger
2016-10-26 15:00 ` [PATCH 4.4 3/5] ipip: Properly mark ipip GRO packets as encapsulated Juerg Haefliger
2016-10-26 15:00 ` [PATCH 4.4 4/5] tunnels: Don't apply GRO to multiple layers of encapsulation Juerg Haefliger
2016-10-26 15:00 ` [PATCH 4.4 5/5] tunnels: Remove encapsulation offloads on decap Juerg Haefliger
2016-10-26 15:36 ` [PATCH 4.4 0/5] CVE fixes for stable 4.4 Greg KH
2016-10-26 17:14   ` Juerg Haefliger
2016-10-28 15:48   ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.