diff --git a/checkin_notes b/checkin_notes index aad63ebc8a..a7ab64e63c 100755 --- a/checkin_notes +++ b/checkin_notes @@ -8190,3 +8190,39 @@ David 6 Dec 2003 sched/ main.C start + +David 7 Dec 2003 + - Fixed bugs involving buffer overflow of BLOB fields. + These can be up to 65536 bytes in MySQL. + MAX_BLOB_SIZE was defined as 4K. + strcpy2() didn't do any buffer size checking. + A team description was over 8K long. + This caused db_dump to crash. + Solution: + - strcpy2() now defined as a macro that uses the sizeof() + its destination, and doesn't overwrite it. + - MAX_BLOB_SIZE replaced with 2 symbols: + MEDIUM_BLOB_SIZE for fields used by BOINC + defined as 4K so as to not increase shmem usage + LARGE_BLOB_SIZE for fields with user-supplied text + defined as 64K + + db/ + boinc_db.h + db_base.C,h + html_user/ + result.inc + white.css + sched/ + assimilator.C + db_dump.C + file_deleter.C + handle_request.C + make_work.C + server_types.C + transitioner.C + tools/ + add.C + backend_lib.C + create_work.C + process_result_template.C diff --git a/db/boinc_db.h b/db/boinc_db.h index 9ec0edb427..e2a5041188 100755 --- a/db/boinc_db.h +++ b/db/boinc_db.h @@ -33,9 +33,13 @@ extern DB_CONN boinc_db; -// Maximum allowed size for SQL based blobs (Binary Large Object) -// -#define MAX_BLOB_SIZE 4096 +// Sizes of text buffers in memory, corresponding to database BLOBs. +// Medium is for XML fields used by BOINC; +// this has to be kept small to reduce shared mem usage. +// Large is for fields with user-supplied text, and preferences + +#define MEDIUM_BLOB_SIZE 4096 +#define LARGE_BLOB_SIZE 65536 // represents the project as a whole. // There is only of these per DB @@ -69,7 +73,7 @@ struct CORE_VERSION { int create_time; int version_num; int platformid; - char xml_doc[MAX_BLOB_SIZE]; // a for the download file + char xml_doc[MEDIUM_BLOB_SIZE]; // a for the download file char message[256]; // if we get a request from this version, // send this message bool deprecated; // if we get a request from this version, @@ -97,7 +101,7 @@ struct APP_VERSION { int appid; int version_num; int platformid; - char xml_doc[MAX_BLOB_SIZE]; + char xml_doc[MEDIUM_BLOB_SIZE]; // describes app files. format: // ... // ... @@ -133,9 +137,9 @@ struct USER { double total_credit; double expavg_credit; // credit per second, recent average double expavg_time; // when the above was computed - char global_prefs[MAX_BLOB_SIZE]; + char global_prefs[LARGE_BLOB_SIZE]; // global preferences, within tag - char project_prefs[MAX_BLOB_SIZE]; + char project_prefs[LARGE_BLOB_SIZE]; // project preferences; format: // // X @@ -184,7 +188,7 @@ struct TEAM { char url[256]; int type; // Team type (see above) char name_html[256]; - char description[MAX_BLOB_SIZE]; + char description[LARGE_BLOB_SIZE]; int nusers; // UNDEFINED BY DEFAULT char country[256]; double total_credit; // UNDEFINED BY DEFAULT @@ -254,7 +258,7 @@ struct HOST { double credit_per_cpu_sec; char venue[256]; // home/work/school - char projects[MAX_BLOB_SIZE]; + char projects[MEDIUM_BLOB_SIZE]; // list of projects this host is attached to, // and the resource shares (XML) @@ -292,7 +296,7 @@ struct WORKUNIT { int create_time; int appid; // associated app char name[256]; - char xml_doc[MAX_BLOB_SIZE]; + char xml_doc[MEDIUM_BLOB_SIZE]; int batch; double rsc_fpops_est; // estimated # of FP operations // used to estimate how long a result will take on a host @@ -330,7 +334,7 @@ struct WORKUNIT { // (need this in case results never returned int max_success_results; // WU error if < #success results // without consensus (i.e. WU is nondeterministic) - char result_template[MAX_BLOB_SIZE]; + char result_template[MEDIUM_BLOB_SIZE]; // the following not used in the DB char app_name[256]; @@ -381,9 +385,9 @@ struct RESULT { int received_time; // when result was received from host char name[256]; double cpu_time; // CPU time used to complete result - char xml_doc_in[MAX_BLOB_SIZE]; // descriptions of output files - char xml_doc_out[MAX_BLOB_SIZE]; // MD5s of output files - char stderr_out[MAX_BLOB_SIZE]; // stderr output, if any + char xml_doc_in[MEDIUM_BLOB_SIZE]; // descriptions of output files + char xml_doc_out[MEDIUM_BLOB_SIZE]; // MD5s of output files + char stderr_out[MEDIUM_BLOB_SIZE]; // stderr output, if any int batch; int file_delete_state; int validate_state; diff --git a/db/db_base.C b/db/db_base.C index 8b59d47748..9547de7f9f 100644 --- a/db/db_base.C +++ b/db/db_base.C @@ -197,10 +197,12 @@ int DB_BASE::sum(double& x, char* field, char* clause) { return get_double(query, x); } +#if 0 void strcpy2(char* dest, char* src) { if (!src) *dest = 0; else strcpy(dest, src); } +#endif // convert ' to \' in place void escape_single_quotes(char* field) { diff --git a/db/db_base.h b/db/db_base.h index 8f182168f1..c11f4420eb 100644 --- a/db/db_base.h +++ b/db/db_base.h @@ -65,7 +65,16 @@ public: virtual void db_parse(MYSQL_ROW&); }; -void strcpy2(char* dest, char* src); +#define strcpy2(x, y) \ + { \ + char* z = y; \ + if (!z) { \ + x[0]=0; \ + } else { \ + strlcpy(x, z, sizeof(x)); \ + } \ + } +//void strcpy2(char* dest, char* src); void escape_single_quotes(char* field); void unescape_single_quotes(char* p); diff --git a/html/user/result.inc b/html/user/result.inc index 7ea1de17c6..7a6022116c 100644 --- a/html/user/result.inc +++ b/html/user/result.inc @@ -56,13 +56,13 @@ function result_table_start($show_wu_link, $show_host_link) { Sent Received Server state -
Explain +
explain Outcome -
Explain +
explain Client state -
Explain +
explain CPU time (sec) claimed credit @@ -84,7 +84,11 @@ function show_result_row($result, $show_wu_link, $show_host_link) { echo "workunitid>$result->workunitid\n"; } if ($show_host_link) { - echo "hostid>$result->hostid\n"; + if ($result->hostid) { + echo "hostid>$result->hostid\n"; + } else { + echo "---\n"; + } } $result_claimed_credit = format_credit($result->claimed_credit); $result_granted_credit = format_credit($result->granted_credit); diff --git a/html/user/white.css b/html/user/white.css index b5809d7c68..728977bc36 100644 --- a/html/user/white.css +++ b/html/user/white.css @@ -29,14 +29,12 @@ table.bordered { } th { - border-bottom: 2px solid white; background-color: ffffcc; font-weight: bold; } td { border: 1px solid white; - } td.bordered { diff --git a/sched/assimilator.C b/sched/assimilator.C index 4e6487bfee..8a4889dd0a 100644 --- a/sched/assimilator.C +++ b/sched/assimilator.C @@ -42,7 +42,7 @@ bool do_pass(APP& app) { DB_WORKUNIT wu; DB_RESULT canonical_result, result; bool did_something = false; - char buf[MAX_BLOB_SIZE]; + char buf[MEDIUM_BLOB_SIZE]; check_stop_trigger(); diff --git a/sched/db_dump.C b/sched/db_dump.C index 9e2351da06..1470a6ed93 100644 --- a/sched/db_dump.C +++ b/sched/db_dump.C @@ -286,7 +286,7 @@ void write_user(USER& user, FILE* f, bool detail, bool show_team) { void write_team(TEAM& team, FILE* f, bool detail) { DB_USER user; - char buf[MAX_BLOB_SIZE*2]; + char buf[256]; string name; xml_escape(team.name, name); diff --git a/sched/file_deleter.C b/sched/file_deleter.C index b7a3223cd5..0571e3ffd1 100644 --- a/sched/file_deleter.C +++ b/sched/file_deleter.C @@ -38,7 +38,7 @@ SCHED_CONFIG config; int wu_delete_files(WORKUNIT& wu) { char* p; - char filename[256], pathname[256], buf[MAX_BLOB_SIZE]; + char filename[256], pathname[256], buf[MEDIUM_BLOB_SIZE]; bool no_delete=false; int count_deleted = 0; @@ -69,7 +69,7 @@ int wu_delete_files(WORKUNIT& wu) { int result_delete_files(RESULT& result) { char* p; - char filename[256], pathname[256], buf[MAX_BLOB_SIZE]; + char filename[256], pathname[256], buf[MEDIUM_BLOB_SIZE]; bool no_delete=false; int count_deleted = 0, retval; diff --git a/sched/handle_request.C b/sched/handle_request.C index 1b328cd419..24aac1a4db 100644 --- a/sched/handle_request.C +++ b/sched/handle_request.C @@ -168,9 +168,9 @@ bool wu_is_feasible(WORKUNIT& wu, HOST& host, WORK_REQ& wreq) { // int insert_after(char* buffer, char* after, char* text) { char* p; - char temp[MAX_BLOB_SIZE]; + char temp[MEDIUM_BLOB_SIZE]; - if (strlen(buffer) + strlen(text) > MAX_BLOB_SIZE-1) { + if (strlen(buffer) + strlen(text) > MEDIUM_BLOB_SIZE-1) { log_messages.printf(SchedMessages::NORMAL, "insert_after: overflow\n"); return ERR_BUFFER_OVERFLOW; } @@ -190,7 +190,7 @@ int insert_after(char* buffer, char* after, char* text) { // it to a client // int insert_wu_tags(WORKUNIT& wu, APP& app) { - char buf[MAX_BLOB_SIZE]; + char buf[MEDIUM_BLOB_SIZE]; sprintf(buf, " %f\n" diff --git a/sched/make_work.C b/sched/make_work.C index 7b961f5480..211cfba845 100644 --- a/sched/make_work.C +++ b/sched/make_work.C @@ -67,7 +67,7 @@ char wu_name[256], result_template_file[256]; void replace_file_name( char* xml_doc, char* filename, char* new_filename, char* download_url ) { - char buf[MAX_BLOB_SIZE], temp[256], download_path[256], + char buf[MEDIUM_BLOB_SIZE], temp[256], download_path[256], new_download_path[256]; char * p; @@ -119,10 +119,10 @@ void make_work() { SCHED_CONFIG config; char * p; int retval, start_time=time(0); - char keypath[256], result_template[MAX_BLOB_SIZE]; - char file_name[256], buf[MAX_BLOB_SIZE], pathname[256]; + char keypath[256], result_template[MEDIUM_BLOB_SIZE]; + char file_name[256], buf[MEDIUM_BLOB_SIZE], pathname[256]; char new_file_name[256], new_pathname[256], command[256]; - char starting_xml[MAX_BLOB_SIZE], new_buf[MAX_BLOB_SIZE]; + char starting_xml[MEDIUM_BLOB_SIZE], new_buf[MEDIUM_BLOB_SIZE]; R_RSA_PRIVATE_KEY key; DB_WORKUNIT wu; int seqno = 0; diff --git a/sched/server_types.h b/sched/server_types.h index bde41172f8..89a3a4b21e 100644 --- a/sched/server_types.h +++ b/sched/server_types.h @@ -34,9 +34,9 @@ struct SCHEDULER_REQUEST { int core_client_minor_version; int rpc_seqno; int work_req_seconds; - char global_prefs_xml[MAX_BLOB_SIZE]; - char projects_xml[MAX_BLOB_SIZE]; - char code_sign_key[MAX_BLOB_SIZE]; + char global_prefs_xml[LARGE_BLOB_SIZE]; + char projects_xml[MEDIUM_BLOB_SIZE]; + char code_sign_key[MEDIUM_BLOB_SIZE]; double total_disk_usage; double project_disk_usage; @@ -68,8 +68,8 @@ struct SCHEDULER_REPLY { vectorwus; vectorresults; vectorresult_acks; - char code_sign_key[MAX_BLOB_SIZE]; - char code_sign_key_signature[MAX_BLOB_SIZE]; + char code_sign_key[MEDIUM_BLOB_SIZE]; + char code_sign_key_signature[MEDIUM_BLOB_SIZE]; SCHEDULER_REPLY(); ~SCHEDULER_REPLY(); diff --git a/sched/transitioner.C b/sched/transitioner.C index a959bbd297..cbc3e71e41 100644 --- a/sched/transitioner.C +++ b/sched/transitioner.C @@ -52,7 +52,7 @@ void handle_wu(DB_WORKUNIT& wu) { DB_RESULT* p_canonical_result = NULL; int nerrors, retval, ninprogress, nsuccess; int nunsent, ncouldnt_send, nover; - char suffix[256], result_template[MAX_BLOB_SIZE]; + char suffix[256], result_template[MEDIUM_BLOB_SIZE]; time_t now = time(0), x; bool all_over, have_result_to_validate, do_delete; diff --git a/tools/add.C b/tools/add.C index 6800ef3f62..8cd8a24d38 100644 --- a/tools/add.C +++ b/tools/add.C @@ -160,7 +160,7 @@ int sign_executable(char* path, char* signature_text) { static int process_executable_file( char* filename, char* signature_text, char* xml_doc ) { - char longbuf[MAX_BLOB_SIZE]; + char longbuf[MEDIUM_BLOB_SIZE]; char path[256]; sprintf(path, "%s/%s", exec_dir, filename); @@ -243,7 +243,7 @@ void add_core_version() { void add_app_version() { char path[256]; - char longbuf[MAX_BLOB_SIZE]; + char longbuf[MEDIUM_BLOB_SIZE]; char signature_text[1024]; int i; DB_APP app; diff --git a/tools/backend_lib.C b/tools/backend_lib.C index b407e63474..3052606671 100644 --- a/tools/backend_lib.C +++ b/tools/backend_lib.C @@ -33,7 +33,7 @@ int read_file(FILE* f, char* buf) { assert(f); assert(buf); - int n = fread(buf, 1, MAX_BLOB_SIZE, f); + int n = fread(buf, 1, MEDIUM_BLOB_SIZE, f); buf[n] = 0; return 0; } @@ -58,7 +58,7 @@ static int process_wu_template( const char* upload_url, const char* download_url ) { char* p; - char buf[MAX_BLOB_SIZE], md5[33], path[256]; + char buf[MEDIUM_BLOB_SIZE], md5[33], path[256]; int retval, file_number; double nbytes; char open_name[256]; @@ -154,7 +154,7 @@ int create_result( ) { DB_RESULT result; char base_outfile_name[256]; - char result_template_copy[MAX_BLOB_SIZE]; + char result_template_copy[MEDIUM_BLOB_SIZE]; int retval; result.clear(); @@ -210,8 +210,8 @@ int create_work( const char* upload_url, const char* download_url ) { int retval; - char _result_template[MAX_BLOB_SIZE]; - char wu_template[MAX_BLOB_SIZE]; + char _result_template[MEDIUM_BLOB_SIZE]; + char wu_template[MEDIUM_BLOB_SIZE]; #if 0 retval = check_files(infiles, ninfiles, download_dir); diff --git a/tools/create_work.C b/tools/create_work.C index 9bf1ca65f7..a73a46f67c 100644 --- a/tools/create_work.C +++ b/tools/create_work.C @@ -62,7 +62,7 @@ int main(int argc, char** argv) { DB_APP app; DB_WORKUNIT wu; int retval; - char wu_template[MAX_BLOB_SIZE]; + char wu_template[MEDIUM_BLOB_SIZE]; char wu_template_file[256], result_template_file[256]; char keyfile[256]; char** infiles = NULL; diff --git a/tools/process_result_template.C b/tools/process_result_template.C index 73c9459fab..b8bd73777a 100644 --- a/tools/process_result_template.C +++ b/tools/process_result_template.C @@ -36,7 +36,7 @@ int generate_signature( ) { DATA_BLOCK block, signature; unsigned char signature_buf[SIGNATURE_SIZE_BINARY]; - char buf[MAX_BLOB_SIZE]; + char buf[MEDIUM_BLOB_SIZE]; int retval; block.data = (unsigned char*)signed_xml; @@ -60,8 +60,8 @@ int generate_signature( // add a signature of its contents up to that point. // int add_signatures(char* xml, R_RSA_PRIVATE_KEY& key) { - char* p = xml, *q1, *q2, buf[MAX_BLOB_SIZE], buf2[MAX_BLOB_SIZE];; - char signature[MAX_BLOB_SIZE]; + char* p = xml, *q1, *q2, buf[MEDIUM_BLOB_SIZE], buf2[MEDIUM_BLOB_SIZE];; + char signature[MEDIUM_BLOB_SIZE]; int retval, len; while (1) { @@ -116,7 +116,7 @@ int process_result_template( char* upload_url ) { char* p,*q; - char temp[MAX_BLOB_SIZE]; + char temp[MEDIUM_BLOB_SIZE]; char num; int i; @@ -151,7 +151,7 @@ int process_result_template_upload_url_only( const char* upload_url ) { char *p; - char temp[MAX_BLOB_SIZE]; + char temp[MEDIUM_BLOB_SIZE]; while (1) { p = strstr(result_template, UPLOAD_URL_MACRO);