HADOOP-12344. Improve validateSocketPathSecurity0 error message (Casey Brotherton via Colin P. McCabe)
This commit is contained in:
parent
da16c9b3b4
commit
6716f15964
|
@ -882,6 +882,9 @@ Release 2.8.0 - UNRELEASED
|
||||||
HADOOP-11104. org.apache.hadoop.metrics2.lib.MetricsRegistry needs numerical
|
HADOOP-11104. org.apache.hadoop.metrics2.lib.MetricsRegistry needs numerical
|
||||||
parameter checking. (Ray Chiang via aajisaka)
|
parameter checking. (Ray Chiang via aajisaka)
|
||||||
|
|
||||||
|
HADOOP-12344. Improve validateSocketPathSecurity0 error message (Casey
|
||||||
|
Brotherton via Colin P. McCabe)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
HADOOP-11785. Reduce the number of listStatus operation in distcp
|
HADOOP-11785. Reduce the number of listStatus operation in distcp
|
||||||
|
|
|
@ -92,6 +92,9 @@ public class DomainSocket implements Closeable {
|
||||||
* misconfigurations. System administrators do not commonly change
|
* misconfigurations. System administrators do not commonly change
|
||||||
* permissions on these paths while the server is running.
|
* permissions on these paths while the server is running.
|
||||||
*
|
*
|
||||||
|
* For more information on Security exceptions see this wiki page:
|
||||||
|
* https://wiki.apache.org/hadoop/SocketPathSecurity
|
||||||
|
*
|
||||||
* @param path the path to validate
|
* @param path the path to validate
|
||||||
* @param skipComponents the number of starting path components to skip
|
* @param skipComponents the number of starting path components to skip
|
||||||
* validation for (used only for testing)
|
* validation for (used only for testing)
|
||||||
|
|
|
@ -268,7 +268,7 @@ Java_org_apache_hadoop_net_unix_DomainSocket_validateSocketPathSecurity0(
|
||||||
JNIEnv *env, jclass clazz, jobject jstr, jint skipComponents)
|
JNIEnv *env, jclass clazz, jobject jstr, jint skipComponents)
|
||||||
{
|
{
|
||||||
jint utfLength;
|
jint utfLength;
|
||||||
char path[PATH_MAX], check[PATH_MAX], *token, *rest;
|
char path[PATH_MAX], check[PATH_MAX], *token, *rest, *rest_free;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int ret, mode, strlenPath;
|
int ret, mode, strlenPath;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
@ -280,6 +280,7 @@ JNIEnv *env, jclass clazz, jobject jstr, jint skipComponents)
|
||||||
"no longer than %zd UTF-8 bytes.", (sizeof(path)-1));
|
"no longer than %zd UTF-8 bytes.", (sizeof(path)-1));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*env)->GetStringUTFRegion(env, jstr, 0, utfLength, path);
|
(*env)->GetStringUTFRegion(env, jstr, 0, utfLength, path);
|
||||||
path [ utfLength ] = 0;
|
path [ utfLength ] = 0;
|
||||||
jthr = (*env)->ExceptionOccurred(env);
|
jthr = (*env)->ExceptionOccurred(env);
|
||||||
|
@ -304,7 +305,16 @@ JNIEnv *env, jclass clazz, jobject jstr, jint skipComponents)
|
||||||
// last one. We don't validate the last component, since it's not supposed to
|
// last one. We don't validate the last component, since it's not supposed to
|
||||||
// be a directory. (If it is a directory, we will fail to create the socket
|
// be a directory. (If it is a directory, we will fail to create the socket
|
||||||
// later with EISDIR or similar.)
|
// later with EISDIR or similar.)
|
||||||
for (check[0] = '/', check[1] = '\0', rest = path, token = "";
|
rest=strdup(path);
|
||||||
|
if ( rest == NULL ){
|
||||||
|
ret = errno;
|
||||||
|
jthr = newIOException(env,"memory allocation failure trying to copy a path"
|
||||||
|
" with %d length. error code %d (%s). ", strlenPath, ret, terror(ret));
|
||||||
|
goto done;
|
||||||
|
};
|
||||||
|
rest_free=rest;
|
||||||
|
|
||||||
|
for (check[0] = '/', check[1] = '\0', token = "";
|
||||||
token && rest && rest[0];
|
token && rest && rest[0];
|
||||||
token = strtok_r(rest, "/", &rest)) {
|
token = strtok_r(rest, "/", &rest)) {
|
||||||
if (strcmp(check, "/") != 0) {
|
if (strcmp(check, "/") != 0) {
|
||||||
|
@ -322,36 +332,51 @@ JNIEnv *env, jclass clazz, jobject jstr, jint skipComponents)
|
||||||
}
|
}
|
||||||
if (stat(check, &st) < 0) {
|
if (stat(check, &st) < 0) {
|
||||||
ret = errno;
|
ret = errno;
|
||||||
jthr = newIOException(env, "failed to stat a path component: '%s'. "
|
jthr = newIOException(env, "failed to stat a path component: "
|
||||||
"error code %d (%s)", check, ret, terror(ret));
|
"'%s' in '%s'. error code %d (%s). "
|
||||||
|
"Ensure that the path is configured correctly.",
|
||||||
|
check, path, ret, terror(ret));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
mode = st.st_mode & 0777;
|
mode = st.st_mode & 0777;
|
||||||
if (mode & 0002) {
|
if (mode & 0002) {
|
||||||
jthr = newIOException(env, "the path component: '%s' is "
|
jthr = newIOException(env, "The path component: '%s' in '%s' has "
|
||||||
"world-writable. Its permissions are 0%03o. Please fix "
|
"permissions 0%03o uid %ld and gid %ld. "
|
||||||
"this or select a different socket path.", check, mode);
|
"It is not protected because it "
|
||||||
|
"is world-writable. This might help: 'chmod o-w %s'. "
|
||||||
|
"For more information: "
|
||||||
|
"https://wiki.apache.org/hadoop/SocketPathSecurity",
|
||||||
|
check, path, mode, (long long)st.st_uid, (long long)st.st_gid, check);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((mode & 0020) && (st.st_gid != 0)) {
|
if ((mode & 0020) && (st.st_gid != 0)) {
|
||||||
jthr = newIOException(env, "the path component: '%s' is "
|
jthr = newIOException(env, "The path component: '%s' in '%s' has "
|
||||||
"group-writable, and the group is not root. Its permissions are "
|
"permissions 0%03o uid %ld and gid %ld. "
|
||||||
"0%03o, and it is owned by gid %d. Please fix this or "
|
"It is not protected because it "
|
||||||
"select a different socket path.", check, mode, st.st_gid);
|
"is group-writable and not owned by root. "
|
||||||
|
"This might help: 'chmod g-w %s' or 'chown root %s'. "
|
||||||
|
"For more information: "
|
||||||
|
"https://wiki.apache.org/hadoop/SocketPathSecurity",
|
||||||
|
check, path, mode, (long long)st.st_uid, (long long)st.st_gid,
|
||||||
|
check, check);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((mode & 0200) && (st.st_uid != 0) &&
|
if ((mode & 0200) && (st.st_uid != 0) && (st.st_uid != uid)) {
|
||||||
(st.st_uid != uid)) {
|
jthr = newIOException(env, "The path component: '%s' in '%s' has "
|
||||||
jthr = newIOException(env, "the path component: '%s' is "
|
"permissions 0%03o uid %ld and gid %ld. "
|
||||||
"owned by a user who is not root and not you. Your effective user "
|
"It is not protected because it "
|
||||||
"id is %d; the path is owned by user id %d, and its permissions are "
|
"is owned by a user who is not root "
|
||||||
"0%03o. Please fix this or select a different socket path.",
|
"and not the effective user: '%ld'. "
|
||||||
check, uid, st.st_uid, mode);
|
"This might help: 'chown root %s' or 'chown %ld %s'. "
|
||||||
goto done;
|
"For more information: "
|
||||||
|
"https://wiki.apache.org/hadoop/SocketPathSecurity",
|
||||||
|
check, path, mode, (long long)st.st_uid, (long long)st.st_gid,
|
||||||
|
(long long)uid, check, (long long)uid, check);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
if ( rest_free ) free(rest_free);
|
||||||
if (jthr) {
|
if (jthr) {
|
||||||
(*env)->Throw(env, jthr);
|
(*env)->Throw(env, jthr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -712,9 +712,8 @@ public class TestDomainSocket {
|
||||||
try {
|
try {
|
||||||
testValidateSocketPath(prefix + "/foo/bar/baz", prefix);
|
testValidateSocketPath(prefix + "/foo/bar/baz", prefix);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
GenericTestUtils.assertExceptionContains("/foo' is world-writable. " +
|
GenericTestUtils.assertExceptionContains("world-writable" ,e);
|
||||||
"Its permissions are 0707. Please fix this or select a " +
|
GenericTestUtils.assertExceptionContains("/foo'" ,e);
|
||||||
"different socket path.", e);
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
testValidateSocketPath(prefix + "/nope", prefix);
|
testValidateSocketPath(prefix + "/nope", prefix);
|
||||||
|
@ -723,7 +722,7 @@ public class TestDomainSocket {
|
||||||
"component: ", e);
|
"component: ", e);
|
||||||
}
|
}
|
||||||
// Root should be secure
|
// Root should be secure
|
||||||
DomainSocket.validateSocketPathSecurity0("/foo", 1);
|
DomainSocket.validateSocketPathSecurity0("/foo", 0);
|
||||||
} finally {
|
} finally {
|
||||||
tmp.close();
|
tmp.close();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue