blob: 3803304be897c7cf26d58a4b6236290aa2af9964 [file] [log] [blame]
Jan Stanceka0e618c2013-06-07 11:09:26 +02001/*
2 * Copyright (C) 2013 Linux Test Project
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it
13 * is free of the rightful claim of any third person regarding
14 * infringement or the like. Any license provided herein, whether
15 * implied or otherwise, applies only to this software file. Patent
16 * licenses, if any, provided herein do not apply to combinations of
17 * this program with other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24/*
25 * Test /dev/kmsg based on kernel doc: Documentation/ABI/testing/dev-kmsg
26 * - read() blocks
27 * - non-blocking read() fails with EAGAIN
28 * - partial read fails (buffer smaller than message)
29 * - can write to /dev/kmsg and message seqno grows
30 * - first read() after open() returns same message
31 * - if messages get overwritten, read() returns -EPIPE
32 * - device supports SEEK_SET, SEEK_END, SEEK_DATA
33 */
34#define _GNU_SOURCE
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <sys/syscall.h>
38#include <sys/wait.h>
39#include <errno.h>
40#include <fcntl.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45#include "config.h"
46#include "test.h"
Jan Stanceka0e618c2013-06-07 11:09:26 +020047#include "safe_macros.h"
48#include "linux_syscall_numbers.h"
49
50#define MSG_PREFIX "LTP kmsg01 "
51#define MAX_MSGSIZE 4096
52#define NUM_READ_MSGS 3
53#define NUM_READ_RETRY 10
54#define NUM_OVERWRITE_MSGS 1024
55#define READ_TIMEOUT 5
56
57char *TCID = "kmsg01";
58static void setup(void);
59static void cleanup(void);
60
61/*
62 * inject_msg - write message to /dev/kmsg
63 * @msg: null-terminated message to inject, should end with \n
64 *
65 * RETURNS:
66 * 0 on success
67 * -1 on failure, errno reflects write() errno
68 */
69static int inject_msg(const char *msg)
70{
71 int f;
72 f = open("/dev/kmsg", O_WRONLY);
73 if (f < 0)
74 tst_brkm(TBROK | TERRNO, cleanup, "failed to open /dev/kmsg");
75 TEST(write(f, msg, strlen(msg)));
76 SAFE_CLOSE(cleanup, f);
77 errno = TEST_ERRNO;
78 return TEST_RETURN;
79}
80
81/*
82 * find_msg - find message in kernel ring buffer
83 * @fd: fd to use, if < 0 function opens /dev/kmsg itself
84 * @text_to_find: substring to look for in messages
85 * @buf: buf to store found message
86 * @bufsize: size of 'buf'
87 * @first: 1 - return first matching message
88 * 0 - return last matching message
89 * RETURNS:
90 * 0 on success
91 * -1 on failure
92 */
93static int find_msg(int fd, const char *text_to_find, char *buf, int bufsize,
94 int first)
95{
96 int f, msg_found = 0;
97 char msg[MAX_MSGSIZE + 1];
98
99 if (fd < 0) {
100 f = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
101 if (f < 0)
102 tst_brkm(TBROK, cleanup, "failed to open /dev/kmsg");
103 } else {
104 f = fd;
105 }
106
107 while (1) {
108 TEST(read(f, msg, sizeof(msg)));
109 if (TEST_RETURN < 0) {
110 if (TEST_ERRNO == EAGAIN)
111 /* there are no more messages */
112 break;
113 else if (TEST_ERRNO == EPIPE)
114 /* current message was overwritten */
115 continue;
116 else
117 tst_brkm(TBROK|TTERRNO, cleanup,
118 "failed to read /dev/kmsg");
119 } else if (TEST_RETURN < bufsize) {
120 /* lines from kmsg are not NULL terminated */
121 msg[TEST_RETURN] = '\0';
122 if (strstr(msg, text_to_find) != NULL) {
123 strncpy(buf, msg, bufsize);
124 msg_found = 1;
125 if (first)
126 break;
127 }
128 }
129 }
130 if (fd < 0)
131 SAFE_CLOSE(cleanup, f);
132
133 if (msg_found)
134 return 0;
135 else
136 return -1;
137}
138
139static int get_msg_fields(const char *msg, unsigned long *prio,
140 unsigned long *seqno)
141{
142 unsigned long s, p;
143 if (sscanf(msg, "%lu,%lu,", &p, &s) == 2) {
144 if (prio)
145 *prio = p;
146 if (seqno)
147 *seqno = s;
148 return 0;
149 } else {
150 return 1;
151 }
152}
153
154/*
155 * timed_read - if possible reads from fd or times out
156 * @fd: fd to read from
157 * @timeout_sec: timeout in seconds
158 *
159 * RETURNS:
160 * read bytes on successful read
161 * -1 on read() error, errno reflects read() errno
162 * -2 on timeout
163 */
164static int timed_read(int fd, int timeout_sec)
165{
166 int ret, tmp;
167 struct timeval timeout;
168 fd_set read_fds;
169
170 FD_ZERO(&read_fds);
171 FD_SET(fd, &read_fds);
172 timeout.tv_sec = timeout_sec;
173 timeout.tv_usec = 0;
174
175 ret = select(fd + 1, &read_fds, 0, 0, &timeout);
176 switch (ret) {
177 case -1:
178 tst_brkm(TBROK|TERRNO, cleanup, "select failed");
179 case 0:
180 /* select timed out */
181 return -2;
182 }
183
184 return read(fd, &tmp, 1);
185}
186
187/*
188 * timed_read_kmsg - reads file until it reaches end of file,
189 * read fails or times out. This ignores any
190 * EPIPE errors.
191 * @fd: fd to read from
192 * @timeout_sec: timeout in seconds for every read attempt
193 *
194 * RETURNS:
195 * 0 on read reaching eof
196 * -1 on read error, errno reflects read() errno
197 * -2 on timeout
198 */
199static int timed_read_kmsg(int fd, int timeout_sec)
200{
201 int child, status, ret = 0;
202 int pipefd[2];
203 char msg[MAX_MSGSIZE];
204
205 if (pipe(pipefd) != 0)
206 tst_brkm(TBROK|TERRNO, cleanup, "pipe failed");
207
208 child = fork();
209 switch (child) {
210 case -1:
211 tst_brkm(TBROK|TERRNO, cleanup, "failed to fork");
212 case 0:
213 /* child does all the reading and keeps writing to
214 * pipe to let parent know that it didn't block */
215 close(pipefd[0]);
216 while (1) {
217 write(pipefd[1], "", 1);
218 TEST(read(fd, msg, MAX_MSGSIZE));
219 if (TEST_RETURN == 0)
220 break;
221 if (TEST_RETURN == -1 && TEST_ERRNO != EPIPE) {
222 ret = TEST_ERRNO;
223 break;
224 }
225 }
226
227 close(pipefd[1]);
228 exit(ret);
229 }
230 SAFE_CLOSE(cleanup, pipefd[1]);
231
232 /* parent reads pipe until it reaches eof or until read times out */
233 do {
234 TEST(timed_read(pipefd[0], timeout_sec));
235 } while (TEST_RETURN > 0);
236 SAFE_CLOSE(cleanup, pipefd[0]);
237
238 /* child is blocked, kill it */
239 if (TEST_RETURN == -2)
240 kill(child, SIGTERM);
241 if (waitpid(child, &status, 0) == -1)
242 tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
243 if (WIFEXITED(status)) {
244 if (WEXITSTATUS(status) == 0) {
245 return 0;
246 } else {
247 errno = WEXITSTATUS(status);
248 return -1;
249 }
250 }
251 return -2;
252}
253
254static void test_read_nonblock(void)
255{
256 int fd;
257
258 tst_resm(TINFO, "TEST: nonblock read");
259 fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
260 if (fd < 0)
261 tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg");
262
263 TEST(timed_read_kmsg(fd, READ_TIMEOUT));
264 if (TEST_RETURN == -1 && TEST_ERRNO == EAGAIN)
265 tst_resm(TPASS, "non-block read returned EAGAIN");
266 else
267 tst_resm(TFAIL|TTERRNO, "non-block read returned: %ld",
268 TEST_RETURN);
269 SAFE_CLOSE(cleanup, fd);
270}
271
272static void test_read_block(void)
273{
274 int fd;
275
276 tst_resm(TINFO, "TEST: blocking read");
277 fd = open("/dev/kmsg", O_RDONLY);
278 if (fd < 0)
279 tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg");
280
281 TEST(timed_read_kmsg(fd, READ_TIMEOUT));
282 if (TEST_RETURN == -2)
283 tst_resm(TPASS, "read blocked");
284 else
285 tst_resm(TFAIL|TTERRNO, "read returned: %ld", TEST_RETURN);
286 SAFE_CLOSE(cleanup, fd);
287}
288
289static void test_partial_read(void)
290{
291 char msg[MAX_MSGSIZE];
292 int fd;
293
294 tst_resm(TINFO, "TEST: partial read");
295 fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
296 if (fd < 0)
297 tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg");
298
299 TEST(read(fd, msg, 1));
300 if (TEST_RETURN < 0)
301 tst_resm(TPASS|TTERRNO, "read failed as expected");
302 else
303 tst_resm(TFAIL, "read returned: %ld", TEST_RETURN);
304 SAFE_CLOSE(cleanup, fd);
305}
306
307static void test_inject(void)
308{
309 char imsg[MAX_MSGSIZE], imsg_prefixed[MAX_MSGSIZE];
310 char tmp[MAX_MSGSIZE];
311 unsigned long prefix, seqno, seqno_last = 0;
312 int i, facility, prio;
313
314 tst_resm(TINFO, "TEST: injected messages appear in /dev/kmsg");
315
316 /* test all combinations of prio 0-7, facility 0-15 */
317 for (i = 0; i < 127; i++) {
318 prio = (i & 7);
319 facility = (i >> 3);
320 sprintf(imsg, MSG_PREFIX"TEST MESSAGE %ld prio: %d, "
321 "facility: %d\n", random(), prio, facility);
322 sprintf(imsg_prefixed, "<%d>%s", i, imsg);
323
324 if (inject_msg(imsg_prefixed) == -1) {
325 tst_resm(TFAIL|TERRNO, "inject failed");
326 return;
327 }
328
329 /* check that message appears in log */
330 if (find_msg(-1, imsg, tmp, sizeof(tmp), 0) == -1) {
331 tst_resm(TFAIL, "failed to find: %s", imsg);
332 return;
333 }
334
335 /* check that facility is not 0 (LOG_KERN). */
336 if (get_msg_fields(tmp, &prefix, &seqno) != 0) {
337 tst_resm(TFAIL, "failed to parse seqid: %s", tmp);
338 return;
339 }
340 if (prefix >> 3 == 0) {
341 tst_resm(TFAIL, "facility 0 found: %s", tmp);
342 return;
343 }
344
345 /* check that seq. number grows */
346 if (seqno > seqno_last) {
347 seqno_last = seqno;
348 } else {
349 tst_resm(TFAIL, "seqno doesn't grow: %lu, "
350 "last: %lu", seqno, seqno_last);
351 return;
352 }
353 }
354
355 tst_resm(TPASS, "injected messages found in log");
356 tst_resm(TPASS, "sequence numbers grow as expected");
357}
358
359static void test_read_returns_first_message(void)
360{
361 unsigned long seqno[NUM_READ_MSGS + 1];
362 char msg[MAX_MSGSIZE];
363 int msgs_match = 1;
364 int i, fd, j = NUM_READ_RETRY;
365
366 /* Open extra fd, which we try to read after reading NUM_READ_MSGS.
367 * If this read fails with EPIPE, first message was overwritten and
368 * we should retry the whole test. If it still fails after
369 * NUM_READ_RETRY attempts, report TWARN */
370 tst_resm(TINFO, "TEST: mult. readers will get same first message");
371 while (j) {
372 fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
373 if (fd < 0)
374 tst_brkm(TBROK|TERRNO, cleanup,
375 "failed to open /dev/kmsg");
376
377 for (i = 0; i < NUM_READ_MSGS; i++) {
378 if (find_msg(-1, "", msg, sizeof(msg), 1) != 0)
379 tst_resm(TFAIL, "failed to find any message");
380 if (get_msg_fields(msg, NULL, &seqno[i]) != 0)
381 tst_resm(TFAIL, "failed to parse seqid: %s",
382 msg);
383 }
384
385 TEST(read(fd, msg, sizeof(msg)));
386 SAFE_CLOSE(cleanup, fd);
387 if (TEST_RETURN != -1)
388 break;
389
390 if (TEST_ERRNO == EPIPE)
391 tst_resm(TINFO, "msg overwritten, retrying");
392 else
393 tst_resm(TFAIL|TTERRNO, "read failed");
394
395 /* give a second to whoever overwrote first message to finish */
396 sleep(1);
397 j--;
398 }
399
400 if (!j) {
401 tst_resm(TWARN, "exceeded: %d attempts", NUM_READ_RETRY);
402 return;
403 }
404
405 for (i = 0; i < NUM_READ_MSGS - 1; i++)
406 if (seqno[i] != seqno[i + 1])
407 msgs_match = 0;
408 if (msgs_match) {
409 tst_resm(TPASS, "all readers got same message on first read");
410 } else {
411 tst_resm(TFAIL, "readers got different messages");
412 for (i = 0; i < NUM_READ_MSGS; i++)
413 tst_resm(TINFO, "msg%d: %lu\n", i, seqno[i]);
414 }
415}
416
417static void test_messages_overwritten(void)
418{
419 int i, fd;
420 char msg[MAX_MSGSIZE];
421 unsigned long first_seqno, seqno;
422 char filler_str[] = MSG_PREFIX"FILLER MESSAGE TO OVERWRITE OTHERS\n";
423
424 /* Keep injecting messages until we overwrite first one.
425 * We know first message is overwritten when its seqno changes */
426 tst_resm(TINFO, "TEST: read returns EPIPE when messages get "
427 "overwritten");
428 fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
429 if (fd < 0)
430 tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg");
431
432 if (find_msg(-1, "", msg, sizeof(msg), 1) == 0
433 && get_msg_fields(msg, NULL, &first_seqno) == 0) {
434 tst_resm(TINFO, "first seqno: %lu", first_seqno);
435 } else {
436 tst_brkm(TBROK, cleanup, "failed to get first seq. number");
437 }
438
439 while (1) {
440 if (find_msg(-1, "", msg, sizeof(msg), 1) != 0
441 || get_msg_fields(msg, NULL, &seqno) != 0) {
442 tst_resm(TFAIL, "failed to get first seq. number");
443 break;
444 }
445 if (first_seqno != seqno) {
446 /* first message was overwritten */
447 tst_resm(TINFO, "first seqno now: %lu", seqno);
448 break;
449 }
450 for (i = 0; i < NUM_OVERWRITE_MSGS; i++) {
451 if (inject_msg(filler_str) == -1)
452 tst_brkm(TBROK|TERRNO, cleanup,
453 "failed write to /dev/kmsg");
454 }
455 }
456
457 /* first message is overwritten, so this next read should fail */
458 TEST(read(fd, msg, sizeof(msg)));
459 if (TEST_RETURN == -1 && TEST_ERRNO == EPIPE)
460 tst_resm(TPASS, "read failed with EPIPE as expected");
461 else
462 tst_resm(TFAIL|TTERRNO, "read returned: %ld", TEST_RETURN);
463
464 /* seek position is updated to the next available record */
465 tst_resm(TINFO, "TEST: Subsequent reads() will return available "
466 "records again");
467 if (find_msg(fd, "", msg, sizeof(msg), 1) != 0)
468 tst_resm(TFAIL|TTERRNO, "read returned: %ld", TEST_RETURN);
469 else
470 tst_resm(TPASS, "after EPIPE read returned next record");
471
472 SAFE_CLOSE(cleanup, fd);
473}
474
475static void test_seek(void)
476{
477 int k, j = NUM_READ_RETRY, fd;
478 char msg[MAX_MSGSIZE];
479 unsigned long seqno[2];
480
481 /* 1. read() after SEEK_SET 0 returns same (first) message */
482 tst_resm(TINFO, "TEST: seek SEEK_SET 0");
483
484 fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
485 if (fd < 0)
486 tst_brkm(TBROK|TERRNO, cleanup, "failed to open /dev/kmsg");
487
488 while (j) {
489 for (k = 0; k < 2; k++) {
490 TEST(read(fd, msg, sizeof(msg)));
491 if (TEST_RETURN == -1) {
492 if (errno == EPIPE)
493 break;
494 else
495 tst_brkm(TBROK|TTERRNO, cleanup,
496 "failed to read /dev/kmsg");
497 }
498 if (get_msg_fields(msg, NULL, &seqno[k]) != 0)
499 tst_resm(TFAIL, "failed to parse seqid: %s",
500 msg);
501 if (k == 0)
502 if (lseek(fd, 0, SEEK_SET) == -1)
503 tst_resm(TFAIL|TERRNO,
504 "SEEK_SET 0 failed");
505 }
506
507 if (TEST_RETURN != -1)
508 break;
509
510 /* give a second to whoever overwrote first message to finish */
511 sleep(1);
512 j--;
513
514 /* read above has returned EPIPE, reopen fd and try again */
515 SAFE_CLOSE(cleanup, fd);
516 fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
517 if (fd < 0)
518 tst_brkm(TBROK|TERRNO, cleanup,
519 "failed to open /dev/kmsg");
520 }
521
522 if (!j) {
523 tst_resm(TWARN, "exceeded: %d attempts", NUM_READ_RETRY);
524 } else {
525 if (seqno[0] != seqno[1])
526 tst_resm(TFAIL, "SEEK_SET 0");
527 else
528 tst_resm(TPASS, "SEEK_SET 0");
529 }
530
531 /* 2. messages after SEEK_END 0 shouldn't contain MSG_PREFIX */
532 tst_resm(TINFO, "TEST: seek SEEK_END 0");
533 if (lseek(fd, 0, SEEK_END) == -1)
534 tst_resm(TFAIL|TERRNO, "lseek SEEK_END 0 failed");
535 if (find_msg(fd, MSG_PREFIX, msg, sizeof(msg), 0) != 0)
536 tst_resm(TPASS, "SEEK_END 0");
537 else
538 tst_resm(TFAIL, "SEEK_END 0 found: %s", msg);
539
540#ifdef SEEK_DATA
541 /* 3. messages after SEEK_DATA 0 shouldn't contain MSG_PREFIX */
542 tst_resm(TINFO, "TEST: seek SEEK_DATA 0");
543
544 /* clear ring buffer */
545 if (ltp_syscall(__NR_syslog, 5, NULL, 0) == -1)
546 tst_brkm(TBROK|TERRNO, cleanup, "syslog clear failed");
547 if (lseek(fd, 0, SEEK_DATA) == -1)
548 tst_resm(TFAIL|TERRNO, "lseek SEEK_DATA 0 failed");
549 if (find_msg(fd, MSG_PREFIX, msg, sizeof(msg), 0) != 0)
550 tst_resm(TPASS, "SEEK_DATA 0");
551 else
552 tst_resm(TFAIL, "SEEK_DATA 0 found: %s", msg);
553#endif
554 SAFE_CLOSE(cleanup, fd);
555}
556
557int main(int argc, char *argv[])
558{
559 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200560 const char *msg;
Jan Stanceka0e618c2013-06-07 11:09:26 +0200561
562 msg = parse_opts(argc, argv, NULL, NULL);
563 if (msg != NULL)
564 tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
565
566 setup();
567 for (lc = 0; TEST_LOOPING(lc); lc++) {
568 /* run test_inject first so log isn't empty for other tests */
569 test_inject();
570 test_read_nonblock();
571 test_read_block();
572 test_partial_read();
573 test_read_returns_first_message();
574 test_messages_overwritten();
575 test_seek();
576 }
577 cleanup();
578 tst_exit();
579}
580
581static void setup(void)
582{
583 tst_require_root(NULL);
584 if (tst_kvercmp(3, 5, 0) < 0)
585 tst_brkm(TCONF, NULL, "This test requires kernel"
586 " >= 3.5.0");
587 srand(getpid());
588 TEST_PAUSE;
589}
590
591static void cleanup(void)
592{
Jan Stanceka0e618c2013-06-07 11:09:26 +0200593}