From 002840f60557eb629420a93df7b7ce18a77523b8 Mon Sep 17 00:00:00 2001 From: Colin McCabe Date: Wed, 11 Dec 2013 18:58:30 +0000 Subject: [PATCH] HADOOP-10087. UserGroupInformation.getGroupNames() fails to return primary group first when JniBasedUnixGroupsMappingWithFallback is used (cmccabe) git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1550229 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 3 ++ .../apache/hadoop/security/hadoop_user_info.c | 47 ++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 84cc137d394..1ccc28e3ba1 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -538,6 +538,9 @@ Release 2.3.0 - UNRELEASED HADOOP-10081. Client.setupIOStreams can leak socket resources on exception or error (Tsuyoshi OZAWA via jlowe) + HADOOP-10087. UserGroupInformation.getGroupNames() fails to return primary + group first when JniBasedUnixGroupsMappingWithFallback is used (cmccabe) + Release 2.2.0 - 2013-10-13 INCOMPATIBLE CHANGES diff --git a/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c b/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c index 2b11032e1c3..5c58b96c39e 100644 --- a/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c +++ b/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c @@ -122,13 +122,43 @@ int hadoop_user_info_fetch(struct hadoop_user_info *uinfo, } } +static int put_primary_gid_first(struct hadoop_user_info *uinfo) +{ + int i, num_gids = uinfo->num_gids; + gid_t first_gid; + gid_t gid; + gid_t primary = uinfo->pwd.pw_gid; + + if (num_gids < 1) { + // There are no gids, but we expected at least one. + return EINVAL; + } + first_gid = uinfo->gids[0]; + if (first_gid == primary) { + // First gid is already the primary. + return 0; + } + for (i = 1; i < num_gids; i++) { + gid = uinfo->gids[i]; + if (gid == primary) { + // swap first gid and this gid. + uinfo->gids[0] = gid; + uinfo->gids[i] = first_gid; + return 0; + } + } + // Did not find the primary gid in the list. + return EINVAL; +} + int hadoop_user_info_getgroups(struct hadoop_user_info *uinfo) { int ret, ngroups; gid_t *ngids; if (!uinfo->pwd.pw_name) { - return EINVAL; // invalid user info + // invalid user info + return EINVAL; } uinfo->num_gids = 0; if (!uinfo->gids) { @@ -141,8 +171,12 @@ int hadoop_user_info_getgroups(struct hadoop_user_info *uinfo) ngroups = uinfo->gids_size; ret = getgrouplist(uinfo->pwd.pw_name, uinfo->pwd.pw_gid, uinfo->gids, &ngroups); - if (ret != -1) { + if (ret > 0) { uinfo->num_gids = ngroups; + ret = put_primary_gid_first(uinfo); + if (ret) { + return ret; + } return 0; } ngids = realloc(uinfo->gids, sizeof(uinfo->gids[0]) * ngroups); @@ -153,11 +187,12 @@ int hadoop_user_info_getgroups(struct hadoop_user_info *uinfo) uinfo->gids_size = ngroups; ret = getgrouplist(uinfo->pwd.pw_name, uinfo->pwd.pw_gid, uinfo->gids, &ngroups); - if (ret != -1) { - uinfo->num_gids = ngroups; - return 0; + if (ret < 0) { + return EIO; } - return EIO; + uinfo->num_gids = ngroups; + ret = put_primary_gid_first(uinfo); + return ret; } #ifdef USER_TESTING