You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by cm...@apache.org on 2013/06/24 18:25:52 UTC
svn commit: r1496115 - in
/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common: ./
src/ src/main/java/org/apache/hadoop/io/nativeio/
src/main/java/org/apache/hadoop/security/ src/main/native/src/
src/main/native/src/org/apache/hadoop/io...
Author: cmccabe
Date: Mon Jun 24 16:25:52 2013
New Revision: 1496115
URL: http://svn.apache.org/r1496115
Log:
HADOOP-9439. JniBasedUnixGroupsMapping: fix some crash bugs (Colin Patrick McCabe)
Added:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.c
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.h
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.h
Removed:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/getGroup.c
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/CMakeLists.txt
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/nativeio/NativeIO.java
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/JniBasedUnixGroupsMapping.java
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.c
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.h
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/io/nativeio/NativeIO.c
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/net/unix/DomainSocket.c
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMappingWin.c
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt Mon Jun 24 16:25:52 2013
@@ -285,6 +285,9 @@ Release 2.1.0-beta - UNRELEASED
HADOOP-9624. TestFSMainOperationsLocalFileSystem failed when the Hadoop test
root path has "X" in its name. (Xi Fang via cnauroth)
+ HADOOP-9439. JniBasedUnixGroupsMapping: fix some crash bugs (Colin Patrick
+ McCabe)
+
BREAKDOWN OF HADOOP-8562 SUBTASKS AND RELATED JIRAS
HADOOP-8924. Hadoop Common creating package-info.java must not depend on
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/CMakeLists.txt
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/CMakeLists.txt?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/CMakeLists.txt (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/CMakeLists.txt Mon Jun 24 16:25:52 2013
@@ -180,7 +180,8 @@ add_dual_library(hadoop
${D}/net/unix/DomainSocket.c
${D}/security/JniBasedUnixGroupsMapping.c
${D}/security/JniBasedUnixGroupsNetgroupMapping.c
- ${D}/security/getGroup.c
+ ${D}/security/hadoop_group_info.c
+ ${D}/security/hadoop_user_info.c
${D}/util/NativeCodeLoader.c
${D}/util/NativeCrc32.c
${D}/util/bulk_crc32.c
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/nativeio/NativeIO.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/nativeio/NativeIO.java?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/nativeio/NativeIO.java (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/nativeio/NativeIO.java Mon Jun 24 16:25:52 2013
@@ -98,7 +98,7 @@ public class NativeIO {
static final String WORKAROUND_NON_THREADSAFE_CALLS_KEY =
"hadoop.workaround.non.threadsafe.getpwuid";
- static final boolean WORKAROUND_NON_THREADSAFE_CALLS_DEFAULT = false;
+ static final boolean WORKAROUND_NON_THREADSAFE_CALLS_DEFAULT = true;
private static long cacheTimeout = -1;
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/JniBasedUnixGroupsMapping.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/JniBasedUnixGroupsMapping.java?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/JniBasedUnixGroupsMapping.java (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/JniBasedUnixGroupsMapping.java Mon Jun 24 16:25:52 2013
@@ -40,22 +40,44 @@ public class JniBasedUnixGroupsMapping i
private static final Log LOG =
LogFactory.getLog(JniBasedUnixGroupsMapping.class);
-
- native String[] getGroupForUser(String user);
-
+
static {
if (!NativeCodeLoader.isNativeCodeLoaded()) {
throw new RuntimeException("Bailing out since native library couldn't " +
"be loaded");
}
+ anchorNative();
LOG.debug("Using JniBasedUnixGroupsMapping for Group resolution");
}
+ /**
+ * Set up our JNI resources.
+ *
+ * @throws RuntimeException if setup fails.
+ */
+ native static void anchorNative();
+
+ /**
+ * Get the set of groups associated with a user.
+ *
+ * @param username The user name
+ *
+ * @return The set of groups associated with a user.
+ */
+ native static String[] getGroupsForUser(String username);
+
+ /**
+ * Log an error message about a group. Used from JNI.
+ */
+ static private void logError(int groupId, String error) {
+ LOG.error("error looking up the name of group " + groupId + ": " + error);
+ }
+
@Override
public List<String> getGroups(String user) throws IOException {
String[] groups = new String[0];
try {
- groups = getGroupForUser(user);
+ groups = getGroupsForUser(user);
} catch (Exception e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Error getting groups for " + user, e);
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.c?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.c (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.c Mon Jun 24 16:25:52 2013
@@ -107,3 +107,12 @@ jthrowable newIOException(JNIEnv* env, c
va_end(ap);
return jthr;
}
+
+const char* terror(int errnum)
+{
+ if ((errnum < 0) || (errnum >= sys_nerr)) {
+ return "unknown error.";
+ }
+ return sys_errlist[errnum];
+}
+
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.h?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.h (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/exception.h Mon Jun 24 16:25:52 2013
@@ -79,4 +79,12 @@ jthrowable newRuntimeException(JNIEnv* e
jthrowable newIOException(JNIEnv* env, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
+/**
+ * Thread-safe strerror alternative.
+ *
+ * @param errnum Error number.
+ * @return Statically allocated error string.
+ */
+const char* terror(int errnum);
+
#endif
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/io/nativeio/NativeIO.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/io/nativeio/NativeIO.c?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/io/nativeio/NativeIO.c (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/io/nativeio/NativeIO.c Mon Jun 24 16:25:52 2013
@@ -59,7 +59,7 @@ static jmethodID nioe_ctor;
// the monitor used for working around non-threadsafe implementations
// of getpwuid_r, observed on platforms including RHEL 6.0.
// Please see HADOOP-7156 for details.
-static jobject pw_lock_object;
+jobject pw_lock_object;
// Internal functions
static void throw_ioe(JNIEnv* env, int errnum);
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/net/unix/DomainSocket.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/net/unix/DomainSocket.c?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/net/unix/DomainSocket.c (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/net/unix/DomainSocket.c Mon Jun 24 16:25:52 2013
@@ -107,14 +107,6 @@ static jthrowable newSocketException(JNI
return jthr;
}
-static const char* terror(int errnum)
-{
- if ((errnum < 0) || (errnum >= sys_nerr)) {
- return "unknown error.";
- }
- return sys_errlist[errnum];
-}
-
/**
* Flexible buffer that will try to fit data on the stack, and fall back
* to the heap if necessary.
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMapping.c Mon Jun 24 16:25:52 2013
@@ -30,88 +30,173 @@
#include <pwd.h>
#include <string.h>
+#include "exception.h"
#include "org_apache_hadoop_security_JniBasedUnixGroupsMapping.h"
#include "org_apache_hadoop.h"
+#include "hadoop_group_info.h"
+#include "hadoop_user_info.h"
-static jobjectArray emptyGroups = NULL;
+static jmethodID g_log_error_method;
-JNIEXPORT jobjectArray JNICALL
-Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_getGroupForUser
-(JNIEnv *env, jobject jobj, jstring juser) {
- extern int getGroupIDList(const char *user, int *ngroups, gid_t **groups);
- extern int getGroupDetails(gid_t group, char **grpBuf);
- const char *cuser = NULL;
- jobjectArray jgroups = NULL;
- int error = -1;
+static jclass g_string_clazz;
- if (emptyGroups == NULL) {
- jobjectArray lEmptyGroups = (jobjectArray)(*env)->NewObjectArray(env, 0,
- (*env)->FindClass(env, "java/lang/String"), NULL);
- if (lEmptyGroups == NULL) {
- goto cleanup;
- }
- emptyGroups = (*env)->NewGlobalRef(env, lEmptyGroups);
- if (emptyGroups == NULL) {
- goto cleanup;
- }
- }
- char *grpBuf = NULL;
- cuser = (*env)->GetStringUTFChars(env, juser, NULL);
- if (cuser == NULL) {
- goto cleanup;
- }
+extern jobject pw_lock_object;
- /*Get the number of the groups, and their IDs, this user belongs to*/
- gid_t *groups = NULL;
- int ngroups = 0;
- error = getGroupIDList(cuser, &ngroups, &groups);
- if (error != 0) {
- goto cleanup;
+JNIEXPORT void JNICALL
+Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_anchorNative(
+JNIEnv *env, jclass clazz)
+{
+ jobject string_clazz;
+
+ g_log_error_method = (*env)->GetStaticMethodID(env, clazz, "logError",
+ "(ILjava/lang/String;)V");
+ if (!g_log_error_method) {
+ return; // an exception has been raised
+ }
+ string_clazz = (*env)->FindClass(env, "java/lang/String");
+ if (!string_clazz) {
+ return; // an exception has been raised
+ }
+ g_string_clazz = (*env)->NewGlobalRef(env, string_clazz);
+ if (!g_string_clazz) {
+ jthrowable jthr = newRuntimeException(env,
+ "JniBasedUnixGroupsMapping#anchorNative: failed to make "
+ "a global reference to the java.lang.String class\n");
+ (*env)->Throw(env, jthr);
+ return;
}
+}
- jgroups = (jobjectArray)(*env)->NewObjectArray(env, ngroups,
- (*env)->FindClass(env, "java/lang/String"), NULL);
- if (jgroups == NULL) {
- error = -1;
- goto cleanup;
+/**
+ * Log an error about a failure to look up a group ID
+ *
+ * @param env The JNI environment
+ * @param clazz JniBasedUnixGroupsMapping class
+ * @param gid The gid we failed to look up
+ * @param ret Failure code
+ */
+static void logError(JNIEnv *env, jclass clazz, jint gid, int ret)
+{
+ jstring error_msg;
+
+ error_msg = (*env)->NewStringUTF(env, terror(ret));
+ if (!error_msg) {
+ (*env)->ExceptionClear(env);
+ return;
+ }
+ (*env)->CallStaticVoidMethod(env, clazz, g_log_error_method, gid, error_msg);
+ if ((*env)->ExceptionCheck(env)) {
+ (*env)->ExceptionClear(env);
+ return;
}
+ (*env)->DeleteLocalRef(env, error_msg);
+}
- /*Iterate over the groupIDs and get the group structure for each*/
- int i = 0;
- for (i = 0; i < ngroups; i++) {
- error = getGroupDetails(groups[i],&grpBuf);
- if (error != 0) {
- goto cleanup;
+JNIEXPORT jobjectArray JNICALL
+Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_getGroupsForUser
+(JNIEnv *env, jclass clazz, jstring jusername)
+{
+ const char *username = NULL;
+ struct hadoop_user_info *uinfo = NULL;
+ struct hadoop_group_info *ginfo = NULL;
+ jstring jgroupname = NULL;
+ int i, ret, nvalid;
+ int pw_lock_locked = 0;
+ jobjectArray jgroups = NULL, jnewgroups = NULL;
+
+ if (pw_lock_object != NULL) {
+ if ((*env)->MonitorEnter(env, pw_lock_object) != JNI_OK) {
+ goto done; // exception thrown
+ }
+ pw_lock_locked = 1;
+ }
+ username = (*env)->GetStringUTFChars(env, jusername, NULL);
+ if (username == NULL) {
+ goto done; // exception thrown
+ }
+ uinfo = hadoop_user_info_alloc();
+ if (!uinfo) {
+ THROW(env, "java/lang/OutOfMemoryError", NULL);
+ goto done;
+ }
+ ret = hadoop_user_info_fetch(uinfo, username);
+ if (ret == ENOENT) {
+ jgroups = (*env)->NewObjectArray(env, 0, g_string_clazz, NULL);
+ goto done;
+ }
+ ginfo = hadoop_group_info_alloc();
+ if (!ginfo) {
+ THROW(env, "java/lang/OutOfMemoryError", NULL);
+ goto done;
+ }
+ ret = hadoop_user_info_getgroups(uinfo);
+ if (ret) {
+ if (ret == ENOMEM) {
+ THROW(env, "java/lang/OutOfMemoryError", NULL);
+ } else {
+ char buf[128];
+ snprintf(buf, sizeof(buf), "getgrouplist error %d (%s)",
+ ret, terror(ret));
+ THROW(env, "java/lang/RuntimeException", buf);
}
- jstring jgrp = (*env)->NewStringUTF(env, ((struct group*)grpBuf)->gr_name);
- if (jgrp == NULL) {
- error = -1;
- goto cleanup;
+ goto done;
+ }
+ jgroups = (jobjectArray)(*env)->NewObjectArray(env, uinfo->num_gids,
+ g_string_clazz, NULL);
+ for (nvalid = 0, i = 0; i < uinfo->num_gids; i++) {
+ ret = hadoop_group_info_fetch(ginfo, uinfo->gids[i]);
+ if (ret) {
+ logError(env, clazz, uinfo->gids[i], ret);
+ } else {
+ jgroupname = (*env)->NewStringUTF(env, ginfo->group.gr_name);
+ if (!jgroupname) { // exception raised
+ (*env)->DeleteLocalRef(env, jgroups);
+ jgroups = NULL;
+ goto done;
+ }
+ (*env)->SetObjectArrayElement(env, jgroups, nvalid++, jgroupname);
+ // We delete the local reference once the element is in the array.
+ // This is OK because the array has a reference to it.
+ // Technically JNI only mandates that the JVM allow up to 16 local
+ // references at a time (though many JVMs allow more than that.)
+ (*env)->DeleteLocalRef(env, jgroupname);
+ }
+ }
+ if (nvalid != uinfo->num_gids) {
+ // If some group names could not be looked up, allocate a smaller array
+ // with just the entries that could be resolved. Java has no equivalent to
+ // realloc, so we have to do this manually.
+ jnewgroups = (jobjectArray)(*env)->NewObjectArray(env, nvalid,
+ (*env)->FindClass(env, "java/lang/String"), NULL);
+ if (!jnewgroups) { // exception raised
+ (*env)->DeleteLocalRef(env, jgroups);
+ jgroups = NULL;
+ goto done;
+ }
+ for (i = 0; i < nvalid; i++) {
+ jgroupname = (*env)->GetObjectArrayElement(env, jgroups, i);
+ (*env)->SetObjectArrayElement(env, jnewgroups, i, jgroupname);
+ (*env)->DeleteLocalRef(env, jgroupname);
}
- (*env)->SetObjectArrayElement(env, jgroups,i,jgrp);
- free(grpBuf);
- grpBuf = NULL;
+ (*env)->DeleteLocalRef(env, jgroups);
+ jgroups = jnewgroups;
}
-cleanup:
- if (error == ENOMEM) {
- THROW(env, "java/lang/OutOfMemoryError", NULL);
+done:
+ if (pw_lock_locked) {
+ (*env)->MonitorExit(env, pw_lock_object);
}
- if (error == ENOENT) {
- THROW(env, "java/io/IOException", "No entry for user");
+ if (username) {
+ (*env)->ReleaseStringUTFChars(env, jusername, username);
}
- if (groups != NULL) {
- free(groups);
+ if (uinfo) {
+ hadoop_user_info_free(uinfo);
}
- if (grpBuf != NULL) {
- free(grpBuf);
+ if (ginfo) {
+ hadoop_group_info_free(ginfo);
}
- if (cuser != NULL) {
- (*env)->ReleaseStringUTFChars(env, juser, cuser);
- }
- if (error == 0) {
- return jgroups;
- } else {
- return emptyGroups;
+ if (jgroupname) {
+ (*env)->DeleteLocalRef(env, jgroupname);
}
+ return jgroups;
}
Modified: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMappingWin.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMappingWin.c?rev=1496115&r1=1496114&r2=1496115&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMappingWin.c (original)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/JniBasedUnixGroupsMappingWin.c Mon Jun 24 16:25:52 2013
@@ -25,6 +25,13 @@
static jobjectArray emptyGroups = NULL;
+JNIEXPORT void JNICALL
+Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_anchorNative(
+JNIEnv *env, jclass clazz)
+{
+ // no-op until full port of HADOOP-9439 to Windows is available
+}
+
/*
* Throw a java.IO.IOException, generating the message from errno.
*/
@@ -57,8 +64,8 @@ static void throw_ioexception(JNIEnv* en
}
JNIEXPORT jobjectArray JNICALL
-Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_getGroupForUser
-(JNIEnv *env, jobject jobj, jstring juser) {
+Java_org_apache_hadoop_security_JniBasedUnixGroupsMapping_getGroupsForUser
+(JNIEnv *env, jclass clazz, jstring juser) {
const WCHAR *user = NULL;
jobjectArray jgroups = NULL;
DWORD dwRtnCode = ERROR_SUCCESS;
Added: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.c?rev=1496115&view=auto
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.c (added)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.c Mon Jun 24 16:25:52 2013
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hadoop_group_info.h"
+
+#include <errno.h>
+#include <grp.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct hadoop_group_info *hadoop_group_info_alloc(void)
+{
+ struct hadoop_group_info *ginfo;
+ size_t buf_sz;
+ char *buf;
+
+ ginfo = calloc(1, sizeof(struct hadoop_group_info));
+ buf_sz = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (buf_sz < 1024) {
+ buf_sz = 1024;
+ }
+ buf = malloc(buf_sz);
+ if (!buf) {
+ free(ginfo);
+ return NULL;
+ }
+ ginfo->buf_sz = buf_sz;
+ ginfo->buf = buf;
+ return ginfo;
+}
+
+void hadoop_group_info_clear(struct hadoop_group_info *ginfo)
+{
+ struct group *group = &ginfo->group;
+
+ group->gr_name = NULL;
+ group->gr_passwd = NULL;
+ group->gr_gid = 0;
+ group->gr_mem = NULL;
+}
+
+void hadoop_group_info_free(struct hadoop_group_info *ginfo)
+{
+ free(ginfo->buf);
+ free(ginfo);
+}
+
+/**
+ * Different platforms use different error codes to represent "group not found."
+ * So whitelist the errors which do _not_ mean "group not found."
+ *
+ * @param err The errno
+ *
+ * @return The error code to use
+ */
+static int getgrgid_error_translate(int err)
+{
+ if ((err == EIO) || (err == EMFILE) || (err == ENFILE) ||
+ (err == ENOMEM) || (err == ERANGE)) {
+ return err;
+ }
+ return ENOENT;
+}
+
+int hadoop_group_info_fetch(struct hadoop_group_info *ginfo, gid_t gid)
+{
+ struct group *group;
+ int err;
+ size_t buf_sz;
+ char *nbuf;
+
+ hadoop_group_info_clear(ginfo);
+ for (;;) {
+ do {
+ group = NULL;
+ err = getgrgid_r(gid, &ginfo->group, ginfo->buf,
+ ginfo->buf_sz, &group);
+ } while ((!group) && (err == EINTR));
+ if (group) {
+ return 0;
+ }
+ if (err != ERANGE) {
+ return getgrgid_error_translate(errno);
+ }
+ buf_sz = ginfo->buf_sz * 2;
+ nbuf = realloc(ginfo->buf, buf_sz);
+ if (!nbuf) {
+ return ENOMEM;
+ }
+ ginfo->buf = nbuf;
+ ginfo->buf_sz = buf_sz;
+ }
+}
+
+#ifdef GROUP_TESTING
+/**
+ * A main() is provided so that quick testing of this
+ * library can be done.
+ */
+int main(int argc, char **argv) {
+ char **groupname;
+ struct hadoop_group_info *ginfo;
+ int ret;
+
+ ginfo = hadoop_group_info_alloc();
+ if (!ginfo) {
+ fprintf(stderr, "hadoop_group_info_alloc returned NULL.\n");
+ return EXIT_FAILURE;
+ }
+ for (groupname = argv + 1; *groupname; groupname++) {
+ gid_t gid = atoi(*groupname);
+ if (gid == 0) {
+ fprintf(stderr, "won't accept non-parseable group-name or gid 0: %s\n",
+ *groupname);
+ return EXIT_FAILURE;
+ }
+ ret = hadoop_group_info_fetch(ginfo, gid);
+ if (!ret) {
+ fprintf(stderr, "gid[%lld] : gr_name = %s\n",
+ (long long)gid, ginfo->group.gr_name);
+ } else {
+ fprintf(stderr, "group[%lld] : error %d (%s)\n",
+ (long long)gid, ret, strerror(ret));
+ }
+ }
+ hadoop_group_info_free(ginfo);
+ return EXIT_SUCCESS;
+}
+#endif
Added: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.h?rev=1496115&view=auto
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.h (added)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_group_info.h Mon Jun 24 16:25:52 2013
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef HADOOP_GROUP_INFO_DOT_H
+#define HADOOP_GROUP_INFO_DOT_H
+
+#include <grp.h> /* for struct group */
+#include <unistd.h> /* for size_t */
+
+struct hadoop_group_info {
+ size_t buf_sz;
+ struct group group;
+ char *buf;
+};
+
+/**
+ * Allocate a hadoop group info context.
+ *
+ * @return NULL on OOM; the context otherwise.
+ */
+struct hadoop_group_info *hadoop_group_info_alloc(void);
+
+/**
+ * Free a hadoop group info context.
+ *
+ * @param uinfo The hadoop group info context to free.
+ */
+void hadoop_group_info_free(struct hadoop_group_info *ginfo);
+
+/**
+ * Look up information for a group id.
+ *
+ * @param uinfo The hadoop group info context.
+ * Existing data in this context will be cleared.
+ * @param gid The group id to look up.
+ *
+ * @return ENOENT if the group wasn't found;
+ * 0 on success;
+ * EIO, EMFILE, ENFILE, or ENOMEM if appropriate.
+ */
+int hadoop_group_info_fetch(struct hadoop_group_info *ginfo, gid_t gid);
+
+#endif
Added: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c?rev=1496115&view=auto
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c (added)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.c Mon Jun 24 16:25:52 2013
@@ -0,0 +1,203 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hadoop_user_info.h"
+
+#include <errno.h>
+#include <grp.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define INITIAL_GIDS_SIZE 32
+
+struct hadoop_user_info *hadoop_user_info_alloc(void)
+{
+ struct hadoop_user_info *uinfo;
+ size_t buf_sz;
+ char *buf;
+
+ uinfo = calloc(1, sizeof(struct hadoop_user_info));
+ buf_sz = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (buf_sz < 1024) {
+ buf_sz = 1024;
+ }
+ buf = malloc(buf_sz);
+ if (!buf) {
+ free(uinfo);
+ return NULL;
+ }
+ uinfo->buf_sz = buf_sz;
+ uinfo->buf = buf;
+ return uinfo;
+}
+
+static void hadoop_user_info_clear(struct hadoop_user_info *uinfo)
+{
+ struct passwd *pwd = &uinfo->pwd;
+
+ pwd->pw_name = NULL;
+ pwd->pw_uid = 0;
+ pwd->pw_gid = 0;
+ pwd->pw_passwd = NULL;
+ pwd->pw_gecos = NULL;
+ pwd->pw_dir = NULL;
+ pwd->pw_shell = NULL;
+ free(uinfo->gids);
+ uinfo->gids = 0;
+ uinfo->num_gids = 0;
+ uinfo->gids_size = 0;
+}
+
+void hadoop_user_info_free(struct hadoop_user_info *uinfo)
+{
+ free(uinfo->buf);
+ hadoop_user_info_clear(uinfo);
+ free(uinfo);
+}
+
+/**
+ * Different platforms use different error codes to represent "user not found."
+ * So whitelist the errors which do _not_ mean "user not found."
+ *
+ * @param err The errno
+ *
+ * @return The error code to use
+ */
+static int getpwnam_error_translate(int err)
+{
+ if ((err == EIO) || (err == EMFILE) || (err == ENFILE) ||
+ (err == ENOMEM) || (err == ERANGE)) {
+ return err;
+ }
+ return ENOENT;
+}
+
+int hadoop_user_info_fetch(struct hadoop_user_info *uinfo,
+ const char *username)
+{
+ struct passwd *pwd;
+ int err;
+ size_t buf_sz;
+ char *nbuf;
+
+ hadoop_user_info_clear(uinfo);
+ for (;;) {
+ do {
+ pwd = NULL;
+ err = getpwnam_r(username, &uinfo->pwd, uinfo->buf,
+ uinfo->buf_sz, &pwd);
+ } while ((!pwd) && (errno == EINTR));
+ if (pwd) {
+ return 0;
+ }
+ if (err != ERANGE) {
+ return getpwnam_error_translate(errno);
+ }
+ buf_sz = uinfo->buf_sz * 2;
+ nbuf = realloc(uinfo->buf, buf_sz);
+ if (!nbuf) {
+ return ENOMEM;
+ }
+ uinfo->buf = nbuf;
+ uinfo->buf_sz = buf_sz;
+ }
+}
+
+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
+ }
+ uinfo->num_gids = 0;
+ if (!uinfo->gids) {
+ uinfo->gids = malloc(sizeof(uinfo->gids[0]) * INITIAL_GIDS_SIZE);
+ if (!uinfo->gids) {
+ return ENOMEM;
+ }
+ uinfo->gids_size = INITIAL_GIDS_SIZE;
+ }
+ ngroups = uinfo->gids_size;
+ ret = getgrouplist(uinfo->pwd.pw_name, uinfo->pwd.pw_gid,
+ uinfo->gids, &ngroups);
+ if (ret != -1) {
+ uinfo->num_gids = ngroups;
+ return 0;
+ }
+ ngids = realloc(uinfo->gids, sizeof(uinfo->gids[0]) * ngroups);
+ if (!ngids) {
+ return ENOMEM;
+ }
+ uinfo->gids = ngids;
+ 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;
+ }
+ return EIO;
+}
+
+#ifdef USER_TESTING
+/**
+ * A main() is provided so that quick testing of this
+ * library can be done.
+ */
+int main(int argc, char **argv) {
+ char **username, *prefix;
+ struct hadoop_user_info *uinfo;
+ int i, ret;
+
+ uinfo = hadoop_user_info_alloc();
+ if (!uinfo) {
+ fprintf(stderr, "hadoop_user_info_alloc returned NULL.\n");
+ return EXIT_FAILURE;
+ }
+ for (username = argv + 1; *username; username++) {
+ ret = hadoop_user_info_fetch(uinfo, *username);
+ if (!ret) {
+ fprintf(stderr, "user[%s] : pw_uid = %lld\n",
+ *username, (long long)uinfo->pwd.pw_uid);
+ } else {
+ fprintf(stderr, "user[%s] : error %d (%s)\n",
+ *username, ret, strerror(ret));
+ }
+ ret = hadoop_user_info_getgroups(uinfo);
+ if (!ret) {
+ fprintf(stderr, " getgroups: ");
+ prefix = "";
+ for (i = 0; i < uinfo->num_gids; i++) {
+ fprintf(stderr, "%s%lld", prefix, (long long)uinfo->gids[i]);
+ prefix = ", ";
+ }
+ fprintf(stderr, "\n");
+ } else {
+ fprintf(stderr, " getgroups: error %d\n", ret);
+ }
+ }
+ hadoop_user_info_free(uinfo);
+ return EXIT_SUCCESS;
+}
+#endif
Added: hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.h
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.h?rev=1496115&view=auto
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.h (added)
+++ hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/native/src/org/apache/hadoop/security/hadoop_user_info.h Mon Jun 24 16:25:52 2013
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef HADOOP_USER_INFO_DOT_H
+#define HADOOP_USER_INFO_DOT_H
+
+#include <pwd.h> /* for struct passwd */
+#include <unistd.h> /* for size_t */
+
+struct hadoop_user_info {
+ size_t buf_sz;
+ struct passwd pwd;
+ char *buf;
+ gid_t *gids;
+ int num_gids;
+ int gids_size;
+};
+
+/**
+ * Allocate a hadoop user info context.
+ *
+ * @return NULL on OOM; the context otherwise.
+ */
+struct hadoop_user_info *hadoop_user_info_alloc(void);
+
+/**
+ * Free a hadoop user info context.
+ *
+ * @param uinfo The hadoop user info context to free.
+ */
+void hadoop_user_info_free(struct hadoop_user_info *uinfo);
+
+/**
+ * Look up information for a user name.
+ *
+ * @param uinfo The hadoop user info context.
+ * Existing data in this context will be cleared.
+ * @param username The user name to look up.
+ *
+ * @return ENOENT if the user wasn't found;
+ * 0 on success;
+ * EIO, EMFILE, ENFILE, or ENOMEM if appropriate.
+ */
+int hadoop_user_info_fetch(struct hadoop_user_info *uinfo,
+ const char *username);
+
+/**
+ * Look up the groups this user belongs to.
+ *
+ * @param uinfo The hadoop user info context.
+ * uinfo->gids will be filled in on a successful
+ * return;
+ *
+ * @return 0 on success.
+ * ENOMEM if we ran out of memory.
+ * EINVAL if the uinfo was invalid.
+ */
+int hadoop_user_info_getgroups(struct hadoop_user_info *uinfo);
+
+#endif