mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
debug: fix parsing of /proc/self/stat
The code in init_log_file relies on the process name (COMM) to not contain whitespaces. This change fixes it by looking up the right-most parenthesis to safely jump past COMM. For more context see: https://www.openwall.com/lists/oss-security/2022/12/21/6 Code is only used with testing, so it should have no impact on regular users. Reported-by: Hugues Evrard <hevrard@google.com> mm
This commit is contained in:
parent
7ec97ed5f2
commit
c38b668fc3
@ -217,6 +217,45 @@ void init_log_fn(lvm2_log_fn_t log_fn)
|
||||
_lvm2_log_fn = log_fn;
|
||||
}
|
||||
|
||||
/* Read /proc/self/stat to extract pid and starttime */
|
||||
static int _get_pid_starttime(int *pid, unsigned long long *starttime)
|
||||
{
|
||||
static const char statfile[] = "/proc/self/stat";
|
||||
char buf[1024];
|
||||
char *p;
|
||||
int fd;
|
||||
int e;
|
||||
|
||||
if ((fd = open(statfile, O_RDONLY)) == -1) {
|
||||
log_sys_debug("open", statfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((e = read(fd, buf, sizeof(buf) - 1)) <= 0)
|
||||
log_sys_debug("read", statfile);
|
||||
|
||||
if (!close(fd))
|
||||
log_sys_debug("close", statfile);
|
||||
|
||||
if (e <= 0)
|
||||
return 0;
|
||||
|
||||
buf[e] = '\0';
|
||||
if ((sscanf(buf, "%d ", pid) == 1) &&
|
||||
/* Jump past COMM, don't use scanf with '%s' since COMM may contain a space. */
|
||||
(p = strrchr(buf, ')')) &&
|
||||
(scanf(++p, " %*c %*d %*d %*d %*d " /* tty_nr */
|
||||
"%*d %*u %*u %*u %*u " /* mjflt */
|
||||
"%*u %*u %*u %*d %*d " /* cstim */
|
||||
"%*d %*d %*d %*d " /* itrealvalue */
|
||||
"%llu", &starttime) == 1))
|
||||
return 1;
|
||||
|
||||
log_debug("Cannot parse content of %s.", statfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support envvar LVM_LOG_FILE_EPOCH and allow to attach
|
||||
* extra keyword (consist of upto 32 alpha chars) to
|
||||
@ -228,11 +267,9 @@ void init_log_fn(lvm2_log_fn_t log_fn)
|
||||
*/
|
||||
void init_log_file(const char *log_file, int append)
|
||||
{
|
||||
static const char statfile[] = "/proc/self/stat";
|
||||
const char *env;
|
||||
int pid;
|
||||
unsigned long long starttime;
|
||||
FILE *st;
|
||||
int pid = 0;
|
||||
unsigned long long starttime = 0;
|
||||
int i = 0;
|
||||
|
||||
_log_file_path[0] = '\0';
|
||||
@ -245,15 +282,9 @@ void init_log_file(const char *log_file, int append)
|
||||
goto no_epoch;
|
||||
}
|
||||
|
||||
if (!(st = fopen(statfile, "r")))
|
||||
log_sys_error("fopen", statfile);
|
||||
else if (fscanf(st, "%d %*s %*c %*d %*d %*d %*d " /* tty_nr */
|
||||
"%*d %*u %*u %*u %*u " /* mjflt */
|
||||
"%*u %*u %*u %*d %*d " /* cstim */
|
||||
"%*d %*d %*d %*d " /* itrealvalue */
|
||||
"%llu", &pid, &starttime) != 2) {
|
||||
log_warn("WARNING: Cannot parse content of %s.", statfile);
|
||||
} else {
|
||||
if (!_get_pid_starttime(&pid, &starttime))
|
||||
log_debug("Failed to obtain pid and starttime.");
|
||||
|
||||
if (dm_snprintf(_log_file_path, sizeof(_log_file_path),
|
||||
"%s_%s_%d_%llu", log_file, env, pid, starttime) < 0) {
|
||||
log_warn("WARNING: Debug log file path is too long for epoch.");
|
||||
@ -262,10 +293,6 @@ void init_log_file(const char *log_file, int append)
|
||||
log_file = _log_file_path;
|
||||
append = 1; /* force */
|
||||
}
|
||||
}
|
||||
|
||||
if (st && fclose(st))
|
||||
log_sys_debug("fclose", statfile);
|
||||
|
||||
if ((env = getenv("LVM_LOG_FILE_MAX_LINES"))) {
|
||||
if (sscanf(env, FMTu64, &_log_file_max_lines) != 1) {
|
||||
@ -896,4 +923,3 @@ uint32_t log_journal_str_to_val(const char *str)
|
||||
log_warn("Ignoring unrecognized journal value.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user