Skip to content

Commit 9ec514f

Browse files
committed
Avoid blocking during disk alerts
Disk alerts can be configured to write a "wall" message to all users. Some terminals may control the character flow. This can hold up the audit daemon momentarily. Change to NONBLOCKING open and don't allow to be blocked.
1 parent 120f51e commit 9ec514f

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

common/common.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,21 @@ void wall_message(const char* format, ...)
9191
{
9292
struct utmpx* entry;
9393
char message[512];
94+
char wall_buf[640];
9495
va_list args;
9596
int fd;
97+
ssize_t len;
9698

9799
// Format the message
98100
va_start(args, format);
99101
vsnprintf(message, sizeof(message), format, args);
100102
va_end(args);
103+
len = snprintf(wall_buf, sizeof(wall_buf),
104+
"\nBroadcast message from audit daemon:\n%s\n", message);
105+
if (len <= 0)
106+
return;
107+
if ((size_t)len >= sizeof(wall_buf))
108+
len = sizeof(wall_buf) - 1;
101109

102110
setutxent();
103111

@@ -109,9 +117,29 @@ void wall_message(const char* format, ...)
109117
snprintf(tty_path, sizeof(tty_path), "/dev/%s",
110118
entry->ut_line);
111119

112-
fd = open(tty_path, O_WRONLY | O_NOCTTY);
120+
fd = open(tty_path, O_WRONLY | O_NOCTTY | O_NONBLOCK);
113121
if (fd != -1) {
114-
dprintf(fd, "\nBroadcast message from audit daemon:\n%s\n", message);
122+
ssize_t off = 0;
123+
124+
while (off < len) {
125+
ssize_t rc;
126+
127+
rc = write(fd, wall_buf+off, len - off);
128+
// Allow partial writes
129+
if (rc > 0) {
130+
off += rc;
131+
continue;
132+
}
133+
// Allow signal interruptions
134+
if (rc < 0 && errno == EINTR)
135+
continue;
136+
// Breaking here to prevent holding up
137+
// the daemon on flow-controlled
138+
// terminals.
139+
if (rc < 0 && (errno == EAGAIN))
140+
break;
141+
break;
142+
}
115143
close(fd);
116144
}
117145
}

0 commit comments

Comments
 (0)