Skip to content

Commit 1234249

Browse files
committed
Handle failed report time formatting
format_fs_error_time returned the caller buffer even when the size check rejected it. That let report code pass an uninitialized buffer to fprintf when an undersized destination was supplied, and the same returned-buffer pattern existed in related report time formatters added to the access-attribute audit. The affected formatters now return NULL when the destination buffer cannot be initialized, and each report caller substitutes unavailable before printing. The return-value comments now document the NULL result so future callers do not treat it as a valid string.
1 parent 0dd79df commit 1234249

3 files changed

Lines changed: 40 additions & 18 deletions

File tree

src/daemon/fanotify-fs-error.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,15 @@ static const char *fs_error_code_text(int error)
168168
* @when: timestamp saved with the error details.
169169
* @buf: destination buffer.
170170
* @buf_size: destination size.
171-
* Returns @buf.
171+
* Returns @buf on success, or NULL when @buf cannot be initialized.
172172
*/
173173
static const char *format_fs_error_time(time_t when, char *buf,
174174
size_t buf_size)
175175
{
176176
struct tm tm;
177177

178-
if (buf_size < 11)
179-
return buf;
178+
if (buf == NULL || buf_size < 11)
179+
return NULL;
180180

181181
if (when == 0) {
182182
strncpy(buf, "never", buf_size - 1);
@@ -347,6 +347,7 @@ static void record_fs_error_event(
347347
void fanotify_fs_error_report(FILE *f)
348348
{
349349
struct fanotify_fs_error_details details;
350+
const char *when_text;
350351
char when[64];
351352

352353
if (f == NULL)
@@ -358,8 +359,11 @@ void fanotify_fs_error_report(FILE *f)
358359

359360
fprintf(f, "Filesystem error last status: %s\n",
360361
fs_error_status(&details));
362+
when_text = format_fs_error_time(details.when, when, sizeof(when));
363+
if (when_text == NULL)
364+
when_text = "unavailable";
361365
fprintf(f, "Filesystem error last seen: %s\n",
362-
format_fs_error_time(details.when, when, sizeof(when)));
366+
when_text);
363367
if (!details.valid)
364368
return;
365369

src/daemon/state-report.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@ void usr1_handler(int sig __attribute__((unused)),
115115
* format_metrics_reset_time - format the last metric reset timestamp.
116116
* @buf: destination buffer.
117117
* @buf_size: destination size.
118-
* Returns @buf.
118+
* Returns @buf on success, or NULL when @buf cannot be initialized.
119119
*/
120120
static const char *format_metrics_reset_time(char *buf, size_t buf_size)
121121
{
122122
struct tm tm;
123123

124-
if (buf_size == 0)
125-
return buf;
124+
if (buf == NULL || buf_size == 0)
125+
return NULL;
126126

127127
if (last_metrics_reset == 0) {
128128
strncpy(buf, "never", buf_size - 1);
@@ -253,15 +253,19 @@ void decision_report_reset(FILE *f, int reset)
253253
void decision_report_metrics_reset(FILE *f, int reset)
254254
{
255255
decision_metrics_t metrics;
256+
const char *reset_text;
256257
char reset_time[64];
257258

258259
if (f == NULL)
259260
return;
260261

261262
getDecisionMetricsReset(&metrics, reset);
262263

264+
reset_text = format_metrics_reset_time(reset_time, sizeof(reset_time));
265+
if (reset_text == NULL)
266+
reset_text = "unavailable";
263267
fprintf(f, "Last metrics reset: %s\n",
264-
format_metrics_reset_time(reset_time, sizeof(reset_time)));
268+
reset_text);
265269
fprintf(f, "Ruleset generation: %u\n", metrics.ruleset_generation);
266270

267271
fprintf(f, "\nDecision outcomes:\n");

src/library/decision-timing.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -492,13 +492,16 @@ static int open_timing_report(void)
492492
* @when: timestamp to format.
493493
* @buf: destination buffer.
494494
* @buf_len: size of @buf.
495-
* Returns @buf.
495+
* Returns @buf on success, or NULL when @buf cannot be initialized.
496496
*/
497497
static const char *format_report_time(long when, char *buf, size_t buf_len)
498498
{
499499
struct tm tm;
500500
time_t t = (time_t)when;
501501

502+
if (buf == NULL || buf_len == 0)
503+
return NULL;
504+
502505
if (when <= 0) {
503506
strncpy(buf, "never", buf_len - 1);
504507
buf[buf_len - 1] = 0;
@@ -2276,6 +2279,7 @@ static void write_timing_report(const conf_t *config)
22762279
FILE *f;
22772280
unsigned int worker, stage, worker_count;
22782281
char decisions[32], duration[32], start_time[64], stop_time[64];
2282+
const char *start_text, *stop_text;
22792283
const char *mode = decision_timing_mode_name(
22802284
config_timing_mode(config));
22812285
unsigned long long duration_ns = 0;
@@ -2339,11 +2343,16 @@ static void write_timing_report(const conf_t *config)
23392343

23402344
format_count(decision_count, decisions, sizeof(decisions));
23412345
format_hms_duration(duration_ns, duration, sizeof(duration));
2346+
start_text = format_report_time(started, start_time,
2347+
sizeof(start_time));
2348+
if (start_text == NULL)
2349+
start_text = "unavailable";
2350+
stop_text = format_report_time(stopped, stop_time, sizeof(stop_time));
2351+
if (stop_text == NULL)
2352+
stop_text = "unavailable";
23422353

23432354
fprintf(f, "Mode: %s\n", mode);
2344-
fprintf(f, "Timing run: %s to %s\n",
2345-
format_report_time(started, start_time, sizeof(start_time)),
2346-
format_report_time(stopped, stop_time, sizeof(stop_time)));
2355+
fprintf(f, "Timing run: %s to %s\n", start_text, stop_text);
23472356
fprintf(f, "Duration: %s\n", duration);
23482357
fprintf(f, "Workers: %u\n", worker_count);
23492358
fprintf(f, "Max queue depth: %u\n", max_queue_depth);
@@ -2679,17 +2688,22 @@ void decision_timing_control_report(FILE *f, const conf_t *config)
26792688
*/
26802689
void decision_timing_history_report(FILE *f)
26812690
{
2691+
const char *arm_text, *stop_text;
26822692
char arm_time[64], stop_time[64];
26832693

26842694
if (f == NULL)
26852695
return;
26862696

2687-
fprintf(f, "Timing collection last start time: %s\n",
2688-
format_report_time(atomic_load_explicit(&last_arm_time,
2689-
memory_order_relaxed), arm_time, sizeof(arm_time)));
2690-
fprintf(f, "Timing collection last stop time: %s\n",
2691-
format_report_time(atomic_load_explicit(&last_stop_time,
2692-
memory_order_relaxed), stop_time, sizeof(stop_time)));
2697+
arm_text = format_report_time(atomic_load_explicit(&last_arm_time,
2698+
memory_order_relaxed), arm_time, sizeof(arm_time));
2699+
if (arm_text == NULL)
2700+
arm_text = "unavailable";
2701+
stop_text = format_report_time(atomic_load_explicit(&last_stop_time,
2702+
memory_order_relaxed), stop_time, sizeof(stop_time));
2703+
if (stop_text == NULL)
2704+
stop_text = "unavailable";
2705+
fprintf(f, "Timing collection last start time: %s\n", arm_text);
2706+
fprintf(f, "Timing collection last stop time: %s\n", stop_text);
26932707
}
26942708

26952709
/*

0 commit comments

Comments
 (0)