From 081e51151efc7976f578692ee9fc23df14b35a6e Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 26 Jun 2024 18:15:55 +0100 Subject: [PATCH 01/14] status: Constify a bunch of local variables This is yet more missed constification, due in this case to me searching for 'static nxt_str_t ' but these only having a single space after the type... Anyway no problem, this can be a preparatory patch for adding further /status information... Signed-off-by: Andrew Clayton --- src/nxt_status.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/nxt_status.c b/src/nxt_status.c index f8002e86e..0635f0b2b 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -17,17 +17,17 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) nxt_status_app_t *app; nxt_conf_value_t *status, *obj, *apps, *app_obj; - static nxt_str_t conns_str = nxt_string("connections"); - static nxt_str_t acc_str = nxt_string("accepted"); - static nxt_str_t active_str = nxt_string("active"); - static nxt_str_t idle_str = nxt_string("idle"); - static nxt_str_t closed_str = nxt_string("closed"); - static nxt_str_t reqs_str = nxt_string("requests"); - static nxt_str_t total_str = nxt_string("total"); - static nxt_str_t apps_str = nxt_string("applications"); - static nxt_str_t procs_str = nxt_string("processes"); - static nxt_str_t run_str = nxt_string("running"); - static nxt_str_t start_str = nxt_string("starting"); + static const nxt_str_t conns_str = nxt_string("connections"); + static const nxt_str_t acc_str = nxt_string("accepted"); + static const nxt_str_t active_str = nxt_string("active"); + static const nxt_str_t idle_str = nxt_string("idle"); + static const nxt_str_t closed_str = nxt_string("closed"); + static const nxt_str_t reqs_str = nxt_string("requests"); + static const nxt_str_t total_str = nxt_string("total"); + static const nxt_str_t apps_str = nxt_string("applications"); + static const nxt_str_t procs_str = nxt_string("processes"); + static const nxt_str_t run_str = nxt_string("running"); + static const nxt_str_t start_str = nxt_string("starting"); status = nxt_conf_create_object(mp, 3); if (nxt_slow_path(status == NULL)) { From c8d70c3ff28bcf18dfbcfa1332ce0f0d869c0d5f Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 26 Jun 2024 23:52:43 +0100 Subject: [PATCH 02/14] status: Use a variable to represent the status member index In nxt_status_get() call nxt_conf_set_member() multiple times to set the main /status json sections. Previously this used hard coded values, 0, 1, 2 etc, if you wanted to change the order or insert new sections it could mean renumbering all these. Instead use a variable to track this index which starts at 0 and is simply incremented in each call of nxt_conf_set_member(). Currently this is only for the main outer sections, but can be replicated for inner sections if required. This is a preparatory patch for adding a new "modules" section at the top. Signed-off-by: Andrew Clayton --- src/nxt_status.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/nxt_status.c b/src/nxt_status.c index 0635f0b2b..957bc34e8 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -12,6 +12,7 @@ nxt_conf_value_t * nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) { size_t i; + uint32_t idx = 0; nxt_str_t name; nxt_int_t ret; nxt_status_app_t *app; @@ -39,7 +40,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) return NULL; } - nxt_conf_set_member(status, &conns_str, obj, 0); + nxt_conf_set_member(status, &conns_str, obj, idx++); nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0); nxt_conf_set_member_integer(obj, &active_str, report->accepted_conns @@ -53,7 +54,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) return NULL; } - nxt_conf_set_member(status, &reqs_str, obj, 1); + nxt_conf_set_member(status, &reqs_str, obj, idx++); nxt_conf_set_member_integer(obj, &total_str, report->requests, 0); @@ -62,7 +63,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) return NULL; } - nxt_conf_set_member(status, &apps_str, apps, 2); + nxt_conf_set_member(status, &apps_str, apps, idx++); for (i = 0; i < report->apps_count; i++) { app = &report->apps[i]; From 55041ef9607c073bc5e1b431ec271e9c23200cb1 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 4 Jul 2024 15:52:56 +0100 Subject: [PATCH 03/14] Flow the language module name into nxt_app_lang_module_t The nxt_app_lang_module_t structure contains various bits of information as obtained from the nxt_app_module_t structure that language modules define. One bit of information that is in the nxt_app_module_t but not in the nxt_app_lang_module_t is the language module name. Having this name flowed through will be useful for displaying the loaded language modules in the /status endpoint. Signed-off-by: Andrew Clayton --- src/nxt_application.c | 15 ++++++++++++--- src/nxt_application.h | 1 + src/nxt_main_process.c | 6 ++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/nxt_application.c b/src/nxt_application.c index e0247bf08..629aa11c4 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -32,6 +32,7 @@ typedef struct { nxt_app_type_t type; + nxt_str_t name; nxt_str_t version; nxt_str_t file; nxt_array_t *mounts; @@ -257,12 +258,14 @@ nxt_discovery_modules(nxt_task_t *task, const char *path) module[i].type, &module[i].version, &module[i].file); size += nxt_length("{\"type\": ,"); + size += nxt_length(" \"name\": \"\","); size += nxt_length(" \"version\": \"\","); size += nxt_length(" \"file\": \"\","); size += nxt_length(" \"mounts\": []},"); size += NXT_INT_T_LEN + module[i].version.length + + module[i].name.length + module[i].file.length; mounts = module[i].mounts; @@ -294,9 +297,10 @@ nxt_discovery_modules(nxt_task_t *task, const char *path) for (i = 0; i < n; i++) { mounts = module[i].mounts; - p = nxt_sprintf(p, end, "{\"type\": %d, \"version\": \"%V\", " - "\"file\": \"%V\", \"mounts\": [", - module[i].type, &module[i].version, &module[i].file); + p = nxt_sprintf(p, end, "{\"type\": %d, \"name\": \"%V\", " + "\"version\": \"%V\", \"file\": \"%V\", \"mounts\": [", + module[i].type, &module[i].name, &module[i].version, + &module[i].file); mnt = mounts->elts; for (j = 0; j < mounts->nelts; j++) { @@ -412,6 +416,11 @@ nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, goto fail; } + nxt_str_dup(mp, &module->name, &app->type); + if (module->name.start == NULL) { + goto fail; + } + module->file.length = nxt_strlen(name); module->file.start = nxt_mp_alloc(mp, module->file.length); diff --git a/src/nxt_application.h b/src/nxt_application.h index f5d7a9df3..a3b4230a0 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -35,6 +35,7 @@ typedef nxt_int_t (*nxt_application_setup_t)(nxt_task_t *task, typedef struct { nxt_app_type_t type; + char *name; u_char *version; char *file; nxt_app_module_t *module; diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index c302cb02f..00318226b 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -1354,6 +1354,12 @@ static nxt_conf_map_t nxt_app_lang_module_map[] = { offsetof(nxt_app_lang_module_t, type), }, + { + nxt_string("name"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_app_lang_module_t, name), + }, + { nxt_string("version"), NXT_CONF_MAP_CSTRZ, From 707f4ef821f82eb772728f687e41afc9d6945f98 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Fri, 28 Jun 2024 21:09:37 +0100 Subject: [PATCH 04/14] status: Show list of loaded language modules When querying the '/status' node in the control API, display the list of currently loaded modules. So we now get something like { "modules": { "python": [ { "version": "3.12.3", "lib": "/opt/unit/modules/python.unit.so" }, { "version": "3.12.1", "lib": "/opt/unit/modules/python-3.12.1.unit.so" } ], "wasm": { "version": "0.1", "lib": "/opt/unit/modules/wasm.unit.so" }, "wasm-wasi-component": { "version": "0.1", "lib": "/opt/unit/modules/wasm_wasi_component.unit.so" } }, ... } This can be useful for debugging to show exactly what modules Unit has loaded _and_ from where. Closes: https://github.com/nginx/unit/issues/1343 Signed-off-by: Andrew Clayton --- src/nxt_status.c | 102 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 8 deletions(-) diff --git a/src/nxt_status.c b/src/nxt_status.c index 957bc34e8..b48ec743b 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -6,18 +6,27 @@ #include #include #include +#include nxt_conf_value_t * nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) { - size_t i; - uint32_t idx = 0; - nxt_str_t name; - nxt_int_t ret; - nxt_status_app_t *app; - nxt_conf_value_t *status, *obj, *apps, *app_obj; - + size_t i, nr_langs; + uint16_t lang_cnts[NXT_APP_UNKNOWN] = { 1 }; + uint32_t idx = 0; + nxt_str_t name; + nxt_int_t ret; + nxt_array_t *langs; + nxt_thread_t *thr; + nxt_app_type_t type, prev_type; + nxt_status_app_t *app; + nxt_conf_value_t *status, *obj, *mods, *apps, *app_obj, *mod_obj; + nxt_app_lang_module_t *modules; + + static const nxt_str_t modules_str = nxt_string("modules"); + static const nxt_str_t version_str = nxt_string("version"); + static const nxt_str_t lib_str = nxt_string("lib"); static const nxt_str_t conns_str = nxt_string("connections"); static const nxt_str_t acc_str = nxt_string("accepted"); static const nxt_str_t active_str = nxt_string("active"); @@ -30,11 +39,88 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) static const nxt_str_t run_str = nxt_string("running"); static const nxt_str_t start_str = nxt_string("starting"); - status = nxt_conf_create_object(mp, 3); + status = nxt_conf_create_object(mp, 4); if (nxt_slow_path(status == NULL)) { return NULL; } + thr = nxt_thread(); + langs = thr->runtime->languages; + + modules = langs->elts; + /* + * We need to count the number of unique languages to correctly + * allocate the below mods object. + * + * We also need to count how many of each language. + * + * Start by skipping past NXT_APP_EXTERNAL which is always the + * first entry. + */ + for (i = 1, nr_langs = 0, prev_type = NXT_APP_UNKNOWN; i < langs->nelts; + i++) + { + type = modules[i].type; + + lang_cnts[type]++; + + if (type == prev_type) { + continue; + } + + nr_langs++; + prev_type = type; + } + + mods = nxt_conf_create_object(mp, nr_langs); + if (nxt_slow_path(mods == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &modules_str, mods, idx++); + + i = 1; + obj = mod_obj = NULL; + prev_type = NXT_APP_UNKNOWN; + for (size_t l = 0, a = 0; i < langs->nelts; i++) { + nxt_str_t item, mod_name; + + type = modules[i].type; + if (type != prev_type) { + a = 0; + + if (lang_cnts[type] == 1) { + mod_obj = nxt_conf_create_object(mp, 2); + obj = mod_obj; + } else { + mod_obj = nxt_conf_create_array(mp, lang_cnts[type]); + } + + if (nxt_slow_path(mod_obj == NULL)) { + return NULL; + } + + mod_name.start = (u_char *)modules[i].name; + mod_name.length = strlen(modules[i].name); + nxt_conf_set_member(mods, &mod_name, mod_obj, l++); + } + + if (lang_cnts[type] > 1) { + obj = nxt_conf_create_object(mp, 2); + nxt_conf_set_element(mod_obj, a++, obj); + } + + item.start = modules[i].version; + item.length = nxt_strlen(modules[i].version); + nxt_conf_set_member_string(obj, &version_str, &item, 0); + + item.start = (u_char *)modules[i].file; + item.length = strlen(modules[i].file); + nxt_conf_set_member_string(obj, &lib_str, &item, 1); + + prev_type = type; + } + obj = nxt_conf_create_object(mp, 4); if (nxt_slow_path(obj == NULL)) { return NULL; From f4ba4b5583cef182ad29cc158e8b1e2965b09829 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 3 Jul 2024 17:43:20 +0100 Subject: [PATCH 05/14] tests: Fix `/status' endpoint tests for new 'modules' section Now that the `/status` endpoint returns a list of loaded language modules, e.g { "modules": { "python": { "version": "3.12.2", "lib": "/opt/unit/modules/python.unit.so" }, ... ... } This broke 'test/test_status.py' in a number of ways 1) The check for all the object values being 0 at startup is no longer true with the modules section. 2) The find_diffs() check broke trying to subtract strings from strings. So don't include the 'modules' section in the check_zeros() check and in the find_diffs() check, if we're dealing with strings do a basic compare returning that value instead. [ Commit message - Andrew ] Co-developed-by: Andrew Clayton Signed-off-by: Andrew Clayton --- test/unit/status.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/unit/status.py b/test/unit/status.py index 95096a96f..d8bb4e41e 100644 --- a/test/unit/status.py +++ b/test/unit/status.py @@ -6,16 +6,16 @@ class Status: control = Control() def _check_zeros(): - assert Status.control.conf_get('/status') == { - 'connections': { + status = Status.control.conf_get('/status') + + assert status['connections'] == { 'accepted': 0, 'active': 0, 'idle': 0, 'closed': 0, - }, - 'requests': {'total': 0}, - 'applications': {}, } + assert status['requests'] == {'total': 0} + assert status['applications'] == {} def init(status=None): Status._status = ( @@ -31,6 +31,9 @@ def find_diffs(d1, d2): if k in d2 } + if isinstance(d1, str): + return d1 == d2 + return d1 - d2 return find_diffs(Status.control.conf_get('/status'), Status._status) From ebb10b0ad3fc120b5ad219f9155c80311693f5af Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Fri, 12 Jul 2024 00:49:28 +0100 Subject: [PATCH 06/14] Fix a comment typo for 'Memory-only buffers' in src/nxt_buf.h As the comment for 'Memory-only buffers' says "... it is equal to offsetof(nxt_buf_t, file.pos)" and "... that is it is nxt_buf_t without file and mmap part" Those are at odds with each other, 'file.pos' comes _after_ 'file' in the nxt_buf_t structure. Fix the 'offset()' bit of the comment to reflect that and to match the relevant macro #define NXT_BUF_MEM_SIZE offsetof(nxt_buf_t, file) Signed-off-by: Andrew Clayton --- src/nxt_buf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_buf.h b/src/nxt_buf.h index f1e2879f2..a561ef4e1 100644 --- a/src/nxt_buf.h +++ b/src/nxt_buf.h @@ -13,7 +13,7 @@ * should be allocated by appropriate nxt_buf_XXX_alloc() function. * * 1) Memory-only buffers, their size is less than nxt_buf_t size, it - * is equal to offsetof(nxt_buf_t, file_pos), that is it is nxt_buf_t + * is equal to offsetof(nxt_buf_t, file), that is it is nxt_buf_t * without file and mmap part. The buffers are frequently used, so * the reduction allows to save 20-32 bytes depending on platform. * From 1c607662eb952ecafad08e9774c87aa8676eb836 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Sat, 13 Jul 2024 06:17:51 +0100 Subject: [PATCH 07/14] status: Add a missing check for potential NULL Fixes: 707f4ef8 ("status: Show list of loaded language modules") Signed-off-by: Andrew Clayton --- src/nxt_status.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nxt_status.c b/src/nxt_status.c index b48ec743b..92cbf2e65 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -107,6 +107,10 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) if (lang_cnts[type] > 1) { obj = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + nxt_conf_set_element(mod_obj, a++, obj); } From 58fdff542b176dc7a78c96bff5c401bcda4723f6 Mon Sep 17 00:00:00 2001 From: Arjun Date: Tue, 18 Jun 2024 07:48:18 +0530 Subject: [PATCH 08/14] fuzzing: added cifuzz workflow Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- .github/workflows/cifuzz.yml | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/cifuzz.yml diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml new file mode 100644 index 000000000..c8c4d5a22 --- /dev/null +++ b/.github/workflows/cifuzz.yml @@ -0,0 +1,41 @@ +name: CIFuzz +on: + pull_request: + paths: + - 'src/**' + - 'fuzzing/**' + - '.github/workflows/cifuzz.yml' + +permissions: {} +jobs: + Fuzzing: + runs-on: ubuntu-latest + permissions: + security-events: write + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'unit' + language: c + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'unit' + language: c + fuzz-seconds: 300 + output-sarif: true + - name: Upload Crash + uses: actions/upload-artifact@v3 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts + - name: Upload Sarif + if: always() && steps.build.outcome == 'success' + uses: github/codeql-action/upload-sarif@v2 + with: + # Path to SARIF file relative to the root of the repository + sarif_file: cifuzz-sarif/results.sarif + checkout_path: cifuzz-sarif From fcbaf8f3162e8b589628a8bbe10690a9759f56bb Mon Sep 17 00:00:00 2001 From: Arjun Date: Wed, 10 Jul 2024 10:35:36 +0530 Subject: [PATCH 09/14] fuzzing: fix harness bugs There are multiple false positive bugs in harness due to improper use of the internal API. Fixes: a93d878e ("fuzzing: add fuzzing targets") Signed-off-by: Arjun [ Removed private links - Andrew ] Signed-off-by: Andrew Clayton --- fuzzing/nxt_http_controller_fuzz.c | 8 ++++++++ fuzzing/nxt_http_h1p_fuzz.c | 2 ++ fuzzing/nxt_json_fuzz.c | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/fuzzing/nxt_http_controller_fuzz.c b/fuzzing/nxt_http_controller_fuzz.c index b7c6c2724..eac54d7b0 100644 --- a/fuzzing/nxt_http_controller_fuzz.c +++ b/fuzzing/nxt_http_controller_fuzz.c @@ -76,6 +76,14 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } + r_controller->conn = nxt_mp_zget(mp, sizeof(nxt_conn_t)); + if (r_controller->conn == NULL) { + goto failed; + } + + nxt_main_log.level = NXT_LOG_ALERT; + r_controller->conn->log = nxt_main_log; + nxt_http_fields_process(rp.fields, &nxt_controller_fields_hash, r_controller); diff --git a/fuzzing/nxt_http_h1p_fuzz.c b/fuzzing/nxt_http_h1p_fuzz.c index 471e87a4f..a170463a0 100644 --- a/fuzzing/nxt_http_h1p_fuzz.c +++ b/fuzzing/nxt_http_h1p_fuzz.c @@ -75,6 +75,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } + r_h1p->mem_pool = mp; + nxt_http_fields_process(rp.fields, &nxt_h1p_fields_hash, r_h1p); failed: diff --git a/fuzzing/nxt_json_fuzz.c b/fuzzing/nxt_json_fuzz.c index 532babb1b..cfeb395da 100644 --- a/fuzzing/nxt_json_fuzz.c +++ b/fuzzing/nxt_json_fuzz.c @@ -4,7 +4,7 @@ #include #include - +#include #define KMININPUTLENGTH 2 #define KMAXINPUTLENGTH 1024 @@ -33,6 +33,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { nxt_mp_t *mp; nxt_str_t input; + nxt_thread_t *thr; + nxt_runtime_t *rt; nxt_conf_value_t *conf; nxt_conf_validation_t vldt; @@ -40,11 +42,21 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return 0; } + thr = nxt_thread(); + mp = nxt_mp_create(1024, 128, 256, 32); if (mp == NULL) { return 0; } + rt = nxt_mp_zget(mp, sizeof(nxt_runtime_t)); + if (rt == NULL) { + goto failed; + } + + thr->runtime = rt; + rt->mem_pool = mp; + input.start = (u_char *)data; input.length = size; @@ -64,6 +76,11 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) vldt.conf_pool = mp; vldt.ver = NXT_VERNUM; + rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t)); + if (rt->languages == NULL) { + goto failed; + } + nxt_conf_validate(&vldt); nxt_mp_destroy(vldt.pool); From 61c13ade39473b1b4849ab0ae10ab4ceff324ba5 Mon Sep 17 00:00:00 2001 From: Arjun Date: Sat, 13 Jul 2024 09:42:42 +0530 Subject: [PATCH 10/14] fuzzing: update directory path in README and build-fuzz.sh Fixes: 965fc94e ("fuzzing: add fuzzing infrastructure in build system") Fixes: 5b65134c ("fuzzing: add a basic README") Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- fuzzing/README.md | 10 +++++----- fuzzing/build-fuzz.sh | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fuzzing/README.md b/fuzzing/README.md index b15093277..9c70c8016 100644 --- a/fuzzing/README.md +++ b/fuzzing/README.md @@ -43,11 +43,11 @@ $ mkdir -p build/fuzz_http_h1p_seed $ mkdir -p build/fuzz_http_h1p_peer_seed $ mkdir -p build/fuzz_json_seed -$ ./build/fuzz_basic build/fuzz_basic_seed src/fuzz/fuzz_basic_seed_corpus -$ ./build/fuzz_http_controller build/fuzz_http_controller_seed src/fuzz/fuzz_http_controller_seed_corpus -$ ./build/fuzz_http_h1p build/fuzz_http_h1p_seed src/fuzz/fuzz_http_h1p_seed_corpus -$ ./build/fuzz_http_h1p_peer build/fuzz_http_h1p_peer_seed src/fuzz/fuzz_http_h1p_peer_seed_corpus -$ ./build/fuzz_json build/fuzz_json_seed src/fuzz/fuzz_json_seed_corpus +$ ./build/fuzz_basic build/fuzz_basic_seed fuzzing/fuzz_basic_seed_corpus +$ ./build/fuzz_http_controller build/fuzz_http_controller_seed fuzzing/fuzz_http_seed_corpus +$ ./build/fuzz_http_h1p build/fuzz_http_h1p_seed fuzzing/fuzz_http_seed_corpus +$ ./build/fuzz_http_h1p_peer build/fuzz_http_h1p_peer_seed fuzzing/fuzz_http_seed_corpus +$ ./build/fuzz_json build/fuzz_json_seed fuzzing/fuzz_json_seed_corpus ``` Here is more information about [LibFuzzer](https://llvm.org/docs/LibFuzzer.html). diff --git a/fuzzing/build-fuzz.sh b/fuzzing/build-fuzz.sh index 04f080d94..62f7a6761 100644 --- a/fuzzing/build-fuzz.sh +++ b/fuzzing/build-fuzz.sh @@ -16,5 +16,5 @@ mkdir -p build/fuzz_http_h1p_peer_seed mkdir -p build/fuzz_json_seed echo "" -echo "Run: ./build/\${fuzzer} build/\${fuzzer}_seed src/fuzz/\${fuzzer}_seed_corpus" +echo "Run: ./build/\${fuzzer} build/\${fuzzer}_seed fuzzing/\${fuzzer}_seed_corpus" echo "" From 90542dbd711041499e181911df10794997d792d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 03:23:29 +0000 Subject: [PATCH 11/14] ci: cifuzz: Bump github/codeql-action from 2 to 3 Bumps from 2 to 3. Link: Release notes Link: Changelog Link: Commits Signed-off-by: dependabot[bot] Signed-off-by: Andrew Clayton --- .github/workflows/cifuzz.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index c8c4d5a22..dc89c0b26 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -34,7 +34,7 @@ jobs: path: ./out/artifacts - name: Upload Sarif if: always() && steps.build.outcome == 'success' - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: # Path to SARIF file relative to the root of the repository sarif_file: cifuzz-sarif/results.sarif From 57a75ea062bdd793ad34db20d141c7531c25e502 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:14:05 +0000 Subject: [PATCH 12/14] build(deps): bump openssl from 0.10.64 to 0.10.66 in /tools/unitctl Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.64 to 0.10.66. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.64...openssl-v0.10.66) --- updated-dependencies: - dependency-name: openssl dependency-type: indirect ... Signed-off-by: dependabot[bot] --- tools/unitctl/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/unitctl/Cargo.lock b/tools/unitctl/Cargo.lock index 202799638..bcbe53b7a 100644 --- a/tools/unitctl/Cargo.lock +++ b/tools/unitctl/Cargo.lock @@ -1185,9 +1185,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -1217,9 +1217,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", From b892e99458ec964c3af7cf8b5f973f98ba06cd4b Mon Sep 17 00:00:00 2001 From: Ava Hahn Date: Mon, 15 Jul 2024 13:59:48 -0700 Subject: [PATCH 13/14] tools/unitctl: update readme Signed-off-by: Ava Hahn --- tools/unitctl/README.md | 94 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 10 deletions(-) diff --git a/tools/unitctl/README.md b/tools/unitctl/README.md index 4aa6068c5..977ee1a84 100644 --- a/tools/unitctl/README.md +++ b/tools/unitctl/README.md @@ -51,11 +51,44 @@ desired. ## Features (Current) +``` +CLI interface to the NGINX UNIT Control API + +Usage: unitctl [OPTIONS] + +Commands: + instances List all running UNIT processes + edit Open current UNIT configuration in editor + import Import configuration from a directory + execute Sends raw JSON payload to UNIT + status Get the current status of UNIT + listeners List active listeners + help Print this message or the help of the given subcommand(s) + +Options: + -s, --control-socket-address + Path (unix:/var/run/unit/control.sock), tcp address with port (127.0.0.1:80), or URL + -w, --wait-timeout-seconds + Number of seconds to wait for control socket to become available + -t, --wait-max-tries + Number of times to try to access control socket when waiting [default: 3] + -h, --help + Print help + -V, --version + Print version +``` + - Consumes alternative configuration formats Like YAML and converts them +- Can convert output to multiple different formats. - Syntactic highlighting of JSON output - Interpretation of Unit errors with (arguably more) useful error messages ### Lists all running Unit processes and provides details about each process. +Unitctl will detect and connect to running process of Unit on the host. +It will pull information about the running Unit configuration +(including how to access its control API) from the process information of +each detected Unit process. + ``` $ unitctl instances No socket path provided - attempting to detect from running instance @@ -68,6 +101,11 @@ unitd instance [pid: 79489, version: 1.32.0]: ``` ### Start a new Unit process via docker +Unitctl can launch new containers of Unit. +These can be official Unit images or custom Unit images. +The new containers will then be shown in a call to +`unitctl instances` + ``` $ unitctl instances new /tmp/2 $(pwd) 'unit:wasm' Pulling and starting a container from unit:wasm @@ -77,21 +115,32 @@ Note: Container will be on host network ``` -To the subcommand `unitctl instances new` the user must provide three things: -1. **A directory such as `/tmp/2`.** - The Unit container will mount this to `/var/run` internally. - Thus, the control socket and pid file will be accessible from the host. -2. **A path to an application.** +To the subcommand `unitctl instances new` the user must provide three arguments: +1. **A means of showing the control API:** + There are two possibilities for this argument. + A filepath on which to open a unix socket, + or a TCP address. + - If a directory is specified the Unit container + will mount this to `/var/run` internally. + Thus, the control socket and pid file will be + accessible from the host. For example: `/tmp/2`. + - If a TCP endpoint is specified Unit will be configured + to offer its control API on the given port and address. + For example: `127.0.0.1:7171`. +2. **A path to an application:** In the example, `$(pwd)` is provided. The Unit container will mount this READ ONLY to `/www/`. This will allow the user to configure their Unit container to expose an application stored on the host. -3. **An image tag.** +3. **An image tag:** In the example, `unit:wasm` is used. This will be the image that unitctl will deploy. Custom repos and images can be deployed in this manner. After deployment the user will have one Unit container running on the host network. ### Lists active applications and provides means to restart them +Unitctl can list running applications by accessing the specified control API. +Unitctl can also request from the API that an application be restarted. + Listing applications: ``` $ unitctl app list @@ -120,6 +169,9 @@ $ unitctl -s '127.0.0.1:8001' -s /run/nginx-unit.control.sock app list ``` ### Lists active listeners from running Unit processes +Unitctl can query a given control API to fetch all configured +listeners. + ``` unitctl listeners No socket path provided - attempting to detect from running instance @@ -138,6 +190,9 @@ $ unitctl -s '127.0.0.1:8001' -s /run/nginx-unit.control.sock listeners ``` ### Get the current status of NGINX Unit processes +Unitctl can query the control API to provide the status of the running +Unit daemon. + ``` $ unitctl status -t yaml No socket path provided - attempting to detect from running instance @@ -159,6 +214,10 @@ $ unitctl -s '127.0.0.1:8001' -s /run/nginx-unit.control.sock status ``` ### Send arbitrary configuration payloads to Unit +Unitctl can accept custom request payloads and query given API endpoints with them. +The request payload must be passed in using the `-f` flag either as a filename or +using the `-` filename to denote the use of stdin as shown in the example below. + ``` $ echo '{ "listeners": { @@ -188,6 +247,12 @@ $ unitctl -s '127.0.0.1:8001' -s /run/nginx-unit.control.sock execute ... ``` ### Edit current configuration in your favorite editor +Unitctl can fetch the configuration from a running instance of Unit and +load it in any number of preconfigured editors on your command line. + +Unitctl will try to use whatever editor is configured with the `EDITOR` +environment variable, but will default to vim, emacs, nano, vi, or pico. + ``` $ unitctl edit [[EDITOR LOADS SHOWING CURRENT CONFIGURATION - USER EDITS AND SAVES]] @@ -200,6 +265,10 @@ $ unitctl edit *Note:* This command does not support operating on multiple instances of Unit at once. ### Import configuration, certificates, and NJS modules from directory +Unitctl will parse existing configuration, certificates, and NJS modules +stored in a directory and convert them into a payload to reconfigure a +given Unit daemon. + ``` $ unitctl import /opt/unit/config Imported /opt/unit/config/certificates/snake.pem -> /certificates/snake.pem @@ -209,12 +278,15 @@ Imported 3 files ``` ### Export configuration from a running Unit instance -``` -$ unitctl export -f config.tar -``` +Unitctl will query a control API to fetch running configuration +and NJS modules from a Unit process. Due to a technical limitation +this output will not contain currently stored certificate bundles. +The output is saved as a tarball at the filename given with the `-f` +argument. Standard out may be used with `-f -` as shown in the +following examples. -Addtionally, standard out can be used: ``` +$ unitctl export -f config.tar $ unitctl export -f - $ unitctl export -f - | tar xf - config.json $ unitctl export -f - > config.tar @@ -225,6 +297,8 @@ $ unitctl export -f - > config.tar *Note:* This command does not support operating on multiple instances of Unit at once. ### Wait for socket to become available +All commands support waiting on unix sockets for availability. + ``` $ unitctl --wait-timeout-seconds=3 --wait-max-tries=4 import /opt/unit/config` Waiting for 3s control socket to be available try 2/4... From 1b4843036d6aa10fea6c23ed455c30f4cc9d873d Mon Sep 17 00:00:00 2001 From: Ava Hahn <110854134+avahahn@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:07:57 -0700 Subject: [PATCH 14/14] tools/unitctl: update readme Signed-off-by: Ava Hahn --- tools/unitctl/README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/unitctl/README.md b/tools/unitctl/README.md index 977ee1a84..e6fca4772 100644 --- a/tools/unitctl/README.md +++ b/tools/unitctl/README.md @@ -52,16 +52,16 @@ desired. ## Features (Current) ``` -CLI interface to the NGINX UNIT Control API +CLI interface to the NGINX Unit Control API Usage: unitctl [OPTIONS] Commands: - instances List all running UNIT processes - edit Open current UNIT configuration in editor + instances List all running Unit processes + edit Open current Unit configuration in editor import Import configuration from a directory - execute Sends raw JSON payload to UNIT - status Get the current status of UNIT + execute Sends raw JSON payload to Unit + status Get the current status of Unit listeners List active listeners help Print this message or the help of the given subcommand(s) @@ -79,7 +79,7 @@ Options: ``` - Consumes alternative configuration formats Like YAML and converts them -- Can convert output to multiple different formats. +- Can convert output to multiple different formats (YAML, plain JSON, highlighted JSON) - Syntactic highlighting of JSON output - Interpretation of Unit errors with (arguably more) useful error messages @@ -103,6 +103,8 @@ unitd instance [pid: 79489, version: 1.32.0]: ### Start a new Unit process via docker Unitctl can launch new containers of Unit. These can be official Unit images or custom Unit images. +Any container that calls `unitd` in a CMD declaration will suffice. + The new containers will then be shown in a call to `unitctl instances`