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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions event_fout.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ int event_handler_fout(struct trace_context_s *context, int event_type) {
try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 1, "# phpv = %s", context->target.phpv));
try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 0, "%c", opt_frame_delim));
}
if (opt_verbose_fields_comm) {
try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 1, "# comm = %s", context->target.comm));
try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 0, "%c", opt_frame_delim));
}
try_break(rv, event_handler_fout_snprintf(&udata->cur, &udata->rem, &len, 0, "%c", opt_trace_delim));
} while (0);
try(rv, event_handler_fout_write(udata));
Expand Down
56 changes: 55 additions & 1 deletion phpspy.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int opt_filter_negate = 0;
int opt_verbose_fields_pid = 0;
int opt_verbose_fields_ts = 0;
int opt_verbose_fields_phpv = 0;
int opt_verbose_fields_comm = 0;
int (*opt_event_handler)(struct trace_context_s *context, int event_type) = event_handler_fout;
int opt_continue_on_error = 0;
int opt_fout_buffer_size = 4096;
Expand Down Expand Up @@ -55,6 +56,7 @@ static void varpeek_add(char *varspec);
static void glopeek_add(char *glospec);
static int copy_proc_mem(pid_t pid, const char *what, void *raddr, void *laddr, size_t size);
static void try_get_php_version(trace_target_t *target);
static int get_comm_pid(pid_t pid, char *buf, size_t buf_size);

#ifdef USE_ZEND
static int do_trace(trace_context_t *context);
Expand Down Expand Up @@ -306,9 +308,11 @@ static void parse_opts(int argc, char **argv) {
case 'p': opt_verbose_fields_pid = 1; break;
case 't': opt_verbose_fields_ts = 1; break;
case 'v': opt_verbose_fields_phpv = 1; break;
case 'c': opt_verbose_fields_comm = 1; break;
case 'P': opt_verbose_fields_pid = 0; break;
case 'T': opt_verbose_fields_ts = 0; break;
case 'V': opt_verbose_fields_phpv = 1; break;
case 'V': opt_verbose_fields_phpv = 0; break;
case 'C': opt_verbose_fields_comm = 0; break;
}
}
break;
Expand Down Expand Up @@ -353,6 +357,7 @@ int main_pid(pid_t pid) {

memset(&context, 0, sizeof(trace_context_t));
context.target.pid = pid;
get_comm_pid(pid, context.target.comm, sizeof(context.target.comm));
context.event_handler = opt_event_handler;
try(rv, find_addresses(&context.target));
try(rv, context.event_handler(&context, PHPSPY_TRACE_EVENT_INIT));
Expand Down Expand Up @@ -796,6 +801,55 @@ void log_error(const char *fmt, ...) {
}
}

static int get_comm_pid(pid_t pid, char *buf, size_t buf_size) {
char proc_fs_path[PATH_MAX];
char *line;
ssize_t fread_res;
size_t comm_len;
size_t line_len = 0;

FILE *f = NULL;
snprintf(proc_fs_path, PATH_MAX, "/proc/%d/comm", pid);

f = fopen(proc_fs_path, "rb");
if (f == NULL) {
log_error("Couldn't read comm of pid %d - errno %d\n", pid, errno);
goto error;
}

fread_res = getline(&line, &line_len, f);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't initialize line before reading?

And why use a complicated API like getline when you just gotta read 16 bytes?

if (fread_res == -1) {
log_error("Couldn't read %s file - errno %d\n", proc_fs_path, pid);
goto error;
}
comm_len = (size_t) fread_res - 1; /* remove \n delimiter */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle the 0 case so you don't underflow



#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
/* Copy up to comm_len / buf_size the min between them */
memcpy(buf, line, MIN(buf_size, comm_len));
free(line);
fclose(f);

/* Force null termination */
if (comm_len >= buf_size) {
buf[buf_size] = '\0';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
buf[buf_size] = '\0';
buf[buf_size - 1] = '\0';

} else {
buf[comm_len] = '\0';
}

return PHPSPY_OK;

error:
if (f != NULL) {
fclose(f);
}

strncpy(buf, "UNKNOWN-COMM", buf_size);
buf[buf_size] = '\0'; /* terminate just in case because strncpy doesn't */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

@EzraDechwong0 EzraDechwong0 Jan 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return PHPSPY_ERR;
}

/* TODO figure out a way to make this cleaner */
#ifdef USE_ZEND
#include "phpspy_trace.c"
Expand Down
4 changes: 4 additions & 0 deletions phpspy.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
#define IS_REFERENCE 10
#endif

#define TASK_COMM_LEN (16) /* copied from linux/sched.h */

typedef struct varpeek_var_s {
char name[PHPSPY_STR_SIZE];
UT_hash_handle hh;
Expand Down Expand Up @@ -145,6 +147,7 @@ typedef struct trace_glopeek_s {
typedef struct trace_target_s {
pid_t pid;
char phpv[4];
char comm[TASK_COMM_LEN + 1]; /* TASK_COMM_LEN is allowed to be non null terminated if reaches max size, here add null-termination */
uint64_t executor_globals_addr;
uint64_t sapi_globals_addr;
uint64_t alloc_globals_addr;
Expand Down Expand Up @@ -191,6 +194,7 @@ extern int opt_filter_negate;
extern int opt_verbose_fields_pid;
extern int opt_verbose_fields_ts;
extern int opt_verbose_fields_phpv;
extern int opt_verbose_fields_comm;
extern int opt_continue_on_error;
extern int opt_fout_buffer_size;
extern long opt_time_limit_ms;
Expand Down