Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/hotspot/share/jfr/dcmd/jfrDcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,9 @@ void JfrConfigureFlightRecorderDCmd::print_help(outputStream* out, bool startup)
out->print_cr(" The option redact-argument is best-effort and applies only to");
out->print_cr(" command-line arguments in the jdk.JVMInformation event and to");
out->print_cr(" the java.command system property in the jdk.InitialSystemProperty");
out->print_cr(" event. Other events, such as jdk.ProcessStart (child processes),");
out->print_cr(" are not redacted.");
out->print_cr(" event, and to matching command-line argument text in the values");
out->print_cr(" of jdk.InitialEnvironmentVariable events. Other events, such as");
out->print_cr(" jdk.ProcessStart (child processes), are not redacted.");
out->print_cr("");
out->print_cr(" If the redact-argument option is not specified, the following");
out->print_cr(" filters are used by default:");
Expand Down
176 changes: 137 additions & 39 deletions src/hotspot/share/jfr/periodic/jfrRedactedEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "logging/logMessage.hpp"
#include "runtime/arguments.hpp"
#include "runtime/flags/jvmFlag.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/os.hpp"
#include "runtime/vm_version.hpp"
#include "services/diagnosticArgument.hpp"
Expand All @@ -46,17 +47,20 @@ using StringFlag = JfrRedactedEvents::StringFlag;
using StringKeyValueArray = GrowableArray<JfrRedactedEvents::StringKeyValue*>*;

static const char REDACTED[] = "[REDACTED]";
static const char REDACTED_MARKER = (char)0xFF;
static const char DELIMITER[] = " ";
static const char REDACT_ARGUMENT[] = "redact-argument";
static const char REDACT_ARGUMENT_EQUAL[] = "redact-argument=";

static const size_t REDACTED_LENGTH = sizeof(REDACTED) -1;
static const size_t DELIMITER_LENGTH = sizeof(DELIMITER) -1;
static const size_t REDACT_ARGUMENT_EQUAL_LENGTH = sizeof(REDACT_ARGUMENT_EQUAL) -1;
static const size_t REDACT_ARGUMENT_LENGTH = sizeof(REDACT_ARGUMENT) -1;

String* JfrRedactedEvents::_redacted_java_command_line = nullptr;
String* JfrRedactedEvents::_redacted_jvm_command_line = nullptr;
String* JfrRedactedEvents::_redacted_flags_command_line = nullptr;
String* JfrRedactedEvents::_redacted_flight_recorder_options = nullptr;
String* JfrRedactedEvents::_redacted_flight_recorder_options_with_marker = nullptr;

StringKeyValueArray JfrRedactedEvents::_initial_environment_variables = nullptr;
StringKeyValueArray JfrRedactedEvents::_initial_system_properties = nullptr;
Expand All @@ -71,6 +75,10 @@ bool JfrRedactedEvents::_initialized = false;
bool JfrRedactedEvents::set_argument_filter(const char* filters) {
assert (_argument_filters == nullptr, "invariant");
assert (filters != nullptr, "invariant");
if (strcmp(filters, "*") != 0 && strcmp(filters, "none") != 0) {
_redacted_arguments = new StringArray();
_redacted_arguments->add(filters);
}
_argument_filters = new StringArray();
return append_filters(_argument_filters, true, filters);
}
Expand Down Expand Up @@ -139,9 +147,8 @@ bool JfrRedactedEvents::append_filters(StringArray* target, bool argument, const
}
if (filters[0] == '\0') {
LogMessage(jfr, redact) msg;
msg.warning("Default redaction filters are replaced. Specify:");
msg.warning("-XX:FlightRecorderOptions:%s=none to disable filters without a warning.", option_name);
return true;
msg.error("Specify -XX:FlightRecorderOptions:%s=none to disable filters completely.", option_name);
return false;
}
if (strcmp(filters, "none") == 0) {
return true;
Expand Down Expand Up @@ -187,6 +194,67 @@ char* JfrRedactedEvents::new_redacted_text() {
return result;
}

void JfrRedactedEvents::redact(String* scratch_string, const char* target, const String* redaction) {
if (strchr(redaction->text(), REDACTED_MARKER)) {
return;
}
const char* position = target;
while (true) {
const char* sensitive = strstr(position, redaction->text());
if (sensitive == nullptr) {
return;
}
size_t index = (size_t)(sensitive - target);
for (size_t i = 0; i < redaction->length(); i++) {
scratch_string->set(index + i, REDACTED_MARKER);
}
position = sensitive + 1;
}
}

String* JfrRedactedEvents::redact_environment_variable_value(const char* value) {
if (strchr(value, REDACTED_MARKER)) {
return new String(REDACTED);
}
bool changed = false;
String* input = new String(value);
if (_redacted_flight_recorder_options_with_marker != nullptr) {
size_t length = strlen(FlightRecorderOptions);
while (const char* start = strstr(input->text(), FlightRecorderOptions)) {
changed = true;
const char* end = start + length;
stringStream s;
s.write(input->text(), start - input->text());
s.write(_redacted_flight_recorder_options_with_marker->text(), _redacted_flight_recorder_options_with_marker->length());
s.write(end, strlen(end));
String* result = new String(s.base());
delete input;
input = result;
}
}
String* scratch_string = new String(input->text());
for (int i = 0; i < _redacted_arguments->length(); i++) {
redact(scratch_string, input->text(), _redacted_arguments->at(i));
}
stringStream result;
bool inside_redaction = false;
for (size_t i = 0; i < scratch_string->length(); i++) {
if (scratch_string->at(i) == REDACTED_MARKER) {
changed = true;
if (!inside_redaction) {
result.print(REDACTED);
}
inside_redaction = true;
} else {
result.put(scratch_string->at(i));
inside_redaction = false;
}
}
delete scratch_string;
delete input;
return changed ? new String(result.base()) : nullptr;
}

bool JfrRedactedEvents::emit_initial_environment_variables(bool log) {
if (_initial_environment_variables == nullptr) {
ensure_initialized();
Expand All @@ -207,6 +275,16 @@ bool JfrRedactedEvents::emit_initial_environment_variables(bool log) {
if (log) {
log_debug(jfr, redact)("Redacted initial environment variable named '%s'", key->text());
}
} else {
String* redacted_value = redact_environment_variable_value(value);
if (redacted_value != nullptr) {
if (log) {
log_debug(jfr, redact)("Redacted argument in initial environment variable value named '%s'", key->text());
}
_initial_environment_variables->append(new StringKeyValue(key, redacted_value->text()));
delete redacted_value;
continue;
}
}
_initial_environment_variables->append(new StringKeyValue(key, value));
}
Expand Down Expand Up @@ -262,6 +340,9 @@ bool JfrRedactedEvents::match_flag(const char* flag_name, const char* arg) {
if (flag_name == nullptr || arg == nullptr) {
return false;
}
if (strncmp(arg, "-XX:", 4) == 0) {
arg += 4;
}
while (*flag_name) {
if (*arg != *flag_name) {
return false;
Expand Down Expand Up @@ -346,6 +427,34 @@ void JfrRedactedEvents::emit_jvm_information(bool log) {
}
}

// Method assumes that FlightRecorderOptions has been successfully parsed during startup
String* JfrRedactedEvents::redact_flight_recorder_options(const char* option, bool marker) {
JavaThread* THREAD = JavaThread::current();
const size_t length = strlen(option);
DCmdArgIter iterator(option, length, ',');
while (iterator.next(THREAD)) {
if (strncmp(iterator.key_addr(), REDACT_ARGUMENT, REDACT_ARGUMENT_LENGTH) == 0) {
const char* start = iterator.value_addr();
const char* end = start + iterator.value_length();
stringStream result;
result.write(option, start - option);
if (marker) {
result.put(REDACTED_MARKER);
} else {
result.write(REDACTED, REDACTED_LENGTH);
}
result.write(end, option + length - end);
return new String(result.base());
}
}
if (HAS_PENDING_EXCEPTION) {
DEBUG_ONLY(ShouldNotReachHere();)
CLEAR_PENDING_EXCEPTION;
return new String(REDACTED);
}
return nullptr;
}

void JfrRedactedEvents::ensure_initialized() {
if (_initialized) {
return;
Expand All @@ -359,31 +468,12 @@ void JfrRedactedEvents::ensure_initialized() {
add_default_filters(_argument_filters, true);
}
if (FlightRecorderOptions != nullptr) {
if (strstr(FlightRecorderOptions, REDACT_ARGUMENT_EQUAL) != nullptr) {
DCmdIter iterator(FlightRecorderOptions, ',');
stringStream result;
size_t pos = 0;
while(iterator.has_next()) {
CmdLine line = iterator.next();
const char* start = line.cmd_addr();
if (strncmp(start, REDACT_ARGUMENT_EQUAL, REDACT_ARGUMENT_EQUAL_LENGTH) == 0) {
result.print(REDACT_ARGUMENT_EQUAL);
result.print(REDACTED);
// Preserve ',' if there are more tokens
pos = iterator.has_next() ? iterator.cursor() - 1 : iterator.cursor();
}
while (pos < iterator.cursor()) {
result.write(FlightRecorderOptions + pos, 1);
pos++;
}
}
_redacted_flight_recorder_options = new String(result.base());
} else {
_redacted_flight_recorder_options = new String(FlightRecorderOptions);
}
_redacted_flight_recorder_options = redact_flight_recorder_options(FlightRecorderOptions, false);
_redacted_flight_recorder_options_with_marker = redact_flight_recorder_options(FlightRecorderOptions, true);
}
if (_redacted_arguments == nullptr) {
_redacted_arguments = new StringArray();
}

_redacted_arguments = new StringArray();

StringArray* java_args = make_java_args_array();
_redacted_java_command_line = redact_command_line(java_args);
Expand All @@ -396,7 +486,6 @@ void JfrRedactedEvents::ensure_initialized() {
StringArray* flags_args = make_jvm_args_array(Arguments::jvm_flags_array(), Arguments::num_jvm_flags());
_redacted_flags_command_line = redact_command_line(flags_args);
delete flags_args;

_initialized = true;
}

Expand All @@ -422,8 +511,8 @@ String* JfrRedactedEvents::redact_command_line(StringArray* arguments) {
for (int j = arg_index; j < next_index; j++) {
result->add(REDACTED);
const char* arg = arguments->at(j)->text();
if (arg != nullptr && strncmp(arg, "-XX:", 4) == 0) {
_redacted_arguments->add(arg + 4);
if (arg != nullptr) {
_redacted_arguments->add(arg);
}
}
arg_index = next_index;
Expand Down Expand Up @@ -504,15 +593,23 @@ StringArray* JfrRedactedEvents::make_jvm_args_array(char** jvm_args_array, int a
return nullptr;
}
StringArray* result = new StringArray(array_length);
for(int i = 0; i < array_length; i++) {
for (int i = 0; i < array_length; i++) {
char* argument = jvm_args_array[i];
if (_redacted_flight_recorder_options != nullptr &&
strncmp(argument, "-XX:FlightRecorderOptions", 25) == 0) {
const char* text = _redacted_flight_recorder_options->text();
size_t length = _redacted_flight_recorder_options->length();
// Length must be at least 26 or the JVM will not start.
result->add(new String(argument, 26, text, length));
continue;
if (strncmp(argument, "-XX:FlightRecorderOptions", 25) == 0) {
size_t length = strlen(argument);
if (length > 25 &&
_redacted_flight_recorder_options != nullptr &&
strcmp(argument + 26, FlightRecorderOptions) == 0) {
const char* text = _redacted_flight_recorder_options->text();
// Length must be at least 26 or the JVM will not start.
result->add(new String(argument, 26, text, _redacted_flight_recorder_options->length()));
continue;
}
if (strstr(argument, REDACT_ARGUMENT_EQUAL) != nullptr) {
_redacted_arguments->add(argument);
result->add("-XX:FlightRecorderOptions:[REDACTED]");
continue;
}
}
if (strncmp(argument, "-D", 2) == 0) {
const char* key_start = argument + 2;
Expand All @@ -523,6 +620,7 @@ StringArray* JfrRedactedEvents::make_jvm_args_array(char** jvm_args_array, int a
bool redact = match_key(_key_filters, key_tmp->text());
delete key_tmp;
if (redact) {
_redacted_arguments->add(argument);
size_t unsensitive_length = (size_t)(eq - argument) + 1;
result->add(new String(argument, unsensitive_length, REDACTED, REDACTED_LENGTH));
continue;
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/jfr/periodic/jfrRedactedEvents.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ class JfrRedactedEvents: public AllStatic {
static String* _redacted_jvm_command_line;
static String* _redacted_flags_command_line;
static String* _redacted_flight_recorder_options;
static String* _redacted_flight_recorder_options_with_marker;
static GrowableArray<StringKeyValue*>* _initial_system_properties;
static GrowableArray<StringKeyValue*>* _initial_environment_variables;
static GrowableArray<StringFlag*>* _string_flags;
Expand All @@ -217,7 +218,10 @@ class JfrRedactedEvents: public AllStatic {
static int match_arguments(StringArray* filter_array, StringArray* arguments, int arg_index);
static bool match_key(StringArray* array, const char* text);
static bool read_file(StringArray* target, const char* filename);
static void redact(String* scratch_string, const char* target, const String* redaction);
static String* redact_flight_recorder_options(const char* option, bool marker);
static String* redact_command_line(StringArray* arguments);
static String* redact_environment_variable_value(const char* value);
static StringArray* split(const char* text, char separator);
};

Expand Down
17 changes: 11 additions & 6 deletions src/hotspot/share/opto/memnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3523,24 +3523,24 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* address = in(MemNode::Address);
Node* value = in(MemNode::ValueIn);
// Back-to-back stores to same address? Fold em up. Generally
// unsafe if I have intervening uses.
{
// unsafe if I have intervening uses. Also unsafe for masked or
// scatter vector stores as the wider store.
if (!this->is_StoreVector() || this->Opcode() == Op_StoreVector) {
Node* st = mem;
// If Store 'st' has more than one use, we cannot fold 'st' away.
// For example, 'st' might be the final state at a conditional
// return. Or, 'st' might be used by some node which is live at
// the same time 'st' is live, which might be unschedulable. So,
// require exactly ONE user until such time as we clone 'mem' for
// each of 'mem's uses (thus making the exactly-1-user-rule hold
// true).
while (st->is_Store() && st->outcnt() == 1) {
// true). Further, 'st' must be a contiguous store, otherwise
// memory_size does not make sense for measuring overlap.
while (st->is_Store() && st->outcnt() == 1 && (!st->is_StoreVector() || st->Opcode() == Op_StoreVector)) {
// Looking at a dead closed cycle of memory?
assert(st != st->in(MemNode::Memory), "dead loop in StoreNode::Ideal");
assert(Opcode() == st->Opcode() ||
st->Opcode() == Op_StoreVector ||
Opcode() == Op_StoreVector ||
st->Opcode() == Op_StoreVectorScatter ||
Opcode() == Op_StoreVectorScatter ||
phase->C->get_alias_index(adr_type()) == Compile::AliasIdxRaw ||
(Opcode() == Op_StoreL && st->Opcode() == Op_StoreI) || // expanded ClearArrayNode
(Opcode() == Op_StoreI && st->Opcode() == Op_StoreL) || // initialization by arraycopy
Expand All @@ -3549,6 +3549,11 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {

if (st->in(MemNode::Address)->eqv_uncast(address) &&
st->as_Store()->memory_size() <= this->memory_size()) {
assert(!is_predicated_vector() && !is_StoreVectorMasked() &&
!is_StoreVectorScatter() && !is_StoreVectorScatterMasked() &&
!st->is_predicated_vector() && !st->is_StoreVectorMasked() &&
!st->is_StoreVectorScatter() && !st->is_StoreVectorScatterMasked(),
"optimization only correct for full-width stores without holes");
Node* use = st->raw_out(0);
if (phase->is_IterGVN()) {
phase->is_IterGVN()->rehash_node_delayed(use);
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/parse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ class Parse : public GraphKit {
// Helper: Merge the current mapping into the given basic block
void merge_common(Block* target, int pnum);
// Helper functions for merging individual cells.
Node* maybe_narrow_phi_input(Node* ctrl, Node* n, const Type* phi_type);
PhiNode *ensure_phi( int idx, bool nocreate = false);
PhiNode *ensure_memory_phi(int idx, bool nocreate = false);
// Helper to merge the current memory state into the given basic block
Expand Down
Loading
Loading