From 5008d175e20ada87b5f5c9e3dc15e6555551a32b Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Wed, 23 Feb 2022 22:43:09 +0100 Subject: [PATCH 01/13] dfuzzer: rework df_print_process_info() a bit to make Valgrind happy. Fixes: #8 --- src/dfuzzer.c | 86 ++++++++++++++++++++++++++------------------------- src/dfuzzer.h | 10 ++++++ 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index 358398e..3693349 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -925,58 +925,60 @@ int df_get_pid(const GDBusConnection *dcon) void df_print_process_info(int pid) { char proc_path[15+DECIMAL_STR_MAX(int)]; // "/proc/(int)/[exe|cmdline]" - char name[PATH_MAX]; // for storing process and package name + char name[PATH_MAX + 1]; // for storing process and package name char buf[PATH_MAX + MAXLEN]; // buffer for rpm/dpkg request FILE *fp; - char *c; - int fd, stdoutcpy, stderrcpy, ret; - + _cleanup_close_ int fd = -1; + int stdoutcpy, stderrcpy, ret; sprintf(proc_path, "/proc/%d/exe", pid); - ret = readlink(proc_path, name, sizeof(name)); - // excludes interprets - if (ret != -1 && strstr(name, "python") == NULL && strstr(name, "perl") == NULL) - fprintf(stderr, "%s%s[PROCESS: %s%s\n", - ansi_cr(), ansi_cyan(), name, ansi_normal()); - else { - // if readlink failed or executable was interpret (and our target is - // interpreted script), try to read cmdline - sprintf(proc_path, "/proc/%d/cmdline", pid); - fd = open(proc_path, O_RDONLY); - if (fd == -1) + ret = readlink(proc_path, name, PATH_MAX); + if (ret > 0) { + name[ret] = '\0'; + + if (ret == PATH_MAX) + df_verbose("The process name was truncated\n"); + + if (!strstr(name, "python") && !strstr(name, "perl")) { + fprintf(stderr, "%s%s[PROCESS: %s%s\n", + ansi_cr(), ansi_cyan(), name, ansi_normal()); return; + } + } - ret = 1; - c = name; - fprintf(stderr, "%s%s[PROCESS: ", ansi_cr(), ansi_cyan()); - while (ret > 0) { - ret = read(fd, c, 1); - if (ret > 0) { - if (*c == '\0') - *c = ' '; - fprintf(stderr, "%c", *c); - } - if (ret == -1) { - fprintf(stderr, "%s\n", ansi_normal()); - close(fd); - return; - } - c++; + // if readlink failed or executable was interpret (and our target is + // interpreted script), try to read cmdline + sprintf(proc_path, "/proc/%d/cmdline", pid); + fd = open(proc_path, O_RDONLY); + if (fd <= 0) { + perror("open"); + return; + } + + for (int i = 0;; i++) { + if (i >= PATH_MAX) { + df_verbose("The process name was truncated\n"); + name[PATH_MAX] = '\0'; + break; } - *c = '\0'; - fprintf(stderr, "%s\n", ansi_normal()); - close(fd); - // excludes interprets - if (strstr(name, "python") != NULL || strstr(name, "perl") != NULL) { - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); + ret = read(fd, (name + i), 1); + if (ret < 0) { + perror("read"); return; - } else { // removes cmdline arguments - c = name; - while (*c != ' ' && *c != '\0') - c++; - *c = '\0'; } + + if (name[i] == '\0') + break; + } + + fprintf(stderr, "%s%s[PROCESS: %s%s\n", + ansi_cr(), ansi_cyan(), name, ansi_normal()); + + // excludes interprets + if (strstr(name, "python") || strstr(name, "perl")) { + fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); + return; } diff --git a/src/dfuzzer.h b/src/dfuzzer.h index 1e53515..1aa6d7b 100644 --- a/src/dfuzzer.h +++ b/src/dfuzzer.h @@ -37,6 +37,16 @@ /** Maximum length of strings containing D-Bus name, interface and object path */ #define MAXLEN 256 +static inline void closep(int *fd) { + if (*fd < 0) + return; + + close(*fd); +} + +#define _cleanup_(x) __attribute__((__cleanup__(x))) +#define _cleanup_close_ _cleanup_(closep) + static inline int isempty(const char *s) { return !s || s[0] == '\0'; } From 3bc542d436d74d840602d41598efed239154b3d8 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 24 Feb 2022 13:20:15 +0100 Subject: [PATCH 02/13] dfuzzer: add missing brackets --- src/dfuzzer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index 3693349..5264bdf 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -152,7 +152,7 @@ int main(int argc, char **argv) df_pid = df_get_pid(dcon); if (df_pid > 0) { df_print_process_info(df_pid); - fprintf(stderr, "%s%s[CONNECTED TO PID: %d%s\n", + fprintf(stderr, "%s%s[CONNECTED TO PID: %d]%s\n", ansi_cr(), ansi_cyan(), df_pid, ansi_normal()); if (strlen(target_proc.interface) != 0) { fprintf(stderr, "Object: %s%s%s\n", @@ -209,7 +209,7 @@ int main(int argc, char **argv) df_pid = df_get_pid(dcon); if (df_pid > 0) { df_print_process_info(df_pid); - fprintf(stderr, "%s%s[CONNECTED TO PID: %d%s\n", + fprintf(stderr, "%s%s[CONNECTED TO PID: %d]%s\n", ansi_cr(), ansi_cyan(), df_pid, ansi_normal()); if (strlen(target_proc.interface) != 0) { fprintf(stderr, "Object: %s%s%s\n", @@ -769,7 +769,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_debug("Error in df_get_pid() on getting pid of process\n"); return 1; } - fprintf(stderr, "%s%s[RE-CONNECTED TO PID: %d%s\n", + fprintf(stderr, "%s%s[RE-CONNECTED TO PID: %d]%s\n", ansi_cr(), ansi_cyan(), df_pid, ansi_blue()); // opens process status file @@ -940,7 +940,7 @@ void df_print_process_info(int pid) df_verbose("The process name was truncated\n"); if (!strstr(name, "python") && !strstr(name, "perl")) { - fprintf(stderr, "%s%s[PROCESS: %s%s\n", + fprintf(stderr, "%s%s[PROCESS: %s]%s\n", ansi_cr(), ansi_cyan(), name, ansi_normal()); return; } @@ -972,7 +972,7 @@ void df_print_process_info(int pid) break; } - fprintf(stderr, "%s%s[PROCESS: %s%s\n", + fprintf(stderr, "%s%s[PROCESS: %s]%s\n", ansi_cr(), ansi_cyan(), name, ansi_normal()); // excludes interprets From e81358b76a74949ea9f2a7d556ed62a5188e5ac0 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 24 Feb 2022 13:13:33 +0100 Subject: [PATCH 03/13] dfuzzer: drop the package-info parsing code --- src/dfuzzer.c | 76 ++------------------------------------------------- 1 file changed, 3 insertions(+), 73 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index 5264bdf..c6b5008 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -924,12 +924,10 @@ int df_get_pid(const GDBusConnection *dcon) */ void df_print_process_info(int pid) { - char proc_path[15+DECIMAL_STR_MAX(int)]; // "/proc/(int)/[exe|cmdline]" - char name[PATH_MAX + 1]; // for storing process and package name - char buf[PATH_MAX + MAXLEN]; // buffer for rpm/dpkg request - FILE *fp; + char proc_path[15 + DECIMAL_STR_MAX(int)]; // "/proc/(int)/[exe|cmdline]" + char name[PATH_MAX + 1]; _cleanup_close_ int fd = -1; - int stdoutcpy, stderrcpy, ret; + int ret; sprintf(proc_path, "/proc/%d/exe", pid); ret = readlink(proc_path, name, PATH_MAX); @@ -974,74 +972,6 @@ void df_print_process_info(int pid) fprintf(stderr, "%s%s[PROCESS: %s]%s\n", ansi_cr(), ansi_cyan(), name, ansi_normal()); - - // excludes interprets - if (strstr(name, "python") || strstr(name, "perl")) { - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - return; - } - - - fd = open("/dev/null", O_RDWR, S_IRUSR | S_IWUSR); - if (fd == -1) { - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - return; - } - - // backup std descriptors - stdoutcpy = dup(1); - stderrcpy = dup(2); - - // make stdout and stderr go to fd - if (dup2(fd, 1) == -1) { - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - return; - } - if (dup2(fd, 2) == -1) { - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - dup2(stdoutcpy, 1); - close(stdoutcpy); - return; - } - close(fd); // fd no longer needed - - - // Determines which package manager should be used - if (WEXITSTATUS(system("which rpm")) == 0) - sprintf(buf, "rpm -qf %s", name); - else if (WEXITSTATUS(system("which dpkg")) == 0) - sprintf(buf, "aptitude versions $(dpkg -S %s " - "| sed 's/:.*//') -F %%p %%V | sed 's/Package //' " - "| sed ':a;$!N;s/:\\n/-/;ta' | tr -d ' ' | sed '/^$/d' " - "| tr '\n' ' ' | sed 's/$/\\n$/'" , name); - else { // only rpm/dpkg are supported - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - // restore std descriptors - dup2(stdoutcpy, 1); - close(stdoutcpy); - dup2(stderrcpy, 2); - close(stderrcpy); - return; - } - - fp = popen(buf, "r"); - // restore std descriptors - dup2(stdoutcpy, 1); - close(stdoutcpy); - dup2(stderrcpy, 2); - close(stderrcpy); - if (fp == NULL) { - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - return; - } - fgets(name, PATH_MAX, fp); - ret = pclose(fp); - - - if (WEXITSTATUS(ret) == 0) - fprintf(stderr, "%s%s[PACKAGE: %s%s\n", ansi_cr(), ansi_cyan(), name, ansi_normal()); - else - fprintf(stderr, "%s%s[PACKAGE: %s\n", ansi_cr(), ansi_cyan(), ansi_normal()); } /** From 5a75db20691675cc8d2f2e0a96de85eae1542c77 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 10:23:55 +0100 Subject: [PATCH 04/13] Make use of strdup() in a couple of places --- src/fuzz.c | 62 ++++++++++++++++++++++----------------------- src/introspection.c | 16 ++++++------ 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/fuzz.c b/src/fuzz.c index c032f1d..834f153 100644 --- a/src/fuzz.c +++ b/src/fuzz.c @@ -150,17 +150,16 @@ int df_fuzz_init(GDBusProxy *dproxy, const int statfd, */ int df_fuzz_add_method(const char *name) { - if (name == NULL) { + if (!name) { df_debug("Passing NULL argument to function.\n"); return -1; } - df_list.df_method_name = malloc(sizeof(char) * strlen(name) + 1); - if (df_list.df_method_name == NULL) { + df_list.df_method_name = strdup(name); + if (!df_list.df_method_name) { df_fail("Error: Could not allocate memory for method name.\n"); return -1; } - strcpy(df_list.df_method_name, name); // must be initialized because after df_fuzz_clean_method() memory // of df_list contains junk @@ -180,11 +179,13 @@ int df_fuzz_add_method(const char *name) */ int df_fuzz_add_method_arg(const char *signature) { - if (signature == NULL) + struct df_signature *s; + + if (!signature) return 0; - struct df_signature *s; - if ((s = malloc(sizeof(struct df_signature))) == NULL) { + s = malloc(sizeof(*s)); + if (!s) { df_fail("Error: Could not allocate memory for struct df_signature.\n"); return -1; } @@ -192,20 +193,17 @@ int df_fuzz_add_method_arg(const char *signature) df_list.args++; s->next = NULL; s->var = NULL; - s->sig = malloc(sizeof(char) * strlen(signature) + 1); - if (s->sig == NULL) { + s->sig = strdup(signature); + if (!s->sig) { df_fail("Error: Could not allocate memory for argument signature.\n"); return -1; } - strcpy(s->sig, signature); // fuzzing controlled by generated random strings lengths - if (strstr(s->sig, "s") != NULL) - df_list.fuzz_on_str_len = 1; - if (strstr(s->sig, "v") != NULL) + if (strstr(s->sig, "s") || strstr(s->sig, "v")) df_list.fuzz_on_str_len = 1; - if (df_list.list == NULL) { + if (!df_list.list) { df_list.list = s; df_last = s; } else { @@ -598,7 +596,8 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, // creates variant containing all (fuzzed) method arguments - if ((value = df_fuzz_create_variant()) == NULL) { + value = df_fuzz_create_variant(); + if (!value) { if (df_unsupported_sig) { df_unsupported_sig = 0; df_debug(" unsupported argument by dfuzzer: "); @@ -792,9 +791,17 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, static GVariant *df_fuzz_create_variant(void) { struct df_signature *s = df_list.list; // pointer on first signature + // libffi part, to construct dynamic call of g_variant_new() on runtime + GVariant *val = NULL; + ffi_cif cif; + // MAXSIG = max. amount of D-Bus signatures + 1 (format string) + ffi_type *args[MAXSIG + 1]; + void *values[MAXSIG + 1]; + char *fmt; // format string + int ret; // creates GVariant for every item signature in linked list - int ret = df_fuzz_create_list_variants(); + ret = df_fuzz_create_list_variants(); if (ret == -1) { df_debug("Error in df_fuzz_create_list_variants()\n"); return NULL; @@ -803,17 +810,8 @@ static GVariant *df_fuzz_create_variant(void) return NULL; } - // libffi part, to construct dynamic call of g_variant_new() on runtime - GVariant *val = NULL; - ffi_cif cif; - - // MAXSIG = max. amount of D-Bus signatures + 1 (format string) - ffi_type *args[MAXSIG + 1]; - void *values[MAXSIG + 1]; - char *fmt; // format string - int i; - - if ((fmt = malloc(MAXFMT + 1)) == NULL) { + fmt = malloc(MAXFMT + 1); + if (!fmt) { df_fail("Error: Could not allocate memory for format string.\n"); return NULL; } @@ -825,11 +823,10 @@ static GVariant *df_fuzz_create_variant(void) return NULL; } - // Initialize the argument info vectors args[0] = &ffi_type_pointer; values[0] = &fmt; - for (i = 1; i <= df_list.args && s != NULL; i++) { + for (int i = 1; i <= df_list.args && s; i++) { args[i] = &ffi_type_pointer; values[i] = &(s->var); s = s->next; @@ -1042,9 +1039,10 @@ static int df_fuzz_call_method(const GVariant *value, const int void_method) df_list.df_method_name, value, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (response == NULL) { + if (!response) { // D-Bus exceptions are accepted - if ((dbus_error = g_dbus_error_get_remote_error(error)) != NULL) { + dbus_error = g_dbus_error_get_remote_error(error); + if (dbus_error) { // if process does not respond if (strcmp(dbus_error, "org.freedesktop.DBus.Error.NoReply") == 0) { g_free(dbus_error); @@ -1068,7 +1066,7 @@ static int df_fuzz_call_method(const GVariant *value, const int void_method) } g_dbus_error_strip_remote_error(error); - if (strstr(error->message, "Timeout") != NULL) { + if (strstr(error->message, "Timeout")) { df_verbose("%s %sSKIP%s %s - timeout reached\n", ansi_cr(), ansi_blue(), ansi_normal(), df_list.df_method_name); g_error_free(error); diff --git a/src/introspection.c b/src/introspection.c index e04f04b..4513063 100644 --- a/src/introspection.c +++ b/src/introspection.c @@ -49,7 +49,7 @@ static GDBusArgInfo **df_out_args; */ int df_init_introspection(const GDBusProxy *dproxy, const char *name, const char *interface) { - if (dproxy == NULL || interface == NULL) { + if (!dproxy || !interface) { df_debug("Passing NULL argument to function.\n"); return -1; } @@ -64,7 +64,7 @@ int df_init_introspection(const GDBusProxy *dproxy, const char *name, const char "org.freedesktop.DBus.Introspectable.Introspect", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (response == NULL) { + if (!response) { g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); df_error("Error in g_dbus_proxy_call_sync()", error); @@ -73,7 +73,7 @@ int df_init_introspection(const GDBusProxy *dproxy, const char *name, const char g_variant_get(response, "(s)", &introspection_xml); g_variant_unref(response); - if (introspection_xml == NULL) { + if (!introspection_xml) { df_fail("Error: Unable to get introspection data from GVariant.\n"); return -1; } @@ -82,7 +82,7 @@ int df_init_introspection(const GDBusProxy *dproxy, const char *name, const char // the data. df_introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); g_free(introspection_xml); - if (df_introspection_data == NULL) { + if (!df_introspection_data) { df_fail("Error: Unable to get introspection data.\n"); df_error("Error in g_dbus_node_info_new_for_xml()", error); return -1; @@ -90,7 +90,7 @@ int df_init_introspection(const GDBusProxy *dproxy, const char *name, const char // Looks up information about an interface (methods, their arguments, etc). df_interface_data = g_dbus_node_info_lookup_interface(df_introspection_data, interface); - if (df_interface_data == NULL) { + if (!df_interface_data) { df_fail("Error: Unable to get interface '%s' data.\n", interface); df_debug("Error in g_dbus_node_info_lookup_interface()\n"); return -1; @@ -99,7 +99,7 @@ int df_init_introspection(const GDBusProxy *dproxy, const char *name, const char // *df_methods is a pointer on the GDBusMethodInfo structure (first method) // of interface. df_methods = df_interface_data->methods; - if (*df_methods == NULL) { + if (!*df_methods) { df_debug("Interface '%s' has no methods to test - skipping\n", interface); return 0; } @@ -125,7 +125,7 @@ GDBusMethodInfo *df_get_method(void) void df_next_method(void) { df_methods++; - if (*df_methods != NULL) { + if (*df_methods) { // sets pointer on args of current method df_in_args = (*df_methods)->in_args; df_out_args = (*df_methods)->out_args; @@ -155,7 +155,7 @@ void df_next_method_arg(void) */ int df_method_has_out_args(void) { - if (*df_out_args != NULL) + if (*df_out_args) return 1; return 0; } From 901c7bf40df24f59be091a687df06dba5e146db6 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 10:56:14 +0100 Subject: [PATCH 05/13] dfuzzer: account for kernel.pid_max > 65535, part #2 Follow-up to: * c29e0be2dd3f7ab60e2782f72940cd275f9b0cfe * ffe19852bc63f0cb1c34408deebd7690efa79dd0 --- src/dfuzzer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index c6b5008..5a01f92 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -858,10 +858,12 @@ int df_is_valid_dbus(const char *name, const char *obj, const char *intf) */ int df_open_proc_status_file(const int pid) { - char file_path[25]; // "/proc/(max10chars)/status" + char file_path[14 + DECIMAL_STR_MAX(pid)]; // "/proc/PID/status" + int statfd; + sprintf(file_path, "/proc/%d/status", pid); - int statfd = open(file_path, O_RDONLY); + statfd = open(file_path, O_RDONLY); if (statfd == -1) { df_fail("Error: Unable to open file '%s'.\n", file_path); return -1; From 14ef8dbaf2d8781c7edd451ef2d00588ca3ef68a Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 11:06:22 +0100 Subject: [PATCH 06/13] dfuzzer: formatting tweaks --- src/dfuzzer.c | 146 +++++++++++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 55 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index 5a01f92..3d0df2c 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -297,23 +297,31 @@ int df_list_bus_names(const GDBusConnection *dcon) // Uses dcon (GDBusConnection *) to create proxy for accessing // org.freedesktop.DBus (for calling its method ListNames) - proxy = g_dbus_proxy_new_sync(dcon, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, + proxy = g_dbus_proxy_new_sync( + dcon, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", - NULL, &error); - if (proxy == NULL) { + NULL, + &error); + if (!proxy) { df_fail("Error: Unable to create proxy for getting bus names.\n"); df_error("Error in g_dbus_proxy_new_sync()", error); return -1; } // Synchronously invokes method ListNames - response = g_dbus_proxy_call_sync(proxy, "ListNames", NULL, - G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (response == NULL) { + response = g_dbus_proxy_call_sync( + proxy, + "ListNames", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!response) { g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); df_error("Error in g_dbus_proxy_call_sync()", error); @@ -362,22 +370,30 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) if (!df_is_valid_dbus(target_proc.name, root_node, intro_iface)) return 0; - dproxy = g_dbus_proxy_new_sync(dcon, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, - target_proc.name, root_node, intro_iface, - NULL, &error); - if (dproxy == NULL) { - df_fail("Error: Unable to create proxy for bus name '%s'.\n", - target_proc.name); + dproxy = g_dbus_proxy_new_sync( + dcon, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + target_proc.name, + root_node, + intro_iface, + NULL, + &error); + if (!dproxy) { + df_fail("Error: Unable to create proxy for bus name '%s'.\n", target_proc.name); df_error("Error in g_dbus_proxy_new_sync()", error); return 0; } - - response = g_dbus_proxy_call_sync(dproxy, intro_method, - NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (response == NULL) { + response = g_dbus_proxy_call_sync( + dproxy, + intro_method, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!response) { g_object_unref(dproxy); g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); @@ -386,7 +402,7 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) } g_variant_get(response, "(s)", &introspection_xml); g_variant_unref(response); - if (introspection_xml == NULL) { + if (!introspection_xml) { df_fail("Error: Unable to get introspection data from GVariant.\n"); return 0; } @@ -395,7 +411,7 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) // the data. node_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); g_free(introspection_xml); - if (node_data == NULL) { + if (!node_data) { df_fail("Error: Unable to get introspection data.\n"); df_error("Error in g_dbus_node_info_new_for_xml()", error); g_object_unref(dproxy); @@ -469,22 +485,31 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) if (!df_is_valid_dbus(target_proc.name, root_node, intro_iface)) return 1; - dproxy = g_dbus_proxy_new_sync(dcon, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, - target_proc.name, root_node, intro_iface, - NULL, &error); - if (dproxy == NULL) { - df_fail("Error: Unable to create proxy for bus name '%s'.\n", - target_proc.name); + dproxy = g_dbus_proxy_new_sync( + dcon, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + target_proc.name, + root_node, + intro_iface, + NULL, + &error); + if (!dproxy) { + df_fail("Error: Unable to create proxy for bus name '%s'.\n", target_proc.name); df_error("Error in g_dbus_proxy_new_sync()", error); return 1; } - response = g_dbus_proxy_call_sync(dproxy, intro_method, - NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (response == NULL) { + response = g_dbus_proxy_call_sync( + dproxy, + intro_method, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!response) { g_object_unref(dproxy); gchar *dbus_error = NULL; // D-Bus exceptions @@ -512,7 +537,7 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) } g_variant_get(response, "(s)", &introspection_xml); g_variant_unref(response); - if (introspection_xml == NULL) { + if (!introspection_xml) { df_fail("Error: Unable to get introspection data from GVariant.\n"); return 1; } @@ -521,7 +546,7 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) // the data. node_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); g_free(introspection_xml); - if (node_data == NULL) { + if (!node_data) { df_fail("Error: Unable to get introspection data.\n"); df_error("Error in g_dbus_node_info_new_for_xml()", error); g_object_unref(dproxy); @@ -558,8 +583,7 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) node = node_data->nodes[i++]; while (node != NULL) { // create next object path - object = (char *) calloc(strlen(node->path) + strlen(root_node) + 3, - sizeof(char)); + object = (char *) calloc(strlen(node->path) + strlen(root_node) + 3, sizeof(char)); if (object == NULL) { df_fail("Error: Could not allocate memory for root_node string.\n"); g_dbus_node_info_unref(node_data); @@ -604,6 +628,9 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) */ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, const char *intf) { + GDBusMethodInfo *m; + GDBusArgInfo *in_arg; + int ret = 0; int method_found = 0; // If df_test_method is found in an interface, // method_found is set to 1, otherwise is 0. int void_method; // If method has out args 1, 0 otherwise. @@ -615,7 +642,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // Sanity check fuzzing target - if (strlen(name) == 0 || strlen(obj) == 0 || strlen(intf) == 0) { + if (isempty(name) || isempty(obj) || isempty(intf)) { df_fail("Error in target specification.\n"); return 1; } @@ -624,11 +651,16 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // owned by name at dcon. if (!df_is_valid_dbus(name, obj, intf)) return 1; - dproxy = g_dbus_proxy_new_sync(dcon, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, - name, obj, intf, NULL, &error); - if (dproxy == NULL) { + dproxy = g_dbus_proxy_new_sync( + dcon, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + name, + obj, + intf, + NULL, + &error); + if (!dproxy) { df_fail("Error: Unable to create proxy for bus name '%s'.\n", name); df_error("Error in g_dbus_proxy_new_sync() on creating proxy", error); return 1; @@ -642,7 +674,8 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons } // opens process status file - if ((statfd = df_open_proc_status_file(df_pid)) == -1) { + statfd = df_open_proc_status_file(df_pid); + if (statfd == -1) { df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_open_proc_status_file()\n"); @@ -659,9 +692,6 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons return 1; } - GDBusMethodInfo *m; - GDBusArgInfo *in_arg; - int ret = 0; for (; (m = df_get_method()) != NULL; df_next_method()) { // testing only one method with name df_test_method @@ -886,25 +916,31 @@ int df_get_pid(const GDBusConnection *dcon) // Uses dcon (GDBusConnection *) to create proxy for accessing // org.freedesktop.DBus (for calling its method GetConnectionUnixProcessID) - pproxy = g_dbus_proxy_new_sync(dcon, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, + pproxy = g_dbus_proxy_new_sync( + dcon, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", - NULL, &error); - if (pproxy == NULL) { + NULL, + &error); + if (!pproxy) { df_fail("Error: Unable to create proxy for getting process pid.\n"); df_error("Error on creating proxy for getting process pid", error); return -1; } // Synchronously invokes method GetConnectionUnixProcessID - variant_pid = g_dbus_proxy_call_sync(pproxy, + variant_pid = g_dbus_proxy_call_sync( + pproxy, "GetConnectionUnixProcessID", g_variant_new("(s)", target_proc.name), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); - if (variant_pid == NULL) { + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!variant_pid) { g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); df_error("Error in g_dbus_proxy_call_sync()", error); From 5e85964f385dbdc9115f91d936847094890cbfb3 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 12:03:27 +0100 Subject: [PATCH 07/13] dfuzzer: refactor the main() function --- src/dfuzzer.c | 307 ++++++++++++++++++++------------------------------ src/dfuzzer.h | 20 ++++ 2 files changed, 143 insertions(+), 184 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index 3d0df2c..b7fd81f 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -85,19 +85,13 @@ FILE* logfile; */ int main(int argc, char **argv) { - GDBusConnection *dcon; // D-Bus connection structure - GError *error = NULL; // must be set to NULL - char *root_node = "/"; int rses = 0; // return value from session bus testing int rsys = 0; // return value from system bus testing - int bus_skip = 0; // if skipping one of buses or both, set to 1 - int i; + int ret = 0; char log_file_name[MAXLEN]; - df_parse_parameters(argc, argv); - if (df_full_log_flag) { size_t len = strlen(log_dir_name); strcpy(log_file_name, log_dir_name); @@ -115,169 +109,116 @@ int main(int argc, char **argv) } if (!df_supflg) { // if -s option was not passed if (df_load_suppressions() == -1) { - // free all memory - if (df_suppression != NULL) { - for (i = 0; df_suppression[i] != NULL; i++) - free(df_suppression[i]); - } - if (df_supp_description != NULL) { - for (i = 0; df_supp_description[i] != NULL; i++) - free(df_supp_description[i]); - } printf("%sExit status: 1%s\n", ansi_bold(), ansi_normal()); - return 1; + ret = 1; + goto cleanup; } } - // Initializes the type system. - g_type_init(); + rses = df_process_bus(G_BUS_TYPE_SESSION); + rsys = df_process_bus(G_BUS_TYPE_SYSTEM); - // Synchronously connects to the session bus daemon. - fprintf(stderr, "%s%s[SESSION BUS]%s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - if ((dcon = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error)) == NULL) { - df_fail("Session bus not found.\n"); - df_error("Error in g_bus_get_sync()", error); - error = NULL; - bus_skip = 1; - goto skip_session; - } - if (df_list_names) { - // list names on the bus - if (df_list_bus_names(dcon) == -1) { - df_debug("Error in df_list_bus_names() for session bus\n"); - rses = 1; - } + // both tests ended with error + if (rses == DF_BUS_ERROR || rsys == DF_BUS_ERROR) { + fprintf(stderr, "%sExit status: 1%s\n", ansi_bold(), ansi_normal()); + ret = 1; + } else if (rses == DF_BUS_FAIL || rsys == DF_BUS_FAIL) { + // at least one test found failures + fprintf(stderr, "%sExit status: 2%s\n", ansi_bold(), ansi_normal()); + ret = 2; + } else if (rses == DF_BUS_WARNING || rsys == DF_BUS_WARNING) { + // at least one test found warnings + fprintf(stderr, "%sExit status: 3%s\n", ansi_bold(), ansi_normal()); + ret = 3; + } else if (rses == DF_BUS_NO_PID && rsys == DF_BUS_NO_PID) { + // we couldn't get the process ID on neither of the buses + fprintf(stderr, "%sExit status: 4%s\n", ansi_bold(), ansi_normal()); + ret = 4; } else { - // gets pid of tested process - df_pid = df_get_pid(dcon); - if (df_pid > 0) { - df_print_process_info(df_pid); - fprintf(stderr, "%s%s[CONNECTED TO PID: %d]%s\n", - ansi_cr(), ansi_cyan(), df_pid, ansi_normal()); - if (strlen(target_proc.interface) != 0) { - fprintf(stderr, "Object: %s%s%s\n", - ansi_bold(), target_proc.obj_path, ansi_normal()); - fprintf(stderr, " Interface: %s%s%s\n", - ansi_bold(), target_proc.interface, ansi_normal()); - if (!df_is_object_on_bus(dcon, root_node)) { - df_fail("Error: Unknown object path '%s'.\n", - target_proc.obj_path); - rses = 1; - } else { - rses = df_fuzz(dcon, target_proc.name, target_proc.obj_path, - target_proc.interface); - } - } else if (strlen(target_proc.obj_path) != 0) { - fprintf(stderr, "Object: %s%s%s\n", - ansi_bold(), target_proc.obj_path, ansi_normal()); - if (!df_is_object_on_bus(dcon, root_node)) { - df_fail("Error: Unknown object path '%s'.\n", - target_proc.obj_path); - rses = 1; - } else - rses = df_traverse_node(dcon, target_proc.obj_path); - } else { - fprintf(stderr, "Object: %s/%s\n", ansi_bold(), ansi_normal()); - rses = df_traverse_node(dcon, root_node); - } - } else - rses = 1; + // cases where rses=1,rsys=0 or rses=0,rsys=1 are ok, + // because tests on one of the bus daemons finished + // successfuly + fprintf(stderr, "%sExit status: 0%s\n", ansi_bold(), ansi_normal()); + ret = 0; } - g_object_unref(dcon); +cleanup: + // free all suppressions and their descriptions + if (df_suppression) { + for (int i = 0; df_suppression[i]; i++) + free(df_suppression[i]); + } + if (df_supp_description) { + for (int i = 0; df_supp_description[i]; i++) + free(df_supp_description[i]); + } -skip_session: + return ret; +} +int df_process_bus(GBusType bus_type) +{ + _cleanup_(g_object_unrefp) GDBusConnection *dcon = NULL; + GError *error = NULL; + int ret = DF_BUS_OK; + + switch (bus_type) { + case G_BUS_TYPE_SESSION: + fprintf(stderr, "%s%s[SESSION BUS]%s\n", ansi_cr(), ansi_cyan(), ansi_normal()); + break; + case G_BUS_TYPE_SYSTEM: + fprintf(stderr, "%s%s[SYSTEM BUS]%s\n", ansi_cr(), ansi_cyan(), ansi_normal()); + break; + default: + df_fail("Invalid bus type\n"); + return DF_BUS_ERROR; + } - // Synchronously connects to the system bus daemon. - fprintf(stderr, "%s%s[SYSTEM BUS]%s\n", ansi_cr(), ansi_cyan(), ansi_normal()); - if ((dcon = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error)) == NULL) { - df_fail("System bus not found.\n"); + dcon = g_bus_get_sync(bus_type, NULL, &error); + if (!dcon) { + df_fail("Bus not found.\n"); df_error("Error in g_bus_get_sync()", error); - error = NULL; - bus_skip = 1; - goto skip_system; + return DF_BUS_SKIP; } + if (df_list_names) { // list names on the bus if (df_list_bus_names(dcon) == -1) { - df_debug("Error in df_list_bus_names() for system bus\n"); - rsys = 1; + df_debug("Error in df_list_bus_names() for session bus\n"); + return DF_BUS_ERROR; } } else { // gets pid of tested process df_pid = df_get_pid(dcon); if (df_pid > 0) { df_print_process_info(df_pid); - fprintf(stderr, "%s%s[CONNECTED TO PID: %d]%s\n", - ansi_cr(), ansi_cyan(), df_pid, ansi_normal()); - if (strlen(target_proc.interface) != 0) { - fprintf(stderr, "Object: %s%s%s\n", - ansi_bold(), target_proc.obj_path, ansi_normal()); - fprintf(stderr, " Interface: %s%s%s\n", - ansi_bold(), target_proc.interface, ansi_normal()); - if (!df_is_object_on_bus(dcon, root_node)) { - df_fail("Error: Unknown object path '%s'.\n", - target_proc.obj_path); - rsys = 1; - } else { - rsys = df_fuzz(dcon, target_proc.name, target_proc.obj_path, - target_proc.interface); - } - } else if (strlen(target_proc.obj_path) != 0) { - fprintf(stderr, "Object: %s%s%s\n", - ansi_bold(), target_proc.obj_path, ansi_normal()); - if (!df_is_object_on_bus(dcon, root_node)) { - df_fail("Error: Unknown object path '%s'.\n", - target_proc.obj_path); - rsys = 1; + fprintf(stderr, "%s%s[CONNECTED TO PID: %d]%s\n", ansi_cr(), ansi_cyan(), df_pid, ansi_normal()); + if (!isempty(target_proc.interface)) { + fprintf(stderr, "Object: %s%s%s\n", ansi_bold(), target_proc.obj_path, ansi_normal()); + fprintf(stderr, " Interface: %s%s%s\n", ansi_bold(), target_proc.interface, ansi_normal()); + if (!df_is_object_on_bus(dcon, DF_BUS_ROOT_NODE)) { + df_fail("Error: Unknown object path '%s'.\n", target_proc.obj_path); + return DF_BUS_ERROR; } else - rsys = df_traverse_node(dcon, target_proc.obj_path); + return df_fuzz(dcon, target_proc.name, target_proc.obj_path, target_proc.interface); + } else if (!isempty(target_proc.obj_path)) { + fprintf(stderr, "Object: %s%s%s\n", ansi_bold(), target_proc.obj_path, ansi_normal()); + if (!df_is_object_on_bus(dcon, DF_BUS_ROOT_NODE)) { + df_fail("Error: Unknown object path '%s'.\n", target_proc.obj_path); + return DF_BUS_ERROR; + } else + return df_traverse_node(dcon, target_proc.obj_path); } else { fprintf(stderr, "Object: %s/%s\n", ansi_bold(), ansi_normal()); - rsys = df_traverse_node(dcon, root_node); + return df_traverse_node(dcon, DF_BUS_ROOT_NODE); } - } else - rsys = 1; - } - g_object_unref(dcon); - - -skip_system: - - - // free all suppressions and their descriptions - if (df_suppression != NULL) { - for (i = 0; df_suppression[i] != NULL; i++) - free(df_suppression[i]); - } - if (df_supp_description != NULL) { - for (i = 0; df_supp_description[i] != NULL; i++) - free(df_supp_description[i]); + } else { + df_fail("Couldn't get the PID of the tested process\n"); + return DF_BUS_NO_PID; + } } - // both tests ended with error - if (rses == 1 && rsys == 1) { - fprintf(stderr, "%sExit status: 1%s\n", ansi_bold(), ansi_normal()); - return 1; - } else if (bus_skip == 1 && (rses == 1 || rsys == 1)) { - fprintf(stderr, "%sExit status: 1%s\n", ansi_bold(), ansi_normal()); - return 1; - } else if (rses == 2 || rsys == 2) { - // at least one test found failures - fprintf(stderr, "%sExit status: 2%s\n", ansi_bold(), ansi_normal()); - return 2; - } else if (rses == 3 || rsys == 3) { - // at least one test found warnings - fprintf(stderr, "%sExit status: 3%s\n", ansi_bold(), ansi_normal()); - return 3; - } else { - // cases where rses=1,rsys=0 or rses=0,rsys=1 are ok, - // because tests on one of the bus daemons finished - // successfuly - fprintf(stderr, "%sExit status: 0%s\n", ansi_bold(), ansi_normal()); - return 0; - } + return DF_BUS_OK; } /** @@ -478,13 +419,13 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) /** Information about a D-Bus interface. */ GDBusInterfaceInfo *interface = NULL; /** Return values */ - int rd = 0; // return value from df_fuzz() - int rt = 0; // return value from recursive transition - int ret = 0; // return value of this function + int rd = 0; // return value from df_fuzz() + int rt = 0; // return value from recursive transition + int ret = DF_BUS_OK; // return value of this function if (!df_is_valid_dbus(target_proc.name, root_node, intro_iface)) - return 1; + return DF_BUS_ERROR; dproxy = g_dbus_proxy_new_sync( dcon, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, @@ -497,10 +438,9 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) if (!dproxy) { df_fail("Error: Unable to create proxy for bus name '%s'.\n", target_proc.name); df_error("Error in g_dbus_proxy_new_sync()", error); - return 1; + return DF_BUS_ERROR; } - response = g_dbus_proxy_call_sync( dproxy, intro_method, @@ -518,28 +458,28 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) if (strcmp(dbus_error, "org.freedesktop.DBus.Error.NoReply") == 0) { g_free(dbus_error); g_error_free(error); - return 2; + return DF_BUS_FAIL; } if (strcmp(dbus_error, "org.freedesktop.DBus.Error.Timeout") == 0) { g_free(dbus_error); g_error_free(error); - return 2; + return DF_BUS_FAIL; } g_free(dbus_error); g_error_free(error); - return 0; + return DF_BUS_OK; } else { g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); df_error("Error in g_dbus_proxy_call_sync()", error); - return 1; + return DF_BUS_ERROR; } } g_variant_get(response, "(s)", &introspection_xml); g_variant_unref(response); if (!introspection_xml) { df_fail("Error: Unable to get introspection data from GVariant.\n"); - return 1; + return DF_BUS_ERROR; } // Parses introspection_xml and returns a GDBusNodeInfo representing @@ -550,10 +490,9 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) df_fail("Error: Unable to get introspection data.\n"); df_error("Error in g_dbus_node_info_new_for_xml()", error); g_object_unref(dproxy); - return 1; + return DF_BUS_ERROR; } - // go through all interfaces i = 0; interface = node_data->interfaces[i++]; @@ -562,12 +501,12 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) ansi_bold(), interface->name, ansi_normal()); // start fuzzing on the target_proc.name rd = df_fuzz(dcon, target_proc.name, root_node, interface->name); - if (rd == 1) { + if (rd == DF_BUS_ERROR) { g_dbus_node_info_unref(node_data); g_object_unref(dproxy); - return 1; - } else if (ret != 2) { - if (rd != 0) + return DF_BUS_ERROR; + } else if (ret != DF_BUS_FAIL) { + if (rd != DF_BUS_OK) ret = rd; } interface = node_data->interfaces[i++]; @@ -588,7 +527,7 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) df_fail("Error: Could not allocate memory for root_node string.\n"); g_dbus_node_info_unref(node_data); g_object_unref(dproxy); - return 1; + return DF_BUS_ERROR; } if (strlen(root_node) == 1) sprintf(object, "%s%s", root_node, node->path); @@ -596,13 +535,13 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) sprintf(object, "%s/%s", root_node, node->path); fprintf(stderr, "Object: %s%s%s\n", ansi_bold(), object, ansi_normal()); rt = df_traverse_node(dcon, object); - if (rt == 1) { + if (rt == DF_BUS_ERROR) { free(object); g_dbus_node_info_unref(node_data); g_object_unref(dproxy); - return 1; - } else if (ret != 2) { - if (rt != 0) + return DF_BUS_ERROR; + } else if (ret != DF_BUS_FAIL) { + if (rt != DF_BUS_OK) ret = rt; } free(object); @@ -637,20 +576,20 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons GDBusProxy *dproxy; // D-Bus interface proxy int statfd; // FD for process status file GError *error = NULL; // must be set to NULL - int rv = 0; // return value of function + int rv = DF_BUS_OK; // return value of function int i; // Sanity check fuzzing target if (isempty(name) || isempty(obj) || isempty(intf)) { df_fail("Error in target specification.\n"); - return 1; + return DF_BUS_ERROR; } // Creates a proxy for accessing intf on the remote object at path obj // owned by name at dcon. if (!df_is_valid_dbus(name, obj, intf)) - return 1; + return DF_BUS_ERROR; dproxy = g_dbus_proxy_new_sync( dcon, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, @@ -663,14 +602,14 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons if (!dproxy) { df_fail("Error: Unable to create proxy for bus name '%s'.\n", name); df_error("Error in g_dbus_proxy_new_sync() on creating proxy", error); - return 1; + return DF_BUS_ERROR; } // Introspection of object through proxy. if (df_init_introspection(dproxy, name, intf) == -1) { g_object_unref(dproxy); df_debug("Error in df_init_introspection() on introspecting object\n"); - return 1; + return DF_BUS_ERROR; } // opens process status file @@ -679,7 +618,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_open_proc_status_file()\n"); - return 1; + return DF_BUS_ERROR; } // tells fuzz module to call methods on dproxy, use FD statfd @@ -689,7 +628,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_fuzz_add_proxy()\n"); - return 1; + return DF_BUS_ERROR; } for (; (m = df_get_method()) != NULL; df_next_method()) @@ -730,7 +669,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_fuzz_add_method()\n"); - return 1; + return DF_BUS_ERROR; } for (; (in_arg = df_get_method_arg()) != NULL; df_next_method_arg()) { @@ -740,7 +679,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_fuzz_add_method_arg()\n"); - return 1; + return DF_BUS_ERROR; } } @@ -767,13 +706,13 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_fuzz_test_method()\n"); - return 1; + return DF_BUS_ERROR; } else if (ret == 1 && df_test_method == NULL) { // launch process again after crash - rv = 2; + rv = DF_BUS_FAIL; g_object_unref(dproxy); if (!df_is_valid_dbus(name, obj, intf)) - return 1; + return DF_BUS_ERROR; dproxy = g_dbus_proxy_new_sync(dcon, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, @@ -784,7 +723,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); df_fail("Error: Unable to create proxy for bus name '%s'.\n", name); df_error("Error in g_dbus_proxy_new_sync() on creating proxy", error); - return 1; + return DF_BUS_ERROR; } sleep(5); // wait for application to launch @@ -797,7 +736,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_get_pid() on getting pid of process\n"); - return 1; + return DF_BUS_ERROR; } fprintf(stderr, "%s%s[RE-CONNECTED TO PID: %d]%s\n", ansi_cr(), ansi_cyan(), df_pid, ansi_blue()); @@ -810,7 +749,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_open_proc_status_file()\n"); - return 1; + return DF_BUS_ERROR; } // tells fuzz module to call methods on different dproxy and to use @@ -821,21 +760,21 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons df_unref_introspection(); g_object_unref(dproxy); df_debug("Error in df_fuzz_add_proxy()\n"); - return 1; + return DF_BUS_ERROR; } } else if (ret == 1 && df_test_method != NULL) { // for one method, testing ends with failure - rv = 2; + rv = DF_BUS_FAIL; } else if (ret == 2) { // method returning void is returning illegal value - rv = 2; + rv = DF_BUS_FAIL; } else if (ret == 3) { // warnings if (rv != 2) - rv = 3; + rv = DF_BUS_WARNING; } else if (ret == 4) { // executed command finished unsuccessfuly - rv = 2; + rv = DF_BUS_FAIL; } df_fuzz_clean_method(); // cleaning up after testing method diff --git a/src/dfuzzer.h b/src/dfuzzer.h index 1aa6d7b..3f828de 100644 --- a/src/dfuzzer.h +++ b/src/dfuzzer.h @@ -37,6 +37,24 @@ /** Maximum length of strings containing D-Bus name, interface and object path */ #define MAXLEN 256 +#define DF_BUS_ROOT_NODE "/" + +enum { + DF_BUS_OK = 0, + DF_BUS_SKIP, + DF_BUS_NO_PID, + DF_BUS_WARNING, + DF_BUS_FAIL, + DF_BUS_ERROR +}; + +static inline void g_object_unrefp(gpointer *gobj) { + if (!*gobj) + return; + + g_object_unref(*gobj); +} + static inline void closep(int *fd) { if (*fd < 0) return; @@ -103,6 +121,8 @@ DEFINE_ANSI_FUNC(normal, NORMAL); DEFINE_ANSI_FUNC(bold, BOLD); DEFINE_ANSI_FUNC(cr, CR); +int df_process_bus(GBusType bus_type); + /** * @function Calls method ListNames to get all available connection names * on the bus and prints them on the program output. From 90dbd3c1d5593f432adee8bc3876a45486a629fc Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 12:52:22 +0100 Subject: [PATCH 08/13] Move auxiliary functions to their own files --- src/Makefile | 2 +- src/dfuzzer.c | 1 + src/dfuzzer.h | 62 ------------------------------------ src/fuzz.c | 1 + src/util.c | 1 + src/util.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 63 deletions(-) create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/src/Makefile b/src/Makefile index 83f0c26..2abf2d1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,7 +5,7 @@ CC ?= gcc CFLAGS += -Wall -w -O2 -D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 `pkg-config --cflags --libs gio-2.0 libffi` -g -OBJ = dfuzzer.o introspection.o fuzz.o rand.o +OBJ = dfuzzer.o introspection.o fuzz.o rand.o util.o TARGET = dfuzzer all: dfuzzer .PHONY: doc man clean install diff --git a/src/dfuzzer.c b/src/dfuzzer.c index b7fd81f..157429c 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -32,6 +32,7 @@ #include "dfuzzer.h" #include "introspection.h" #include "fuzz.h" +#include "util.h" /** Structure containing D-Bus name, object path and interface of process */ diff --git a/src/dfuzzer.h b/src/dfuzzer.h index 3f828de..d8219c2 100644 --- a/src/dfuzzer.h +++ b/src/dfuzzer.h @@ -48,37 +48,6 @@ enum { DF_BUS_ERROR }; -static inline void g_object_unrefp(gpointer *gobj) { - if (!*gobj) - return; - - g_object_unref(*gobj); -} - -static inline void closep(int *fd) { - if (*fd < 0) - return; - - close(*fd); -} - -#define _cleanup_(x) __attribute__((__cleanup__(x))) -#define _cleanup_close_ _cleanup_(closep) - -static inline int isempty(const char *s) { - return !s || s[0] == '\0'; -} - -/* Returns the number of chars needed to format variables of the - * specified type as a decimal string. Adds in extra space for a - * negative '-' prefix (hence works correctly on signed - * types). Includes space for the trailing NUL. */ -#define DECIMAL_STR_MAX(type) \ - (2U+(sizeof(type) <= 1 ? 3U : \ - sizeof(type) <= 2 ? 5U : \ - sizeof(type) <= 4 ? 10U : \ - sizeof(type) <= 8 ? 20U : sizeof(int[-2*(sizeof(type) > 8)]))) - /** Structure containing D-Bus name, object path and interface of process. */ struct fuzzing_target { /* names on D-Bus have the most MAXLEN characters */ @@ -90,37 +59,6 @@ struct fuzzing_target { char *interface; }; -#define ANSI_RED "\x1B[0;31m" -#define ANSI_GREEN "\x1B[0;32m" -#define ANSI_YELLOW "\x1B[0;33m" -#define ANSI_BLUE "\x1B[0;34m" -#define ANSI_MAGENTA "\x1B[0;35m" -#define ANSI_CYAN "\x1B[0;36m" - -#define ANSI_NORMAL "\x1B[0m" -#define ANSI_BOLD "\x1B[1m" - -#define ANSI_CR "\r" - -static inline int df_isatty(void) { - return isatty(STDOUT_FILENO) && isatty(STDERR_FILENO); -} - -#define DEFINE_ANSI_FUNC(name, NAME) \ - static inline const char *ansi_##name(void) { \ - return df_isatty() ? ANSI_##NAME : ""; \ - } - -DEFINE_ANSI_FUNC(red, RED); -DEFINE_ANSI_FUNC(green, GREEN); -DEFINE_ANSI_FUNC(yellow, YELLOW); -DEFINE_ANSI_FUNC(blue, BLUE); -DEFINE_ANSI_FUNC(magenta, MAGENTA); -DEFINE_ANSI_FUNC(cyan, CYAN); -DEFINE_ANSI_FUNC(normal, NORMAL); -DEFINE_ANSI_FUNC(bold, BOLD); -DEFINE_ANSI_FUNC(cr, CR); - int df_process_bus(GBusType bus_type); /** diff --git a/src/fuzz.c b/src/fuzz.c index 834f153..175d7d2 100644 --- a/src/fuzz.c +++ b/src/fuzz.c @@ -33,6 +33,7 @@ #include "fuzz.h" #include "dfuzzer.h" #include "rand.h" +#include "util.h" /** Pointer on D-Bus interface proxy for calling methods. */ diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..7f74750 --- /dev/null +++ b/src/util.c @@ -0,0 +1 @@ +/** @file util.c */ diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..1855224 --- /dev/null +++ b/src/util.h @@ -0,0 +1,87 @@ +/** @file util.h */ +#pragma once + +static inline void g_object_unrefp(gpointer *gobj) { + if (!*gobj) + return; + + g_object_unref(*gobj); +} + +static inline void closep(int *fd) { + if (*fd < 0) + return; + + close(*fd); +} + +#define _cleanup_(x) __attribute__((__cleanup__(x))) +#define _cleanup_close_ _cleanup_(closep) + +static inline int isempty(const char *s) { + return !s || s[0] == '\0'; +} + +/* Returns the number of chars needed to format variables of the + * specified type as a decimal string. Adds in extra space for a + * negative '-' prefix (hence works correctly on signed + * types). Includes space for the trailing NUL. */ +#define DECIMAL_STR_MAX(type) \ + (2U+(sizeof(type) <= 1 ? 3U : \ + sizeof(type) <= 2 ? 5U : \ + sizeof(type) <= 4 ? 10U : \ + sizeof(type) <= 8 ? 20U : sizeof(int[-2*(sizeof(type) > 8)]))) + +#define ELEMENTSOF(x) \ + (__builtin_choose_expr( \ + !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ + sizeof(x)/sizeof((x)[0]), \ + (void*)0)) + +#define strjoina(a, ...) \ + ({ \ + const char *_appendees_[] = { a, __VA_ARGS__ }; \ + char *_d_, *_p_; \ + size_t _len_ = 0; \ + size_t _i_; \ + for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ + _len_ += strlen(_appendees_[_i_]); \ + _p_ = _d_ = alloca(_len_ + 1); \ + for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ + _p_ = stpcpy(_p_, _appendees_[_i_]); \ + *_p_ = 0; \ + _d_; \ + }) + +#define ANSI_RED "\x1B[0;31m" +#define ANSI_GREEN "\x1B[0;32m" +#define ANSI_YELLOW "\x1B[0;33m" +#define ANSI_BLUE "\x1B[0;34m" +#define ANSI_MAGENTA "\x1B[0;35m" +#define ANSI_CYAN "\x1B[0;36m" + +#define ANSI_NORMAL "\x1B[0m" +#define ANSI_BOLD "\x1B[1m" + +#define ANSI_CR "\r" + +static inline int df_isatty(void) { + return isatty(STDOUT_FILENO) && isatty(STDERR_FILENO); +} + +#define DEFINE_ANSI_FUNC(name, NAME) \ + static inline const char *ansi_##name(void) { \ + return df_isatty() ? ANSI_##NAME : ""; \ + } + +DEFINE_ANSI_FUNC(red, RED); +DEFINE_ANSI_FUNC(green, GREEN); +DEFINE_ANSI_FUNC(yellow, YELLOW); +DEFINE_ANSI_FUNC(blue, BLUE); +DEFINE_ANSI_FUNC(magenta, MAGENTA); +DEFINE_ANSI_FUNC(cyan, CYAN); +DEFINE_ANSI_FUNC(normal, NORMAL); +DEFINE_ANSI_FUNC(bold, BOLD); +DEFINE_ANSI_FUNC(cr, CR); + + From ea1344684055df2c5426903f114be9fc4336495a Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 14:03:29 +0100 Subject: [PATCH 09/13] Utilize cleanup macros for handling deallocations --- src/dfuzzer.c | 197 ++++++++++++++++---------------------------------- src/fuzz.c | 99 +++++++++---------------- src/util.c | 37 ++++++++++ src/util.h | 38 +++++++--- 4 files changed, 161 insertions(+), 210 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index 157429c..8c94615 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -86,25 +86,17 @@ FILE* logfile; */ int main(int argc, char **argv) { + const char *log_file_name; int rses = 0; // return value from session bus testing int rsys = 0; // return value from system bus testing int ret = 0; - char log_file_name[MAXLEN]; - df_parse_parameters(argc, argv); if (df_full_log_flag) { - size_t len = strlen(log_dir_name); - strcpy(log_file_name, log_dir_name); - if (len <= MAXLEN-2) { - log_file_name[len++] = '/'; - log_file_name[len] = 0; - strncat(log_file_name, target_proc.name, MAXLEN-len-1); - logfile = fopen(log_file_name, "a+"); - } + log_file_name = strjoina(log_dir_name, "/", target_proc.name); + logfile = fopen(log_file_name, "a+"); if(!logfile) { - df_fail("Error opening file %s; detailed logs will not be written\n", - log_file_name); + df_fail("Error opening file %s; detailed logs will not be written\n", log_file_name); df_full_log_flag = 0; } } @@ -160,7 +152,7 @@ int main(int argc, char **argv) int df_process_bus(GBusType bus_type) { _cleanup_(g_object_unrefp) GDBusConnection *dcon = NULL; - GError *error = NULL; + _cleanup_(g_error_freep) GError *error = NULL; int ret = DF_BUS_OK; switch (bus_type) { @@ -230,13 +222,12 @@ int df_process_bus(GBusType bus_type) */ int df_list_bus_names(const GDBusConnection *dcon) { - GError *error = NULL; // must be set to NULL - GDBusProxy *proxy; // proxy for getting bus names - GVariant *response = NULL; // response from method ListNames - GVariantIter *iter; + _cleanup_(g_object_unrefp) GDBusProxy *proxy = NULL; // proxy for getting bus names + _cleanup_(g_variant_iter_freep) GVariantIter *iter = NULL; + _cleanup_(g_variant_unrefp) GVariant *response = NULL; // response from method ListNames + _cleanup_(g_error_freep) GError *error = NULL; // must be set to NULL char *str; - // Uses dcon (GDBusConnection *) to create proxy for accessing // org.freedesktop.DBus (for calling its method ListNames) proxy = g_dbus_proxy_new_sync( @@ -267,18 +258,14 @@ int df_list_bus_names(const GDBusConnection *dcon) g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); df_error("Error in g_dbus_proxy_call_sync()", error); - g_object_unref(proxy); return -1; } - g_object_unref(proxy); g_variant_get(response, "(as)", &iter); while (g_variant_iter_loop(iter, "s", &str)) { if (str[0] != ':') printf("%s\n", str); } - g_variant_iter_free(iter); - g_variant_unref(response); return 0; } @@ -295,18 +282,16 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) { char *intro_iface = "org.freedesktop.DBus.Introspectable"; char *intro_method = "Introspect"; - GVariant *response = NULL; - GDBusProxy *dproxy = NULL; - GError *error = NULL; - gchar *introspection_xml = NULL; + _cleanup_(g_variant_unrefp) GVariant *response = NULL; + _cleanup_(g_object_unrefp) GDBusProxy *dproxy = NULL; + _cleanup_(g_freep) gchar *introspection_xml = NULL; + _cleanup_(g_error_freep) GError *error = NULL; /** Information about nodes in a remote object hierarchy. */ - GDBusNodeInfo *node_data = NULL; + _cleanup_(g_dbus_node_info_unrefp) GDBusNodeInfo *node_data = NULL; GDBusNodeInfo *node = NULL; - char *object = NULL; int i = 0; int ret = 0; // return value of this function - if (strstr(root_node, target_proc.obj_path) != NULL) return 1; @@ -336,14 +321,12 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) NULL, &error); if (!response) { - g_object_unref(dproxy); g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); df_error("Error in g_dbus_proxy_call_sync()", error); return 0; } g_variant_get(response, "(s)", &introspection_xml); - g_variant_unref(response); if (!introspection_xml) { df_fail("Error: Unable to get introspection data from GVariant.\n"); return 0; @@ -352,11 +335,9 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) // Parses introspection_xml and returns a GDBusNodeInfo representing // the data. node_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); - g_free(introspection_xml); if (!node_data) { df_fail("Error: Unable to get introspection data.\n"); df_error("Error in g_dbus_node_info_new_for_xml()", error); - g_object_unref(dproxy); return 0; } @@ -364,33 +345,22 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) i = 0; node = node_data->nodes[i++]; while (node != NULL) { + _cleanup_free_ char *object = NULL; // create next object path - object = (char *) calloc(strlen(node->path) + strlen(root_node) + 3, sizeof(char)); + object = strjoin(root_node, strlen(root_node) == 1 ? "" : "/", node->path); if (object == NULL) { - df_fail("Error: Could not allocate memory for root_node string.\n"); - g_dbus_node_info_unref(node_data); - g_object_unref(dproxy); - return 0; + df_fail("Error: Could not allocate memory for object string.\n"); + return DF_BUS_ERROR; } - if (strlen(root_node) == 1) - sprintf(object, "%s%s", root_node, node->path); - else - sprintf(object, "%s/%s", root_node, node->path); ret = df_is_object_on_bus(dcon, object); if (ret == 1) { free(object); - g_dbus_node_info_unref(node_data); - g_object_unref(dproxy); return 1; } - free(object); // move to next node node = node_data->nodes[i++]; } - // cleanup - g_dbus_node_info_unref(node_data); - g_object_unref(dproxy); return ret; } @@ -408,12 +378,12 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) { char *intro_iface = "org.freedesktop.DBus.Introspectable"; char *intro_method = "Introspect"; - GVariant *response = NULL; - GDBusProxy *dproxy = NULL; - GError *error = NULL; - gchar *introspection_xml = NULL; + _cleanup_(g_variant_unrefp) GVariant *response = NULL; + _cleanup_(g_object_unrefp) GDBusProxy *dproxy = NULL; + _cleanup_(g_freep) gchar *introspection_xml = NULL; + _cleanup_(g_error_freep) GError *error = NULL; /** Information about nodes in a remote object hierarchy. */ - GDBusNodeInfo *node_data = NULL; + _cleanup_(g_dbus_node_info_unrefp) GDBusNodeInfo *node_data = NULL; GDBusNodeInfo *node = NULL; char *object = NULL; int i = 0; @@ -451,23 +421,14 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) NULL, &error); if (!response) { - g_object_unref(dproxy); - gchar *dbus_error = NULL; + _cleanup_(g_freep) gchar *dbus_error = NULL; // D-Bus exceptions if ((dbus_error = g_dbus_error_get_remote_error(error)) != NULL) { // if process does not respond - if (strcmp(dbus_error, "org.freedesktop.DBus.Error.NoReply") == 0) { - g_free(dbus_error); - g_error_free(error); + if (strcmp(dbus_error, "org.freedesktop.DBus.Error.NoReply") == 0) return DF_BUS_FAIL; - } - if (strcmp(dbus_error, "org.freedesktop.DBus.Error.Timeout") == 0) { - g_free(dbus_error); - g_error_free(error); + if (strcmp(dbus_error, "org.freedesktop.DBus.Error.Timeout") == 0) return DF_BUS_FAIL; - } - g_free(dbus_error); - g_error_free(error); return DF_BUS_OK; } else { g_dbus_error_strip_remote_error(error); @@ -477,7 +438,6 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) } } g_variant_get(response, "(s)", &introspection_xml); - g_variant_unref(response); if (!introspection_xml) { df_fail("Error: Unable to get introspection data from GVariant.\n"); return DF_BUS_ERROR; @@ -486,11 +446,9 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) // Parses introspection_xml and returns a GDBusNodeInfo representing // the data. node_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); - g_free(introspection_xml); if (!node_data) { df_fail("Error: Unable to get introspection data.\n"); df_error("Error in g_dbus_node_info_new_for_xml()", error); - g_object_unref(dproxy); return DF_BUS_ERROR; } @@ -502,11 +460,9 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) ansi_bold(), interface->name, ansi_normal()); // start fuzzing on the target_proc.name rd = df_fuzz(dcon, target_proc.name, root_node, interface->name); - if (rd == DF_BUS_ERROR) { - g_dbus_node_info_unref(node_data); - g_object_unref(dproxy); + if (rd == DF_BUS_ERROR) return DF_BUS_ERROR; - } else if (ret != DF_BUS_FAIL) { + else if (ret != DF_BUS_FAIL) { if (rd != DF_BUS_OK) ret = rd; } @@ -522,37 +478,25 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) i = 0; node = node_data->nodes[i++]; while (node != NULL) { + _cleanup_free_ char *object = NULL; // create next object path - object = (char *) calloc(strlen(node->path) + strlen(root_node) + 3, sizeof(char)); + object = strjoin(root_node, strlen(root_node) == 1 ? "" : "/", node->path); if (object == NULL) { df_fail("Error: Could not allocate memory for root_node string.\n"); - g_dbus_node_info_unref(node_data); - g_object_unref(dproxy); return DF_BUS_ERROR; } - if (strlen(root_node) == 1) - sprintf(object, "%s%s", root_node, node->path); - else - sprintf(object, "%s/%s", root_node, node->path); fprintf(stderr, "Object: %s%s%s\n", ansi_bold(), object, ansi_normal()); rt = df_traverse_node(dcon, object); - if (rt == DF_BUS_ERROR) { - free(object); - g_dbus_node_info_unref(node_data); - g_object_unref(dproxy); + if (rt == DF_BUS_ERROR) return DF_BUS_ERROR; - } else if (ret != DF_BUS_FAIL) { + else if (ret != DF_BUS_FAIL) { if (rt != DF_BUS_OK) ret = rt; } - free(object); // move to next node node = node_data->nodes[i++]; } - // cleanup - g_dbus_node_info_unref(node_data); - g_object_unref(dproxy); return ret; } @@ -568,15 +512,15 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) */ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, const char *intf) { + _cleanup_(g_object_unrefp) GDBusProxy *dproxy; // D-Bus interface proxy + _cleanup_(g_error_freep) GError *error = NULL; GDBusMethodInfo *m; GDBusArgInfo *in_arg; + _cleanup_(closep) int statfd = -1; int ret = 0; int method_found = 0; // If df_test_method is found in an interface, // method_found is set to 1, otherwise is 0. int void_method; // If method has out args 1, 0 otherwise. - GDBusProxy *dproxy; // D-Bus interface proxy - int statfd; // FD for process status file - GError *error = NULL; // must be set to NULL int rv = DF_BUS_OK; // return value of function int i; @@ -608,7 +552,6 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // Introspection of object through proxy. if (df_init_introspection(dproxy, name, intf) == -1) { - g_object_unref(dproxy); df_debug("Error in df_init_introspection() on introspecting object\n"); return DF_BUS_ERROR; } @@ -617,7 +560,6 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons statfd = df_open_proc_status_file(df_pid); if (statfd == -1) { df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_open_proc_status_file()\n"); return DF_BUS_ERROR; } @@ -625,15 +567,12 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // tells fuzz module to call methods on dproxy, use FD statfd // for monitoring tested process and memory limit for process if (df_fuzz_init(dproxy, statfd, df_pid, df_mem_limit) == -1) { - close(statfd); df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_fuzz_add_proxy()\n"); return DF_BUS_ERROR; } - for (; (m = df_get_method()) != NULL; df_next_method()) - { + for (; (m = df_get_method()) != NULL; df_next_method()) { // testing only one method with name df_test_method if (df_test_method != NULL) { if (strcmp(df_test_method, m->name) != 0) { @@ -666,9 +605,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // adds method name to the fuzzing module if (df_fuzz_add_method(m->name) == -1) { - close(statfd); df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_fuzz_add_method()\n"); return DF_BUS_ERROR; } @@ -676,9 +613,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons for (; (in_arg = df_get_method_arg()) != NULL; df_next_method_arg()) { // adds method argument signature to the fuzzing module if (df_fuzz_add_method_arg(in_arg->signature) == -1) { - close(statfd); df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_fuzz_add_method_arg()\n"); return DF_BUS_ERROR; } @@ -698,28 +633,39 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons void_method = 1; // tests for method - ret = df_fuzz_test_method(statfd, df_buf_size, name, obj, intf, - df_pid, void_method, df_execute_cmd); + ret = df_fuzz_test_method( + statfd, + df_buf_size, + name, + obj, + intf, + df_pid, + void_method, + df_execute_cmd); if (ret == -1) { // error during testing method - close(statfd); df_fuzz_clean_method(); df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_fuzz_test_method()\n"); return DF_BUS_ERROR; } else if (ret == 1 && df_test_method == NULL) { // launch process again after crash rv = DF_BUS_FAIL; g_object_unref(dproxy); + dproxy = NULL; + if (!df_is_valid_dbus(name, obj, intf)) return DF_BUS_ERROR; - dproxy = g_dbus_proxy_new_sync(dcon, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES - | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, name, obj, intf, NULL, &error); - if (dproxy == NULL) { - close(statfd); + dproxy = g_dbus_proxy_new_sync( + dcon, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + name, + obj, + intf, + NULL, + &error); + if (!dproxy) { df_fuzz_clean_method(); df_unref_introspection(); df_fail("Error: Unable to create proxy for bus name '%s'.\n", name); @@ -732,10 +678,8 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // gets pid of tested process df_pid = df_get_pid(dcon); if (df_pid < 0) { - close(statfd); df_fuzz_clean_method(); df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_get_pid() on getting pid of process\n"); return DF_BUS_ERROR; } @@ -744,11 +688,10 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // opens process status file close(statfd); + statfd = -1; if ((statfd = df_open_proc_status_file(df_pid)) == -1) { - close(statfd); df_fuzz_clean_method(); df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_open_proc_status_file()\n"); return DF_BUS_ERROR; } @@ -756,10 +699,8 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons // tells fuzz module to call methods on different dproxy and to use // new status file of process with PID df_pid if (df_fuzz_init(dproxy, statfd, df_pid, df_mem_limit) == -1) { - close(statfd); df_fuzz_clean_method(); df_unref_introspection(); - g_object_unref(dproxy); df_debug("Error in df_fuzz_add_proxy()\n"); return DF_BUS_ERROR; } @@ -783,16 +724,11 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons if (method_found == 0 && df_test_method != NULL) { - df_fail("Error: Method '%s' is not in the interface '%s'.\n", - df_test_method, intf); + df_fail("Error: Method '%s' is not in the interface '%s'.\n", df_test_method, intf); df_unref_introspection(); - g_object_unref(dproxy); - close(statfd); return rv; } df_unref_introspection(); - g_object_unref(dproxy); - close(statfd); return rv; } @@ -849,9 +785,9 @@ int df_open_proc_status_file(const int pid) */ int df_get_pid(const GDBusConnection *dcon) { - GError *error = NULL; // must be set to NULL - GDBusProxy *pproxy; // proxy for getting process PID - GVariant *variant_pid = NULL; // response from GetConnectionUnixProcessID + _cleanup_(g_error_freep) GError *error = NULL; + _cleanup_(g_object_unrefp) GDBusProxy *pproxy = NULL; + _cleanup_(g_variant_unrefp) GVariant *variant_pid = NULL; int pid = -1; // Uses dcon (GDBusConnection *) to create proxy for accessing @@ -884,12 +820,9 @@ int df_get_pid(const GDBusConnection *dcon) g_dbus_error_strip_remote_error(error); df_fail("Error: %s.\n", error->message); df_error("Error in g_dbus_proxy_call_sync()", error); - g_object_unref(pproxy); return -1; } g_variant_get(variant_pid, "(u)", &pid); - g_variant_unref(variant_pid); - g_object_unref(pproxy); return pid; } @@ -1334,16 +1267,12 @@ void df_print_help(const char *name) void df_error(const char *message, GError *error) { if (!df_debug_flag) { - if (error != NULL) - g_error_free(error); return; } if (error == NULL) fprintf(stderr, "%s\n", message); - else { + else fprintf(stderr, "%s: %s\n", message, error->message); - g_error_free(error); - } } /** diff --git a/src/fuzz.c b/src/fuzz.c index 175d7d2..ffba25e 100644 --- a/src/fuzz.c +++ b/src/fuzz.c @@ -557,7 +557,7 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, return 0; struct df_signature *s = df_list.list; // pointer on the first signature - GVariant *value = NULL; + _cleanup_(g_variant_unrefp) GVariant *value = NULL; int ret = 0; // return value from df_fuzz_call_method() int execr = 0; // return value from execution of execute_cmd int leaking_mem_flg = 0; // if set to 1, leaks were detected @@ -591,7 +591,7 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, if (used_memory == -1) { df_fail("Error: Unable to get memory size of [PID:%d].\n", pid); df_debug("Error in df_fuzz_get_proc_mem_size()\n"); - goto err_label; + return -1; } prev_memory = used_memory; @@ -606,17 +606,18 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, df_unsupported_sig_str = NULL; df_verbose("%s %sSKIP%s %s - advanced signatures not yet implemented\n", ansi_cr(), ansi_blue(), ansi_normal(), df_list.df_method_name); - goto skip_label; + return 0; } + df_debug("Call of df_fuzz_create_variant() returned NULL pointer\n"); - goto err_label; + return -1; } ret = df_fuzz_call_method(value, void_method); execr = df_exec_cmd_check(execute_cmd); if (execr == -1) - goto err_label; + return -1; if (ret == -1) { // Here we look at process status file to be sure it really // exited. If file is readable it means process is @@ -638,7 +639,7 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, if (execr > 0) df_fail("%s '%s' returned %s%d%s\n", ansi_cr(), execute_cmd, ansi_red(), execr, ansi_normal()); - goto err_label; + return -1; } // else continue, we managed to get process memory size prev_memory = used_memory; @@ -663,12 +664,12 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, if (execr > 0) df_fail("%s '%s' returned %s%d%s\n", ansi_cr(), execute_cmd, ansi_red(), execr, ansi_normal()); - goto err_label; + return -1; } if (execr > 0) df_fail("%s '%s' returned %s%d%s\n", ansi_cr(), execute_cmd, ansi_red(), execr, ansi_normal()); - goto skip_label; + return 0; } if (execr > 0) { @@ -709,7 +710,7 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, if (execr > 0) df_fail("%s '%s' returned %s%d%s\n", ansi_cr(), execute_cmd, ansi_red(), execr, ansi_normal()); - goto err_label; + return -1; } // else continue, we managed to get process memory size prev_memory = used_memory; @@ -718,10 +719,6 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, if(logfile) df_fuzz_write_log(); FULL_LOG("Success\n"); - if (value != NULL) { - g_variant_unref(value); - value = NULL; - } if (df_except_counter == MAX_EXCEPTIONS) { df_except_counter = 0; break; @@ -744,8 +741,6 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, FULL_LOG("%s;%s;", intf, obj); df_fuzz_write_log(); } - if (value != NULL) - g_variant_unref(value); df_fail(" reproducer: %sdfuzzer -v -n %s -o %s -i %s -t %s", ansi_yellow(), name, obj, intf, df_list.df_method_name); @@ -765,19 +760,8 @@ int df_fuzz_test_method(const int statfd, long buf_size, const char *name, return 4; } FULL_LOG("Crash\n"); - return 1; - - -skip_label: - if (value != NULL) - g_variant_unref(value); - return 0; - -err_label: - if (value != NULL) - g_variant_unref(value); - return -1; + return 1; } /** @@ -798,7 +782,7 @@ static GVariant *df_fuzz_create_variant(void) // MAXSIG = max. amount of D-Bus signatures + 1 (format string) ffi_type *args[MAXSIG + 1]; void *values[MAXSIG + 1]; - char *fmt; // format string + _cleanup_free_ char *fmt = NULL; int ret; // creates GVariant for every item signature in linked list @@ -820,7 +804,6 @@ static GVariant *df_fuzz_create_variant(void) if (df_fuzz_create_fmt_string(&fmt, MAXFMT + 1) == -1) { df_fail("Error: Unable to create format string.\n"); df_debug("Error in df_fuzz_create_fmt_string()\n"); - free(fmt); return NULL; } @@ -843,7 +826,6 @@ static GVariant *df_fuzz_create_variant(void) // their owner } else { df_fail("ffi_prep_cif() failed on initializing cif.\n"); - free(fmt); return NULL; } @@ -857,11 +839,9 @@ static GVariant *df_fuzz_create_variant(void) if (g_variant_is_floating(val)) { df_fail("Error: Unable to convert GVariant from floating to normal" " reference\n(for method '%s()'.\n", df_list.df_method_name); - free(fmt); return NULL; } - free(fmt); return val; } @@ -910,38 +890,34 @@ static int df_fuzz_create_list_variants(void) s->var = g_variant_new(s->sig, df_rand_gdouble()); break; - case 's': - ; - gchar *buf; + case 's': { + _cleanup_(g_freep) gchar *buf = NULL; if (df_rand_string(&buf) == -1) { df_debug("In df_rand_string()\n"); return -1; } s->var = g_variant_new(s->sig, buf); - free(buf); break; - case 'o': - ; - gchar *obj; + } + case 'o': { + _cleanup_(g_freep) gchar *obj = NULL; if (df_rand_dbus_objpath_string(&obj) == -1) { df_debug("In df_rand_dbus_objpath_string()\n"); return -1; } s->var = g_variant_new(s->sig, obj); - free(obj); break; - case 'g': - ; - gchar *sig; + } + case 'g': { + _cleanup_(g_freep) gchar *sig = NULL; if (df_rand_dbus_signature_string(&sig) == -1) { df_debug("In df_rand_dbus_signature_string()\n"); return -1; } s->var = g_variant_new(s->sig, sig); - free(sig); break; - case 'v': - ; + } + case 'v': { GVariant *var; if (df_rand_GVariant(&var) == -1) { df_debug("In df_rand_GVariant()\n"); @@ -949,6 +925,7 @@ static int df_fuzz_create_list_variants(void) } s->var = g_variant_new(s->sig, var); break; + } case 'h': s->var = g_variant_new(s->sig, df_rand_unixFD()); break; @@ -1028,30 +1005,30 @@ static int df_fuzz_create_fmt_string(char **fmt, const int n) */ static int df_fuzz_call_method(const GVariant *value, const int void_method) { - GError *error = NULL; - GVariant *response = NULL; - gchar *dbus_error = NULL; + _cleanup_(g_error_freep) GError *error = NULL; + _cleanup_(g_variant_unrefp) GVariant *response = NULL; + _cleanup_(g_freep) gchar *dbus_error = NULL; gchar *fmt; // Synchronously invokes method with arguments stored in value (GVariant *) // on df_dproxy. - response = g_dbus_proxy_call_sync(df_dproxy, + response = g_dbus_proxy_call_sync( + df_dproxy, df_list.df_method_name, - value, G_DBUS_CALL_FLAGS_NONE, -1, - NULL, &error); + value, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); if (!response) { // D-Bus exceptions are accepted dbus_error = g_dbus_error_get_remote_error(error); if (dbus_error) { // if process does not respond - if (strcmp(dbus_error, "org.freedesktop.DBus.Error.NoReply") == 0) { - g_free(dbus_error); - g_error_free(error); + if (strcmp(dbus_error, "org.freedesktop.DBus.Error.NoReply") == 0) return -1; - } else if (strcmp(dbus_error, "org.freedesktop.DBus.Error.Timeout") == 0) { - g_free(dbus_error); - g_error_free(error); + else if (strcmp(dbus_error, "org.freedesktop.DBus.Error.Timeout") == 0) { sleep(10); // wait for tested process; processing // of longer inputs may take a longer time return -1; @@ -1060,23 +1037,19 @@ static int df_fuzz_call_method(const GVariant *value, const int void_method) df_verbose("%s %sSKIP%s %s - raised exception '%s'\n", ansi_cr(), ansi_blue(), ansi_normal(), df_list.df_method_name, dbus_error); - g_free(dbus_error); return 2; } - g_free(dbus_error); } g_dbus_error_strip_remote_error(error); if (strstr(error->message, "Timeout")) { df_verbose("%s %sSKIP%s %s - timeout reached\n", ansi_cr(), ansi_blue(), ansi_normal(), df_list.df_method_name); - g_error_free(error); return 2; } df_debug("%s EXCE %s - D-Bus exception thrown: %.60s\n", ansi_cr(), df_list.df_method_name, error->message); - g_error_free(error); df_except_counter++; return 0; } else { @@ -1087,13 +1060,11 @@ static int df_fuzz_call_method(const GVariant *value, const int void_method) if (strcmp(fmt, "()") != 0) { df_fail("%s %sFAIL%s %s - void method returns '%s' instead of '()'\n", ansi_cr(), ansi_red(), ansi_normal(), df_list.df_method_name, fmt); - g_variant_unref(response); return 1; } } } - g_variant_unref(response); return 0; } diff --git a/src/util.c b/src/util.c index 7f74750..3820eac 100644 --- a/src/util.c +++ b/src/util.c @@ -1 +1,38 @@ /** @file util.c */ + +#include +#include +#include +#include + +char *strjoin_real(const char *x, ...) { + va_list ap; + size_t l = 1; + char *r, *p; + + va_start(ap, x); + for (const char *t = x; t; t = va_arg(ap, const char *)) { + size_t n; + + n = strlen(t); + if (n > SIZE_MAX - l) { + va_end(ap); + return NULL; + } + l += n; + } + va_end(ap); + + p = r = malloc(l * sizeof(*p)); + if (!r) + return NULL; + + va_start(ap, x); + for (const char *t = x; t; t = va_arg(ap, const char *)) + p = stpcpy(p, t); + va_end(ap); + + *p = 0; + + return r; +} diff --git a/src/util.h b/src/util.h index 1855224..5f5c92f 100644 --- a/src/util.h +++ b/src/util.h @@ -1,21 +1,34 @@ /** @file util.h */ #pragma once -static inline void g_object_unrefp(gpointer *gobj) { - if (!*gobj) - return; +/* When func() returns the void value (NULL, -1, …) of the appropriate type */ +#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ + static inline void func##p(type *p) { \ + if (*p) \ + *p = func(*p); \ + } - g_object_unref(*gobj); -} +/* When func() doesn't return the appropriate type, set variable to empty afterwards */ +#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \ + static inline void func##p(type *p) { \ + if (*p != (empty)) { \ + func(*p); \ + *p = (empty); \ + } \ + } -static inline void closep(int *fd) { - if (*fd < 0) - return; +DEFINE_TRIVIAL_CLEANUP_FUNC(int, close); - close(*fd); -} +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, free, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gpointer, g_free, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gpointer, g_object_unref, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GVariantIter*, g_variant_iter_free, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GError*, g_error_free, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GVariant*, g_variant_unref, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GDBusNodeInfo*, g_dbus_node_info_unref, NULL); #define _cleanup_(x) __attribute__((__cleanup__(x))) +#define _cleanup_free_ _cleanup_(freep) #define _cleanup_close_ _cleanup_(closep) static inline int isempty(const char *s) { @@ -38,6 +51,9 @@ static inline int isempty(const char *s) { sizeof(x)/sizeof((x)[0]), \ (void*)0)) +char *strjoin_real(const char *x, ...) __attribute__((__sentinel__)); +#define strjoin(a, ...) strjoin_real((a), __VA_ARGS__, NULL) + #define strjoina(a, ...) \ ({ \ const char *_appendees_[] = { a, __VA_ARGS__ }; \ @@ -83,5 +99,3 @@ DEFINE_ANSI_FUNC(cyan, CYAN); DEFINE_ANSI_FUNC(normal, NORMAL); DEFINE_ANSI_FUNC(bold, BOLD); DEFINE_ANSI_FUNC(cr, CR); - - From 3a75efa74b215f159909afd9f919d23f0b18bf02 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 15:06:30 +0100 Subject: [PATCH 10/13] dfuzzer: rework exit status reporting --- src/dfuzzer.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/dfuzzer.c b/src/dfuzzer.c index 8c94615..aa3cb6f 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -112,28 +112,23 @@ int main(int argc, char **argv) rsys = df_process_bus(G_BUS_TYPE_SYSTEM); // both tests ended with error - if (rses == DF_BUS_ERROR || rsys == DF_BUS_ERROR) { - fprintf(stderr, "%sExit status: 1%s\n", ansi_bold(), ansi_normal()); + if (rses == DF_BUS_ERROR || rsys == DF_BUS_ERROR) ret = 1; - } else if (rses == DF_BUS_FAIL || rsys == DF_BUS_FAIL) { + else if (rses == DF_BUS_FAIL || rsys == DF_BUS_FAIL) // at least one test found failures - fprintf(stderr, "%sExit status: 2%s\n", ansi_bold(), ansi_normal()); ret = 2; - } else if (rses == DF_BUS_WARNING || rsys == DF_BUS_WARNING) { + else if (rses == DF_BUS_WARNING || rsys == DF_BUS_WARNING) // at least one test found warnings - fprintf(stderr, "%sExit status: 3%s\n", ansi_bold(), ansi_normal()); ret = 3; - } else if (rses == DF_BUS_NO_PID && rsys == DF_BUS_NO_PID) { - // we couldn't get the process ID on neither of the buses - fprintf(stderr, "%sExit status: 4%s\n", ansi_bold(), ansi_normal()); - ret = 4; - } else { - // cases where rses=1,rsys=0 or rses=0,rsys=1 are ok, - // because tests on one of the bus daemons finished - // successfuly - fprintf(stderr, "%sExit status: 0%s\n", ansi_bold(), ansi_normal()); + else if (rses == DF_BUS_OK || rsys == DF_BUS_OK) + // at least one of the tests passed (and the other one is not in + // a fail state) ret = 0; - } + else + // all remaining combinations, like both results missing + ret = 4; + + fprintf(stderr, "%sExit status: %d%s\n", ansi_bold(), ret, ansi_normal()); cleanup: // free all suppressions and their descriptions From 2e0adcdf8edfd401d6f56c180a37c62672eb1ff0 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Thu, 3 Mar 2022 14:59:26 +0100 Subject: [PATCH 11/13] ci: extend the tests a bit --- .github/workflows/build.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccc9db9..935781c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,7 +49,22 @@ jobs: - name: Test run: | + set -ex # Test as an unprivileged user (short options) dfuzzer -v -n org.freedesktop.systemd1 # Test as root (long options + duplicate options) sudo dfuzzer --verbose --bus this.should.be.ignored --bus org.freedesktop.systemd1 + # Test logdir + mkdir dfuzzer-logs + dfuzzer --log-dir dfuzzer-logs -v -n org.freedesktop.systemd1 + # Test a non-existent bus + if sudo dfuzzer --log-dir "" --bus this.should.not.exist; then false; fi + # Test object & interface options + dfuzzer -v --bus org.freedesktop.systemd1 --object / --interface org.freedesktop.DBus.Peer + sudo dfuzzer -v --bus org.freedesktop.systemd1 --object / --interface org.freedesktop.DBus.Peer + # - duplicate object/interface paths + dfuzzer -v --bus org.freedesktop.systemd1 --object xxx --object yyy --object / --interface org.freedesktop.DBus.Peer + dfuzzer -v --bus org.freedesktop.systemd1 --object xxx --object yyy --object / --interface zzz --interface org.freedesktop.DBus.Peer + # - test error paths + if dfuzzer -v --bus org.freedesktop.systemd1 --object aaa; then false; fi + if dfuzzer -v --bus org.freedesktop.systemd1 --interface aaa; then false; fi From 17c2a611d1f9f0cbe43e879072e4ed7790d004c8 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sat, 23 Apr 2022 13:57:54 +0200 Subject: [PATCH 12/13] tree-wide: drop -w and fix (almost) all compile-time warnings --- src/Makefile | 2 +- src/dfuzzer.c | 39 +++++++++++++++++---------------------- src/dfuzzer.h | 10 +++++----- src/fuzz.c | 38 +++++--------------------------------- src/fuzz.h | 10 ---------- src/introspection.c | 2 +- src/introspection.h | 3 +-- src/rand.c | 12 ++---------- src/rand.h | 5 ++++- src/util.h | 13 +++++++++++-- 10 files changed, 47 insertions(+), 87 deletions(-) diff --git a/src/Makefile b/src/Makefile index 2abf2d1..24b50b5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ #============================================================================== CC ?= gcc -CFLAGS += -Wall -w -O2 -D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 `pkg-config --cflags --libs gio-2.0 libffi` -g +CFLAGS += -Wall -Wno-unused-parameter -O2 -D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 `pkg-config --cflags --libs gio-2.0 libffi` -g OBJ = dfuzzer.o introspection.o fuzz.o rand.o util.o TARGET = dfuzzer all: dfuzzer diff --git a/src/dfuzzer.c b/src/dfuzzer.c index aa3cb6f..9b3ac25 100644 --- a/src/dfuzzer.c +++ b/src/dfuzzer.c @@ -132,23 +132,19 @@ int main(int argc, char **argv) cleanup: // free all suppressions and their descriptions - if (df_suppression) { - for (int i = 0; df_suppression[i]; i++) - free(df_suppression[i]); - } - if (df_supp_description) { - for (int i = 0; df_supp_description[i]; i++) - free(df_supp_description[i]); - } + for (int i = 0; df_suppression[i]; i++) + free(df_suppression[i]); + + for (int i = 0; df_supp_description[i]; i++) + free(df_supp_description[i]); return ret; } int df_process_bus(GBusType bus_type) { - _cleanup_(g_object_unrefp) GDBusConnection *dcon = NULL; + _cleanup_(g_dbus_connection_unrefp) GDBusConnection *dcon = NULL; _cleanup_(g_error_freep) GError *error = NULL; - int ret = DF_BUS_OK; switch (bus_type) { case G_BUS_TYPE_SESSION: @@ -215,9 +211,9 @@ int df_process_bus(GBusType bus_type) * @param dcon D-Bus connection structure * @return 0 on success, -1 on error */ -int df_list_bus_names(const GDBusConnection *dcon) +int df_list_bus_names(GDBusConnection *dcon) { - _cleanup_(g_object_unrefp) GDBusProxy *proxy = NULL; // proxy for getting bus names + _cleanup_(g_dbus_proxy_unrefp) GDBusProxy *proxy = NULL; // proxy for getting bus names _cleanup_(g_variant_iter_freep) GVariantIter *iter = NULL; _cleanup_(g_variant_unrefp) GVariant *response = NULL; // response from method ListNames _cleanup_(g_error_freep) GError *error = NULL; // must be set to NULL @@ -273,12 +269,12 @@ int df_list_bus_names(const GDBusConnection *dcon) * will be traversed) * @return 1 when obj. path target_proc.obj_path is found on bus, 0 otherwise */ -int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) +int df_is_object_on_bus(GDBusConnection *dcon, const char *root_node) { char *intro_iface = "org.freedesktop.DBus.Introspectable"; char *intro_method = "Introspect"; _cleanup_(g_variant_unrefp) GVariant *response = NULL; - _cleanup_(g_object_unrefp) GDBusProxy *dproxy = NULL; + _cleanup_(g_dbus_proxy_unrefp) GDBusProxy *dproxy = NULL; _cleanup_(g_freep) gchar *introspection_xml = NULL; _cleanup_(g_error_freep) GError *error = NULL; /** Information about nodes in a remote object hierarchy. */ @@ -369,18 +365,17 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node) * @return 0 on success, 1 on error, 2 when testing detected any failures * or warnings, 3 on warnings */ -int df_traverse_node(const GDBusConnection *dcon, const char *root_node) +int df_traverse_node(GDBusConnection *dcon, const char *root_node) { char *intro_iface = "org.freedesktop.DBus.Introspectable"; char *intro_method = "Introspect"; _cleanup_(g_variant_unrefp) GVariant *response = NULL; - _cleanup_(g_object_unrefp) GDBusProxy *dproxy = NULL; + _cleanup_(g_dbus_proxy_unrefp) GDBusProxy *dproxy = NULL; _cleanup_(g_freep) gchar *introspection_xml = NULL; _cleanup_(g_error_freep) GError *error = NULL; /** Information about nodes in a remote object hierarchy. */ _cleanup_(g_dbus_node_info_unrefp) GDBusNodeInfo *node_data = NULL; GDBusNodeInfo *node = NULL; - char *object = NULL; int i = 0; /** Information about a D-Bus interface. */ GDBusInterfaceInfo *interface = NULL; @@ -505,9 +500,9 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node) * @return 0 on success, 1 on error, 2 when testing detected any failures, * 3 on warnings */ -int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, const char *intf) +int df_fuzz(GDBusConnection *dcon, const char *name, const char *obj, const char *intf) { - _cleanup_(g_object_unrefp) GDBusProxy *dproxy; // D-Bus interface proxy + _cleanup_(g_dbus_proxy_unrefp) GDBusProxy *dproxy = NULL; // D-Bus interface proxy _cleanup_(g_error_freep) GError *error = NULL; GDBusMethodInfo *m; GDBusArgInfo *in_arg; @@ -577,7 +572,7 @@ int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, cons } // if method name is in df_suppression array of names, it is skipped - if (df_suppression != NULL) { + if (df_suppression[0] != NULL) { int skipflg = 0; for (i = 0; df_suppression[i] != NULL; i++) { if (strcmp(df_suppression[i], m->name) == 0) { @@ -778,10 +773,10 @@ int df_open_proc_status_file(const int pid) * @param dcon D-Bus connection structure * @return Process PID on success, -1 on error */ -int df_get_pid(const GDBusConnection *dcon) +int df_get_pid(GDBusConnection *dcon) { _cleanup_(g_error_freep) GError *error = NULL; - _cleanup_(g_object_unrefp) GDBusProxy *pproxy = NULL; + _cleanup_(g_dbus_proxy_unrefp) GDBusProxy *pproxy = NULL; _cleanup_(g_variant_unrefp) GVariant *variant_pid = NULL; int pid = -1; diff --git a/src/dfuzzer.h b/src/dfuzzer.h index d8219c2..11e20a1 100644 --- a/src/dfuzzer.h +++ b/src/dfuzzer.h @@ -67,7 +67,7 @@ int df_process_bus(GBusType bus_type); * @param dcon D-Bus connection structure * @return 0 on success, -1 on error */ -int df_list_bus_names(const GDBusConnection *dcon); +int df_list_bus_names(GDBusConnection *dcon); /** * @function Traverses through all objects of bus name target_proc.name @@ -77,7 +77,7 @@ int df_list_bus_names(const GDBusConnection *dcon); * will be traversed) * @return 1 when obj. path target_proc.obj_path is found on bus, 0 otherwise */ -int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node); +int df_is_object_on_bus(GDBusConnection *dcon, const char *root_node); /** * @function Traverses through all interfaces and objects of bus @@ -89,7 +89,7 @@ int df_is_object_on_bus(const GDBusConnection *dcon, const char *root_node); * @return 0 on success, 1 on error, 2 when testing detected any failures * or warnings, 3 on warnings */ -int df_traverse_node(const GDBusConnection *dcon, const char *root_node); +int df_traverse_node(GDBusConnection *dcon, const char *root_node); /** * @function Controls fuzz testing of all methods of specified interface (intf) @@ -101,7 +101,7 @@ int df_traverse_node(const GDBusConnection *dcon, const char *root_node); * @return 0 on success, 1 on error, 2 when testing detected any failures * or warnings, 3 on warnings */ -int df_fuzz(const GDBusConnection *dcon, const char *name, const char *obj, const char *intf); +int df_fuzz(GDBusConnection *dcon, const char *name, const char *obj, const char *intf); /** * @function Checks if name is valid D-Bus name, obj is valid @@ -126,7 +126,7 @@ int df_open_proc_status_file(const int pid); * @param dcon D-Bus connection structure * @return Process PID on success, -1 on error */ -int df_get_pid(const GDBusConnection *dcon); +int df_get_pid(GDBusConnection *dcon); /** * @function Prints process name and package to which process belongs. diff --git a/src/fuzz.c b/src/fuzz.c index ffba25e..25efb91 100644 --- a/src/fuzz.c +++ b/src/fuzz.c @@ -68,36 +68,9 @@ static int df_exec_cmd_check(const char *cmd); static GVariant *df_fuzz_create_variant(void); static int df_fuzz_create_list_variants(void); static int df_fuzz_create_fmt_string(char **fmt, const int n); -static int df_fuzz_call_method(const GVariant *value, const int void_method); +static int df_fuzz_call_method(GVariant *value, const int void_method); -/** - * @function Error checked write function with short write correction (when - * write is interrupted by a signal). - * @param fd File descriptor where to write - * @param buf Buffer from which to write to file descriptor fd - * @param count Number of bytes to be written - * @return 0 on success, -1 on error - */ -inline int df_ewrite(int fd, const void *buf, size_t count) -{ - ssize_t written = 0; - do { - written = write(fd, buf, count); - if (written == count) - break; - if (written > 0) { - buf += written; - count -= written; - } - } while (written >= 0 || errno == EINTR); - if (written < 0) { - perror("write"); - return -1; - } - return 0; -} - /** * @function Saves pointer on D-Bus interface proxy for this module to be * able to call methods through this proxy during fuzz testing. Also saves @@ -443,7 +416,7 @@ static int df_fuzz_write_log(void) g_variant_get(s->var, s->sig, var); if (var != NULL && g_variant_check_format_string(var, "s", FALSE)) { - g_variant_get(&var, "s", &tmp12); + g_variant_get(var, "s", &tmp12); str_len = strlen(tmp12); tmp12cpy = tmp12; if (tmp12 != NULL) @@ -819,7 +792,7 @@ static GVariant *df_fuzz_create_variant(void) // Initialize the cif if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, df_list.args + 1, &ffi_type_pointer, args) == FFI_OK) { - ffi_call(&cif, g_variant_new, &val, values); + ffi_call(&cif, FFI_FN(g_variant_new), &val, values); // val now holds the result of the call to g_variant_new(). // When val will be freed, all the floating Gvariants which // was used to create it will be freed too, because val is @@ -1003,13 +976,12 @@ static int df_fuzz_create_fmt_string(char **fmt, const int n) * @return 0 on success, -1 on error, 1 if void method returned non-void * value or 2 when tested method raised exception (so it should be skipped) */ -static int df_fuzz_call_method(const GVariant *value, const int void_method) +static int df_fuzz_call_method(GVariant *value, const int void_method) { _cleanup_(g_error_freep) GError *error = NULL; _cleanup_(g_variant_unrefp) GVariant *response = NULL; _cleanup_(g_freep) gchar *dbus_error = NULL; - gchar *fmt; - + const gchar *fmt; // Synchronously invokes method with arguments stored in value (GVariant *) // on df_dproxy. diff --git a/src/fuzz.h b/src/fuzz.h index 9109b8e..dd813c9 100644 --- a/src/fuzz.h +++ b/src/fuzz.h @@ -61,16 +61,6 @@ struct df_sig_list { }; -/** - * @function Error checked write function with short write correction (when - * write is interrupted by a signal). - * @param fd File descriptor where to write - * @param buf Buffer from which to write to file descriptor fd - * @param count Number of bytes to be written - * @return 0 on success, -1 on error - */ -inline int df_ewrite(int fd, const void *buf, size_t count); - /** * @function Saves pointer on D-Bus interface proxy for this module to be * able to call methods through this proxy during fuzz testing. Also saves diff --git a/src/introspection.c b/src/introspection.c index 4513063..77a8e7c 100644 --- a/src/introspection.c +++ b/src/introspection.c @@ -47,7 +47,7 @@ static GDBusArgInfo **df_out_args; * @param interface D-Bus interface * @return 0 on success, -1 on error */ -int df_init_introspection(const GDBusProxy *dproxy, const char *name, const char *interface) +int df_init_introspection(GDBusProxy *dproxy, const char *name, const char *interface) { if (!dproxy || !interface) { df_debug("Passing NULL argument to function.\n"); diff --git a/src/introspection.h b/src/introspection.h index 038e088..d176886 100644 --- a/src/introspection.h +++ b/src/introspection.h @@ -30,8 +30,7 @@ * @param interface D-Bus interface * @return 0 on success, -1 on error */ -int df_init_introspection(const GDBusProxy *dproxy, const char *name, - const char *interface); +int df_init_introspection(GDBusProxy *dproxy, const char *name, const char *interface); /** * @return Pointer on GDBusMethodInfo which contains information about method diff --git a/src/rand.c b/src/rand.c index def4538..62775dc 100644 --- a/src/rand.c +++ b/src/rand.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "rand.h" @@ -336,15 +337,6 @@ guint64 df_rand_guint64(void) return gu64; } -/** - * @return Generated pseudo-random double precision floating point number - * from interval <0, 1> - */ -inline double drand(void) -{ - return ((double)rand() / RAND_MAX); -} - /** * @return Generated pseudo-random double precision floating point number */ @@ -539,7 +531,7 @@ int df_rand_dbus_objpath_string(gchar **buf) */ int df_rand_dbus_signature_string(gchar **buf) { - static unsigned char size = 1; + static uint16_t size = 1; size++; int i, j; diff --git a/src/rand.h b/src/rand.h index 604551d..4c321dc 100644 --- a/src/rand.h +++ b/src/rand.h @@ -88,7 +88,10 @@ guint64 df_rand_guint64(void); * @return Generated pseudo-random double precision floating point number * from interval <0, 1> */ -inline double drand(void); +inline double drand(void) +{ + return ((double)rand() / RAND_MAX); +} /** * @return Generated pseudo-random double precision floating point number diff --git a/src/util.h b/src/util.h index 5f5c92f..606f251 100644 --- a/src/util.h +++ b/src/util.h @@ -17,11 +17,20 @@ } \ } +static inline void g_dbus_connection_unref(GDBusConnection *p) { + g_object_unref(p); +} + +static inline void g_dbus_proxy_unref(GDBusProxy *p) { + g_object_unref(p); +} + DEFINE_TRIVIAL_CLEANUP_FUNC(int, close); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gpointer, g_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gpointer, g_object_unref, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gchar*, g_free, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GDBusConnection*, g_dbus_connection_unref, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GDBusProxy*, g_dbus_proxy_unref, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GVariantIter*, g_variant_iter_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GError*, g_error_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(GVariant*, g_variant_unref, NULL); From de6bc9a98ea47c1fa9df85c7bb2ba05a129183df Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sat, 23 Apr 2022 18:20:01 +0200 Subject: [PATCH 13/13] Makefile: use the override directive for CFLAGS --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 24b50b5..cc50e4e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,8 @@ #============================================================================== CC ?= gcc -CFLAGS += -Wall -Wno-unused-parameter -O2 -D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 `pkg-config --cflags --libs gio-2.0 libffi` -g +# See: https://www.gnu.org/software/make/manual/make.html#Override-Directive +override CFLAGS += -Wall -Wno-unused-parameter -O2 -D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 `pkg-config --cflags --libs gio-2.0 libffi` -g OBJ = dfuzzer.o introspection.o fuzz.o rand.o util.o TARGET = dfuzzer all: dfuzzer