diff mbox

[VIVID,MAKO/MANTA/FLO] net: ipv4: current group_info should be put after using.

Message ID 1422041321-23503-1-git-send-email-tyhicks@canonical.com
State New
Headers show

Commit Message

Tyler Hicks Jan. 23, 2015, 7:28 p.m. UTC
From: "Wang, Xiaoming" <xiaoming.wang@intel.com>

Plug a group_info refcount leak in ping_init.
group_info is only needed during initialization and
the code failed to release the reference on exit.
While here move grabbing the reference to a place
where it is actually needed.

Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
Signed-off-by: Zhang Dongxing <dongxing.zhang@intel.com>
Signed-off-by: xiaoming wang <xiaoming.wang@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit b04c46190219a4f845e46a459e3102137b7f6cac)
CVE-2014-2851
BugLink: http://bugs.launchpad.net/bugs/1312994
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>

Conflicts:
	net/ipv4/ping.c
---

This fix is important for the Touch kernels because the Android init enables
the sending of ICMP echo request by unprivileged processes, meaning that an
unprivileged process can trigger this bug on Touch.

The goldfish kernel already has this patch applied so mako, manta, and flo are
the only branches this should be applied to.

I've manually tested a kernel with this patch applied on a mako device.

Thanks!

Tyler

 net/ipv4/ping.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

Comments

Andy Whitcroft Jan. 27, 2015, 6:18 p.m. UTC | #1
Applied to Vivid (mako, manta and flo).

-apw
diff mbox

Patch

diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index a8d7ed0..cce74ad 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -248,26 +248,33 @@  int ping_init_sock(struct sock *sk)
 	struct net *net = sock_net(sk);
 	gid_t group = current_egid();
 	gid_t range[2];
-	struct group_info *group_info = get_current_groups();
-	int i, j, count = group_info->ngroups;
+	struct group_info *group_info;
+	int i, j, count;
+	int ret = 0;
 
 	inet_get_ping_group_range_net(net, range, range+1);
 	if (range[0] <= group && group <= range[1])
 		return 0;
 
+	group_info = get_current_groups();
+	count = group_info->ngroups;
 	for (i = 0; i < group_info->nblocks; i++) {
 		int cp_count = min_t(int, NGROUPS_PER_BLOCK, count);
 
 		for (j = 0; j < cp_count; j++) {
 			group = group_info->blocks[i][j];
 			if (range[0] <= group && group <= range[1])
-				return 0;
+				goto out_release_group;
 		}
 
 		count -= cp_count;
 	}
 
-	return -EACCES;
+	ret = -EACCES;
+
+out_release_group:
+	put_group_info(group_info);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(ping_init_sock);