void sudo_debug_printf2(const char *func, const char *file, int lineno, int level, const char *fmt, ...) { int buflen, pri, subsys, saved_errno = errno; va_list ap; char *buf; if (!sudo_debug_mode) return; /* Extract pri and subsystem from level. */ pri = SUDO_DEBUG_PRI(level); subsys = SUDO_DEBUG_SUBSYS(level); /* Make sure we want debug info at this level. */ if (subsys < NUM_SUBSYSTEMS && sudo_debug_settings[subsys] >= pri) { va_start(ap, fmt); buflen = vasprintf(&buf, fmt, ap); va_end(ap); if (buflen != -1) { int errcode = ISSET(level, SUDO_DEBUG_ERRNO) ? saved_errno : 0; if (ISSET(level, SUDO_DEBUG_LINENO)) sudo_debug_write2(func, file, lineno, buf, buflen, errcode); else sudo_debug_write2(NULL, NULL, 0, buf, buflen, errcode); free(buf); } } errno = saved_errno; }
/* * Create a new output file for the specified debug instance. * Returns NULL if the file cannot be opened or memory cannot be allocated. */ static struct sudo_debug_output * sudo_debug_new_output(struct sudo_debug_instance *instance, struct sudo_debug_file *debug_file) { char *buf, *cp, *last, *subsys, *pri; struct sudo_debug_output *output; unsigned int j; int i; /* Create new output for the instance. */ /* XXX - reuse fd for existing filename? */ output = calloc(1, sizeof(*output)); if (output == NULL) goto bad; output->fd = -1; output->settings = reallocarray(NULL, instance->max_subsystem + 1, sizeof(int)); if (output->settings == NULL) goto bad; output->filename = strdup(debug_file->debug_file); if (output->filename == NULL) goto bad; output->fd = -1; /* Init per-subsystems settings to -1 since 0 is a valid priority. */ for (j = 0; j <= instance->max_subsystem; j++) output->settings[j] = -1; /* Open debug file. */ output->fd = open(output->filename, O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR); if (output->fd == -1) { /* Create debug file as needed and set group ownership. */ if (errno == ENOENT) { output->fd = open(output->filename, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR); } if (output->fd == -1) goto bad; ignore_result(fchown(output->fd, (uid_t)-1, 0)); } (void)fcntl(output->fd, F_SETFD, FD_CLOEXEC); if (sudo_debug_fds_size < output->fd) { /* Bump fds size to the next multiple of 4 * NBBY. */ const int old_size = sudo_debug_fds_size / NBBY; const int new_size = round_nfds(output->fd + 1) / NBBY; unsigned char *new_fds; new_fds = realloc(sudo_debug_fds, new_size); if (new_fds == NULL) goto bad; memset(new_fds + old_size, 0, new_size - old_size); sudo_debug_fds = new_fds; sudo_debug_fds_size = new_size * NBBY; } sudo_setbit(sudo_debug_fds, output->fd); if (output->fd > sudo_debug_max_fd) sudo_debug_max_fd = output->fd; /* Parse Debug conf string. */ buf = strdup(debug_file->debug_flags); if (buf == NULL) goto bad; for ((cp = strtok_r(buf, ",", &last)); cp != NULL; (cp = strtok_r(NULL, ",", &last))) { /* Should be in the form subsys@pri. */ subsys = cp; if ((pri = strchr(cp, '@')) == NULL) continue; *pri++ = '\0'; /* Look up priority and subsystem, fill in sudo_debug_settings[]. */ for (i = 0; sudo_debug_priorities[i] != NULL; i++) { if (strcasecmp(pri, sudo_debug_priorities[i]) == 0) { for (j = 0; instance->subsystems[j] != NULL; j++) { if (strcasecmp(subsys, "all") == 0) { const unsigned int idx = instance->subsystem_ids ? SUDO_DEBUG_SUBSYS(instance->subsystem_ids[j]) : j; if (i > output->settings[idx]) output->settings[idx] = i; continue; } if (strcasecmp(subsys, instance->subsystems[j]) == 0) { const unsigned int idx = instance->subsystem_ids ? SUDO_DEBUG_SUBSYS(instance->subsystem_ids[j]) : j; if (i > output->settings[idx]) output->settings[idx] = i; break; } } break; } } } free(buf); return output; bad: sudo_warn_nodebug(NULL); if (output != NULL) sudo_debug_free_output(output); return NULL; }
void sudo_debug_execve2(int level, const char *path, char *const argv[], char *const envp[]) { char * const *av; char *buf, *cp; int buflen, pri, subsys, log_envp = 0; size_t plen; if (!sudo_debug_mode) return; /* Extract pri and subsystem from level. */ pri = SUDO_DEBUG_PRI(level); subsys = SUDO_DEBUG_SUBSYS(level); /* Make sure we want debug info at this level. */ if (subsys >= NUM_SUBSYSTEMS || sudo_debug_settings[subsys] < pri) return; /* Log envp for debug level "debug". */ if (sudo_debug_settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp[0] != NULL) log_envp = 1; #define EXEC_PREFIX "exec " /* Alloc and build up buffer. */ plen = strlen(path); buflen = sizeof(EXEC_PREFIX) -1 + plen; if (argv[0] != NULL) { buflen += sizeof(" []") - 1; for (av = argv; *av; av++) buflen += strlen(*av) + 1; buflen--; } if (log_envp) { buflen += sizeof(" []") - 1; for (av = envp; *av; av++) buflen += strlen(*av) + 1; buflen--; } buf = malloc(buflen + 1); if (buf == NULL) return; /* Copy prefix and command. */ memcpy(buf, EXEC_PREFIX, sizeof(EXEC_PREFIX) - 1); cp = buf + sizeof(EXEC_PREFIX) - 1; memcpy(cp, path, plen); cp += plen; /* Copy argv. */ if (argv[0] != NULL) { *cp++ = ' '; *cp++ = '['; for (av = argv; *av; av++) { size_t avlen = strlen(*av); memcpy(cp, *av, avlen); cp += avlen; *cp++ = ' '; } cp[-1] = ']'; } if (log_envp) { *cp++ = ' '; *cp++ = '['; for (av = envp; *av; av++) { size_t avlen = strlen(*av); memcpy(cp, *av, avlen); cp += avlen; *cp++ = ' '; } cp[-1] = ']'; } *cp = '\0'; sudo_debug_write(buf, buflen, 0); free(buf); }