mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-23 21:29:28 +00:00
Fix New World NVRAM limits calculations.
It was possible to corrupt New World nvram using dingusppc setenv command. - setenv must call get_config_vars to set data_length so that it can calculate free space. - data_length represents the number of bytes taken by nvram variables including the terminating null for the value (name, '=', value, '\0'). Previously, it did not include the terminating null. - The list of variables and values ends at a '\0' or at pos == 4096 bytes. Previously, data_length wouldn't get set if pos >= 4096. - Allow setenv to create new nvram variables. - Since data_length now represents the total number of used bytes, free_space now represents the actual free space, so use > free_space (instead of >= free_space) to determine insufficient space. - While parsing nvram variable name, do not read beyond 4096 bytes. - Use a different error message for each problem that can occur while parsing nvram variable name.
This commit is contained in:
parent
07f57a1e9b
commit
439509b408
@ -391,27 +391,47 @@ const OfConfigImpl::config_dict& OfConfigChrp::get_config_vars() {
|
||||
|
||||
this->_config_vars.clear();
|
||||
|
||||
this->data_length = 0;
|
||||
|
||||
if (!this->validate())
|
||||
return _config_vars;
|
||||
|
||||
for (int pos = 0; pos < 4096;) {
|
||||
char *pname = (char *)&this->buf[pos];
|
||||
bool got_name = false;
|
||||
|
||||
// scan property name until '=' is encountered
|
||||
// or max length is reached
|
||||
for (len = 0; len < 32; pos++, len++) {
|
||||
if (pname[len] == '=' || pname[len] == '\0')
|
||||
for (len = 0; ; pos++, len++) {
|
||||
if (len >= 32) {
|
||||
cout << "name > 31 chars" << endl;
|
||||
break;
|
||||
}
|
||||
if (pos >= 4096) {
|
||||
cout << "no = sign before end of partition" << endl;
|
||||
break;
|
||||
}
|
||||
if (pname[len] == '=') {
|
||||
if (len) {
|
||||
got_name = true;
|
||||
}
|
||||
else {
|
||||
cout << "got = sign but no name" << endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (pname[len] == '\0') {
|
||||
if (len) {
|
||||
cout << "no = sign before termminating null" << endl;
|
||||
}
|
||||
else {
|
||||
// empty property name -> free space reached
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// empty property name -> free space reached
|
||||
if (!len) {
|
||||
this->data_length = pos;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pname[len] != '=') {
|
||||
cout << "no = sign found or name > 31 chars" << endl;
|
||||
if (!got_name) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -436,8 +456,11 @@ const OfConfigImpl::config_dict& OfConfigChrp::get_config_vars() {
|
||||
|
||||
this->_config_vars.push_back(std::make_pair(prop_name, pval));
|
||||
pos++; // skip past null terminator
|
||||
|
||||
this->data_length = pos; // point to after null
|
||||
}
|
||||
|
||||
//cout << "Read " << this->data_length << " bytes from nvram." << endl;
|
||||
return this->_config_vars;
|
||||
}
|
||||
|
||||
@ -447,7 +470,7 @@ bool OfConfigChrp::update_partition() {
|
||||
memset(this->buf, 0, 4096);
|
||||
|
||||
for (auto& var : this->_config_vars) {
|
||||
if ((var.first.length() + var.second.length() + 2) >= 4096) {
|
||||
if ((pos + var.first.length() + var.second.length() + 2) > 4096) {
|
||||
cout << "No room in the partition!" << endl;
|
||||
return false;
|
||||
}
|
||||
@ -464,6 +487,7 @@ bool OfConfigChrp::update_partition() {
|
||||
this->nvram_obj->write_byte(this->data_offset + i, this->buf[i]);
|
||||
}
|
||||
|
||||
//cout << "Wrote " << pos << " bytes to nvram." << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -471,25 +495,25 @@ bool OfConfigChrp::set_var(std::string& var_name, std::string& value) {
|
||||
if (!this->validate())
|
||||
return false;
|
||||
|
||||
bool found = false;
|
||||
// see if we're about to change a flag
|
||||
if (var_name.back() == '?') {
|
||||
if (value != "true" && value != "false") {
|
||||
cout << "Flag value can be 'true' or 'false'" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned free_space = 4096 - this->data_length;
|
||||
bool found = false;
|
||||
|
||||
// see if the user tries to change an existing property
|
||||
for (auto& var : this->_config_vars) {
|
||||
if (var.first == var_name) {
|
||||
found = true;
|
||||
|
||||
// see if we're about to change a flag
|
||||
if (var_name.back() == '?') {
|
||||
if (value != "true" && value != "false") {
|
||||
cout << "Flag value can be 'true' or 'false'" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (value.length() > var.second.length()) {
|
||||
unsigned free_space = 4096 - this->data_length;
|
||||
if ((value.length() - var.second.length()) >= free_space) {
|
||||
cout << "No room for new data!" << endl;
|
||||
if ((value.length() - var.second.length()) > free_space) {
|
||||
cout << "No room for updated nvram variable!" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -500,8 +524,11 @@ bool OfConfigChrp::set_var(std::string& var_name, std::string& value) {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
cout << "Attempt to change unknown variable " << var_name << endl;
|
||||
return false;
|
||||
if ((var_name.length() + value.length() + 2) > free_space) {
|
||||
cout << "No room for new nvram variable!" << endl;
|
||||
return false;
|
||||
}
|
||||
this->_config_vars.push_back(std::make_pair(var_name, value));
|
||||
}
|
||||
|
||||
return this->update_partition();
|
||||
@ -551,12 +578,10 @@ static std::string ReplaceAll(std::string& str, const std::string& from, const s
|
||||
}
|
||||
|
||||
void OfConfigUtils::printenv() {
|
||||
OfConfigImpl::config_dict vars;
|
||||
|
||||
if (!this->open_container())
|
||||
return;
|
||||
|
||||
vars = this->cfg_impl->get_config_vars();
|
||||
OfConfigImpl::config_dict vars = this->cfg_impl->get_config_vars();
|
||||
|
||||
for (auto& var : vars) {
|
||||
std::string val = var.second;
|
||||
@ -572,6 +597,8 @@ void OfConfigUtils::setenv(string var_name, string value)
|
||||
if (!this->open_container())
|
||||
return;
|
||||
|
||||
OfConfigImpl::config_dict vars = this->cfg_impl->get_config_vars();
|
||||
|
||||
if (!this->cfg_impl->set_var(var_name, value)) {
|
||||
cout << " Please try again" << endl;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user