master
c 2,033 lines 46.4 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 pipe.c
8
9 Abstract:
10
11 This is the test for pipes.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <stdbool.h>
20 #include <sys/mman.h>
21 #include <sys/ioctl.h>
22 #include <poll.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <sys/wait.h>
26 #include <sys/epoll.h>
27 #include <sys/eventfd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/file.h>
31 #include <sys/fsuid.h>
32 #include <sys/cdefs.h>
33 #include <sys/prctl.h>
34 #include <linux/capability.h>
35 #include <limits.h>
36
37 #define LXT_NAME "Pipe"
38
39 #define min(_a, _b) ((_a) < (_b) ? (_a) : (_b))
40
41 #define _4KB (4 * 1024)
42
43 #define _32KB (32 * 1024)
44
45 #define _64KB (64 * 1024)
46
47 #define _1MB (1024 * 1024)
48
49 #define PIPE_DEFAULT_MAX_SIZE 1048576
50
51 #define ROUND_TO_PAGES(Size) (((unsigned long int)(Size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
52
53 #define PIPE_BUFFER_LENGTH (_1MB / sizeof(unsigned int))
54
55 #define PIPE_LOOPS (8)
56
57 #define PIPE_FIFO "/data/testfifo"
58 #define PIPE_FIFO_MESSAGE "Hello World!"
59
60 //
61 // Use /dev/fd, rather than /proc/self/fd directly, because that's what bash
62 // uses for process substitution.
63 //
64
65 #define PIPE_FD_PATH_FORMAT "/dev/fd/%d"
66 #define PIPE_CHILD_PATH_FORMAT "%s/%s"
67
68 int PipeCheckFdPath(int Fd);
69
70 LXT_VARIATION_HANDLER PipeEpoll;
71
72 LXT_VARIATION_HANDLER PipeFifo;
73
74 LXT_VARIATION_HANDLER PipeFifoNonBlock;
75
76 LXT_VARIATION_HANDLER PipeFifoReadWrite;
77
78 LXT_VARIATION_HANDLER PipeFifoReopen;
79
80 LXT_VARIATION_HANDLER PipeReopen;
81
82 LXT_VARIATION_HANDLER PipeStat;
83
84 LXT_VARIATION_HANDLER PipeFileLocking;
85
86 LXT_VARIATION_HANDLER PipeSecurity;
87
88 LXT_VARIATION_HANDLER PipeFcntl;
89
90 int PipeReader(unsigned int* Buffer, size_t BufferLength, int Pipe, bool Polling);
91
92 int PipeReaderHangup(PLXT_ARGS Args);
93
94 int PipeWriterHangup(PLXT_ARGS Args);
95
96 int PipeTest(bool Polling, bool UsePipe2);
97
98 int PipeVariation0(PLXT_ARGS Args);
99
100 int PipeVariation1(PLXT_ARGS Args);
101
102 int PipeVariationIoctl(PLXT_ARGS Args);
103
104 int PipeWriter(unsigned int* Buffer, size_t BufferLength, int Pipe, bool Polling);
105
106 int PipeZeroByteRead(PLXT_ARGS Args);
107
108 //
109 // Global constants
110 //
111
112 static const LXT_VARIATION g_LxtVariations[] = {
113 {"Pipe0", PipeVariation0},
114 {"Pipe1", PipeVariation1},
115 {"Pipe reader hangup", PipeReaderHangup},
116 {"Pipe writer hangup", PipeWriterHangup},
117 {"Pipe ioctls", PipeVariationIoctl},
118 {"Pipe - epoll", PipeEpoll},
119 {"Pipe - Fifo", PipeFifo},
120 {"Pipe - Fifo O_NONBLOCK", PipeFifoNonBlock},
121 {"Pipe - Fifo O_RDWR", PipeFifoReadWrite},
122 {"Pipe - Fifo re-open", PipeFifoReopen},
123 {"Pipe - fstat", PipeStat},
124 {"Pipe - File locking", PipeFileLocking},
125 {"Pipe - /proc/self/fd reopen", PipeReopen},
126 {"Pipe - Zero byte read", PipeZeroByteRead},
127 {"Pipe - security attributes", PipeSecurity},
128 {"Pipe - fcntl", PipeFcntl}};
129
130 int PipeTestEntry(int Argc, char* Argv[])
131
132 /*++
133 --*/
134
135 {
136
137 LXT_ARGS Args;
138 int Result;
139
140 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
141 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
142
143 ErrorExit:
144 LxtUninitialize();
145 return !LXT_SUCCESS(Result);
146 }
147
148 int PipeCheckFdPath(int Fd)
149
150 /*++
151
152 Description:
153
154 This routine checks the path string for a pipe file descriptor.
155
156 N.B. This routine should not be used for fifos.
157
158 Arguments:
159
160 Fd - Supplies the pipe file descriptor.
161
162 Return Value:
163
164 Returns 0 on success, -1 on failure.
165
166 --*/
167
168 {
169
170 char Expected[100];
171 int Result;
172 struct stat Stat;
173
174 LxtCheckErrnoZeroSuccess(fstat(Fd, &Stat));
175 sprintf(Expected, "pipe:[%lu]", Stat.st_ino);
176 LxtCheckResult(LxtCheckFdPath(Fd, Expected));
177
178 ErrorExit:
179 return Result;
180 }
181
182 int PipeEpoll(PLXT_ARGS Args)
183
184 /*++
185
186 Description:
187
188 This routine tests polling behavior for the read and write end of pipes.
189
190 Arguments:
191
192 Args - Supplies the command line arguments.
193
194 Return Value:
195
196 Returns 0 on success, -1 on failure.
197
198 --*/
199
200 {
201
202 char Buf[3];
203 int Count;
204 int Index;
205 int Pipes[2];
206 int PollFd;
207 int Result;
208 struct epoll_event Event;
209
210 PollFd = -1;
211 for (Index = 0; Index < LXT_COUNT_OF(Pipes); Index += 1)
212 {
213 Pipes[Index] = -1;
214 }
215
216 //
217 // Create a pipe and write to it so it's both read and write ready.
218 //
219
220 LxtCheckErrnoZeroSuccess(pipe(Pipes));
221 LxtCheckErrno(write(Pipes[1], "test", 4));
222
223 //
224 // Make sure polling for write times out on the read descriptor, but
225 // polling for read works.
226 //
227
228 LxtCheckErrno(PollFd = epoll_create1(0));
229 Event.events = EPOLLOUT;
230 Event.data.fd = Pipes[0];
231 LxtCheckErrno(epoll_ctl(PollFd, EPOLL_CTL_ADD, Pipes[0], &Event));
232 LxtCheckErrnoZeroSuccess(epoll_wait(PollFd, &Event, 1, 0));
233 Event.events = EPOLLIN;
234 LxtCheckErrno(epoll_ctl(PollFd, EPOLL_CTL_MOD, Pipes[0], &Event));
235 memset(&Event, 0, sizeof(Event));
236 LxtCheckErrno(Count = epoll_wait(PollFd, &Event, 1, 0));
237 LxtCheckEqual(Count, 1, "%d");
238 LxtCheckEqual(Event.events, EPOLLIN, "0x%x");
239
240 //
241 // Make sure polling for read times out on the write descriptor, but
242 // polling for write works.
243 //
244
245 LxtCheckErrno(epoll_ctl(PollFd, EPOLL_CTL_DEL, Pipes[0], NULL));
246 Event.events = EPOLLIN;
247 Event.data.fd = Pipes[1];
248 LxtCheckErrno(epoll_ctl(PollFd, EPOLL_CTL_ADD, Pipes[1], &Event));
249 LxtCheckErrnoZeroSuccess(epoll_wait(PollFd, &Event, 1, 0));
250 Event.events = EPOLLOUT;
251 LxtCheckErrno(epoll_ctl(PollFd, EPOLL_CTL_MOD, Pipes[1], &Event));
252 memset(&Event, 0, sizeof(Event));
253 LxtCheckErrno(Count = epoll_wait(PollFd, &Event, 1, 0));
254 LxtCheckEqual(Count, 1, "%d");
255 LxtCheckEqual(Event.events, EPOLLOUT, "0x%x");
256
257 //
258 // Test edge triggered epoll events.
259 //
260
261 Event.events = EPOLLOUT | EPOLLET;
262 LxtCheckErrno(epoll_ctl(PollFd, EPOLL_CTL_MOD, Pipes[1], &Event));
263 Event.events = EPOLLIN | EPOLLET;
264 Event.data.fd = Pipes[0];
265 LxtCheckErrno(epoll_ctl(PollFd, EPOLL_CTL_ADD, Pipes[0], &Event));
266 memset(&Event, 0, sizeof(Event));
267 LxtCheckErrno(Count = epoll_wait(PollFd, &Event, 1, 0));
268 LxtCheckEqual(Count, 1, "%d");
269 LxtCheckEqual(Event.events, EPOLLOUT, "0x%x");
270 LxtCheckErrno(Count = epoll_wait(PollFd, &Event, 1, 0));
271 LxtCheckEqual(Count, 1, "%d");
272 LxtCheckEqual(Event.events, EPOLLIN, "0x%x");
273
274 //
275 // Both edge-triggered events should have fired, so no new events should
276 // be available.
277 //
278
279 LxtCheckErrnoZeroSuccess(epoll_wait(PollFd, &Event, 1, 0));
280
281 //
282 // Perform read and write operations and recheck epoll status.
283 //
284
285 LxtCheckErrno(write(Pipes[1], "more", 4));
286 LxtCheckErrno(Count = epoll_wait(PollFd, &Event, 1, 0));
287 LxtCheckEqual(Count, 1, "%d");
288 if (Event.events == EPOLLOUT)
289 {
290
291 //
292 // TODO_LX: The WSL pipe implementation shares the epoll between both
293 // endpoints, so the write endpoint is triggered here when it
294 // is not expected.
295 //
296
297 LxtCheckErrno(Count = epoll_wait(PollFd, &Event, 1, 0));
298 LxtCheckEqual(Count, 1, "%d");
299 }
300
301 LxtCheckEqual(Event.events, EPOLLIN, "0x%x");
302 LxtCheckErrnoZeroSuccess(epoll_wait(PollFd, &Event, 1, 0));
303 LxtCheckErrno(read(Pipes[0], Buf, sizeof(Buf)));
304 LxtCheckErrnoZeroSuccess(epoll_wait(PollFd, &Event, 1, 0));
305
306 ErrorExit:
307 if (PollFd >= 0)
308 {
309 close(PollFd);
310 }
311
312 for (Index = 0; Index < LXT_COUNT_OF(Pipes); Index += 1)
313 {
314 if (Pipes[Index] >= 0)
315 {
316 close(Pipes[Index]);
317 }
318 }
319
320 return Result;
321 }
322
323 int PipeFifo(PLXT_ARGS Args)
324
325 /*++
326
327 Description:
328
329 This routine tests fifo files.
330
331 Arguments:
332
333 Args - Supplies the command line arguments.
334
335 Return Value:
336
337 Returns 0 on success, -1 on failure.
338
339 --*/
340
341 {
342
343 unsigned int* Buffer;
344 ssize_t Bytes;
345 pid_t ChildPid;
346 int Fd;
347 int Fd2;
348 int Result;
349 struct stat Stat;
350
351 Fd = -1;
352 Fd2 = -1;
353 Buffer = NULL;
354 LXT_SYNCHRONIZATION_POINT_INIT();
355
356 //
357 // Create the fifo and make sure umask is applied.
358 //
359
360 umask(022);
361 LxtCheckErrnoZeroSuccess(mkfifo(PIPE_FIFO, 0666));
362 LxtCheckErrnoZeroSuccess(lstat(PIPE_FIFO, &Stat));
363 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0644, "0%o");
364
365 //
366 // Check error when the file exists.
367 //
368
369 LxtCheckErrnoFailure(mkfifo(PIPE_FIFO, 0666), EEXIST);
370
371 //
372 // Fork and connect.
373 //
374
375 Buffer = malloc(PIPE_BUFFER_LENGTH * sizeof(int));
376 LxtCheckNotEqual(Buffer, NULL, "%p");
377 LXT_SYNCHRONIZATION_POINT_START();
378 LxtCheckErrno(ChildPid = fork());
379 if (ChildPid == 0)
380 {
381 LxtCheckErrno(Fd = open(PIPE_FIFO, O_RDONLY));
382 LxtCheckResult(LxtCheckFdPath(Fd, PIPE_FIFO));
383 LXT_SYNCHRONIZATION_POINT();
384 LxtCheckResult(PipeReader(Buffer, PIPE_BUFFER_LENGTH, Fd, false));
385
386 //
387 // Connect a second writer.
388 //
389
390 LxtCheckErrno(Fd2 = open(PIPE_FIFO, O_WRONLY));
391 Buffer[0] = 42;
392 LxtCheckErrno(Bytes = write(Fd2, Buffer, sizeof(int)));
393 LxtCheckEqual(Bytes, sizeof(int), "%ld");
394 Buffer[0] = 0;
395 LxtCheckErrno(Bytes = read(Fd, Buffer, PIPE_BUFFER_LENGTH * sizeof(int)));
396 LxtCheckEqual(Bytes, sizeof(int), "%ld");
397 LxtCheckEqual(Buffer[0], 42, "%u");
398 close(Fd);
399 close(Fd2);
400 exit(0);
401 }
402
403 //
404 // Sleep to test blocking behavior on open for the child.
405 //
406
407 sleep(1);
408 LxtCheckErrno(Fd = open(PIPE_FIFO, O_WRONLY));
409 LxtCheckResult(LxtCheckFdPath(Fd, PIPE_FIFO));
410
411 //
412 // Use the synchronization point to ensure open unblocks before calling
413 // write.
414 //
415
416 LXT_SYNCHRONIZATION_POINT();
417 LxtCheckResult(PipeWriter(Buffer, PIPE_BUFFER_LENGTH, Fd, false));
418 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
419
420 ErrorExit:
421 if (Fd2 >= 0)
422 {
423 close(Fd2);
424 }
425
426 if (Fd >= 0)
427 {
428 close(Fd);
429 }
430
431 if (Buffer != NULL)
432 {
433 free(Buffer);
434 }
435
436 unlink(PIPE_FIFO);
437 LXT_SYNCHRONIZATION_POINT_DESTROY();
438 return Result;
439 }
440
441 int PipeFifoNonBlock(PLXT_ARGS Args)
442
443 /*++
444
445 Description:
446
447 This routine tests fifo files with O_NONBLOCK.
448
449 Arguments:
450
451 Args - Supplies the command line arguments.
452
453 Return Value:
454
455 Returns 0 on success, -1 on failure.
456
457 --*/
458
459 {
460
461 unsigned int* Buffer;
462 pid_t ChildPid;
463 int Fd;
464 int Result;
465 struct stat Stat;
466
467 Fd = -1;
468 Buffer = NULL;
469
470 //
471 // Create the fifo and make sure umask is applied.
472 //
473
474 umask(0);
475 LxtCheckErrnoZeroSuccess(mkfifo(PIPE_FIFO, 0666));
476 LxtCheckErrnoZeroSuccess(lstat(PIPE_FIFO, &Stat));
477 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0666, "0%o");
478
479 //
480 // Try to connect with write when there's no reader, non-blocking.
481 //
482
483 LxtCheckErrnoFailure(Fd = open(PIPE_FIFO, O_WRONLY | O_NONBLOCK), ENXIO);
484
485 //
486 // Fork and connect.
487 //
488
489 Buffer = malloc(PIPE_BUFFER_LENGTH * sizeof(int));
490 LxtCheckNotEqual(Buffer, NULL, "%p");
491 LxtCheckErrno(ChildPid = fork());
492 if (ChildPid == 0)
493 {
494 LxtCheckErrno(Fd = open(PIPE_FIFO, O_RDONLY | O_NONBLOCK));
495 LxtCheckResult(LxtCheckFdPath(Fd, PIPE_FIFO));
496 LxtCheckErrnoZeroSuccess(read(Fd, Buffer, PIPE_BUFFER_LENGTH)) LxtCheckResult(PipeReader(Buffer, PIPE_BUFFER_LENGTH, Fd, true));
497 close(Fd);
498 exit(0);
499 }
500
501 //
502 // O_NONBLOCK for write works once there is a reader.
503 //
504
505 sleep(1);
506 LxtCheckErrno(Fd = open(PIPE_FIFO, O_WRONLY | O_NONBLOCK));
507 LxtCheckResult(LxtCheckFdPath(Fd, PIPE_FIFO));
508 LxtCheckResult(PipeWriter(Buffer, PIPE_BUFFER_LENGTH, Fd, true));
509 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
510
511 ErrorExit:
512 if (Fd >= 0)
513 {
514 close(Fd);
515 }
516
517 if (Buffer != NULL)
518 {
519 free(Buffer);
520 }
521
522 unlink(PIPE_FIFO);
523 return Result;
524 }
525
526 int PipeFifoReadWrite(PLXT_ARGS Args)
527
528 /*++
529
530 Description:
531
532 This routine tests opening a fifo for read/write.
533
534 Arguments:
535
536 Args - Supplies the command line arguments.
537
538 Return Value:
539
540 Returns 0 on success, -1 on failure.
541
542 --*/
543
544 {
545
546 char Buffer[100];
547 ssize_t Bytes;
548 int Fd;
549 int Result;
550 struct stat Stat;
551
552 Fd = -1;
553
554 //
555 // Create the fifo and make sure umask is applied.
556 //
557
558 umask(0);
559 LxtCheckErrnoZeroSuccess(mkfifo(PIPE_FIFO, 0666));
560 LxtCheckErrnoZeroSuccess(lstat(PIPE_FIFO, &Stat));
561 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0666, "0%o");
562
563 //
564 // Open the fifo for read/write which should not block.
565 //
566
567 LxtCheckErrno(Fd = open(PIPE_FIFO, O_RDWR));
568 LxtCheckResult(LxtCheckFdPath(Fd, PIPE_FIFO));
569 LxtCheckErrno(Bytes = write(Fd, PIPE_FIFO_MESSAGE, strlen(PIPE_FIFO_MESSAGE) + 1));
570
571 LxtCheckEqual(Bytes, strlen(PIPE_FIFO_MESSAGE) + 1, "%ld");
572 LxtCheckErrno(Bytes = read(Fd, Buffer, sizeof(Buffer)));
573 LxtCheckEqual(Bytes, strlen(PIPE_FIFO_MESSAGE) + 1, "%ld");
574 LxtCheckStringEqual(Buffer, PIPE_FIFO_MESSAGE);
575
576 ErrorExit:
577 if (Fd >= 0)
578 {
579 close(Fd);
580 }
581
582 unlink(PIPE_FIFO);
583 return Result;
584 }
585
586 int PipeFifoReopen(PLXT_ARGS Args)
587
588 /*++
589
590 Description:
591
592 This routine tests reopening a pipe after closing one end.
593
594 Arguments:
595
596 Args - Supplies the command line arguments.
597
598 Return Value:
599
600 Returns 0 on success, -1 on failure.
601
602 --*/
603
604 {
605
606 char Buffer[100];
607 ssize_t Bytes;
608 int ChildPid;
609 int Count;
610 int ReadFd;
611 int Result;
612 int WriteFd;
613 struct pollfd PollFd;
614
615 ReadFd = -1;
616 WriteFd = -1;
617
618 //
619 // Fork because this test changes signal state.
620 //
621
622 LxtCheckErrno(ChildPid = fork());
623 if (ChildPid == 0)
624 {
625 LxtCheckResult(LxtSignalInitialize());
626 LxtCheckResult(LxtSignalSetupHandler(SIGPIPE, SA_SIGINFO));
627
628 //
629 // Create and open the fifo.
630 //
631
632 LxtCheckErrnoZeroSuccess(mkfifo(PIPE_FIFO, 0666));
633 LxtCheckErrno(ReadFd = open(PIPE_FIFO, O_RDONLY | O_NONBLOCK));
634 LxtCheckErrno(WriteFd = open(PIPE_FIFO, O_WRONLY | O_NONBLOCK));
635 memset(&PollFd, 0, sizeof(PollFd));
636
637 //
638 // Check the initial state of the write end.
639 //
640
641 PollFd.fd = WriteFd;
642 PollFd.events = POLLIN | POLLOUT | POLLERR | POLLHUP;
643 LxtCheckErrno(Count = poll(&PollFd, 1, 1000));
644 LxtCheckEqual(Count, 1, "%d");
645 LxtCheckEqual(PollFd.revents, POLLOUT, "0x%x");
646
647 //
648 // Close the read end and check the write end returns error.
649 //
650
651 LxtCheckErrnoZeroSuccess(close(ReadFd));
652 ReadFd = -1;
653 LxtCheckErrno(Count = poll(&PollFd, 1, 1000));
654 LxtCheckEqual(Count, 1, "%d");
655 LxtCheckEqual(PollFd.revents, POLLOUT | POLLERR, "0x%x");
656 LxtCheckErrnoFailure(write(WriteFd, PIPE_FIFO_MESSAGE, strlen(PIPE_FIFO_MESSAGE) + 1), EPIPE);
657
658 LxtCheckResult(LxtSignalCheckInfoReceived(SIGPIPE, SI_USER, getpid(), getuid()));
659
660 //
661 // Try to open an additional write end, which should fail because there
662 // is no reader.
663 //
664
665 LxtCheckErrnoFailure(open(PIPE_FIFO, O_WRONLY | O_NONBLOCK), ENXIO);
666
667 //
668 // Open a new read end and check the write end is functional again.
669 //
670
671 LxtCheckErrno(ReadFd = open(PIPE_FIFO, O_RDONLY | O_NONBLOCK));
672 LxtCheckErrno(Count = poll(&PollFd, 1, 1000));
673 LxtCheckEqual(Count, 1, "%d");
674 LxtCheckEqual(PollFd.revents, POLLOUT, "0x%x");
675 LxtCheckErrno(Bytes = write(WriteFd, PIPE_FIFO_MESSAGE, strlen(PIPE_FIFO_MESSAGE) + 1));
676
677 LxtCheckEqual(Bytes, strlen(PIPE_FIFO_MESSAGE) + 1, "%ld");
678
679 //
680 // Check the poll state of the read end.
681 //
682
683 PollFd.fd = ReadFd;
684 LxtCheckErrno(Count = poll(&PollFd, 1, 1000));
685 LxtCheckEqual(Count, 1, "%d");
686 LxtCheckEqual(PollFd.revents, POLLIN, "0x%x");
687
688 //
689 // Close the write end and check the read end reports hangup.
690 //
691
692 LxtCheckErrnoZeroSuccess(close(WriteFd));
693 WriteFd = -1;
694 LxtCheckErrno(Count = poll(&PollFd, 1, 1000));
695 LxtCheckEqual(Count, 1, "%d");
696 LxtCheckEqual(PollFd.revents, POLLIN | POLLHUP, "0x%x");
697
698 //
699 // Open a new write end and check the read end returns the old data.
700 //
701
702 LxtCheckErrno(WriteFd = open(PIPE_FIFO, O_WRONLY | O_NONBLOCK));
703 LxtCheckErrno(Count = poll(&PollFd, 1, 1000));
704 LxtCheckEqual(Count, 1, "%d");
705 LxtCheckEqual(PollFd.revents, POLLIN, "0x%x");
706 LxtCheckErrno(Bytes = read(ReadFd, Buffer, sizeof(Buffer)));
707 LxtCheckEqual(Bytes, strlen(PIPE_FIFO_MESSAGE) + 1, "%ld");
708 LxtCheckStringEqual(Buffer, PIPE_FIFO_MESSAGE);
709
710 //
711 // Read should fail now because there's no more data.
712 //
713
714 LxtCheckErrnoFailure(read(ReadFd, Buffer, sizeof(Buffer)), EAGAIN);
715
716 //
717 // Close the write end and make sure the read end return EOF.
718 //
719
720 LxtCheckErrnoZeroSuccess(close(WriteFd));
721 LxtCheckErrnoZeroSuccess(read(ReadFd, Buffer, sizeof(Buffer)));
722 LxtCheckErrnoZeroSuccess(close(ReadFd));
723 exit(0);
724 }
725
726 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
727
728 ErrorExit:
729 if (ReadFd >= 0)
730 {
731 close(ReadFd);
732 }
733
734 if (WriteFd >= 0)
735 {
736 close(WriteFd);
737 }
738
739 unlink(PIPE_FIFO);
740 return Result;
741 }
742
743 int PipeReopen(PLXT_ARGS Args)
744
745 /*++
746
747 Description:
748
749 This routine tests reopening a pipe through /proc/self/fd.
750
751 Arguments:
752
753 Args - Supplies the command line arguments.
754
755 Return Value:
756
757 Returns 0 on success, -1 on failure.
758
759 --*/
760
761 {
762
763 char Buffer[100];
764 int ChildPid;
765 int Fd;
766 struct stat FdStat;
767 char ChildPath[PATH_MAX];
768 char Path[PATH_MAX];
769 int Pipes[2];
770 struct stat PipeStat;
771 int Result;
772
773 Pipes[0] = -1;
774 Pipes[1] = -1;
775 Fd = -1;
776 ChildPid = -1;
777 LxtCheckErrnoZeroSuccess(pipe(Pipes));
778 LxtCheckErrno(write(Pipes[1], PIPE_FIFO_MESSAGE, sizeof(PIPE_FIFO_MESSAGE)));
779
780 //
781 // Attempt to reopen the read end.
782 //
783
784 sprintf(Path, PIPE_FD_PATH_FORMAT, Pipes[0]);
785 LxtCheckErrno(Fd = open(Path, O_RDONLY));
786 memset(Buffer, 0, sizeof(Buffer));
787 LxtCheckErrno(read(Fd, Buffer, sizeof(Buffer)));
788 LxtCheckStringEqual(Buffer, PIPE_FIFO_MESSAGE);
789 LxtCheckErrnoZeroSuccess(close(Fd));
790
791 //
792 // Reopen the write end through the read FD.
793 //
794
795 LxtCheckErrno(Fd = open(Path, O_WRONLY));
796 LxtCheckErrno(write(Fd, PIPE_FIFO_MESSAGE, sizeof(PIPE_FIFO_MESSAGE)));
797 memset(Buffer, 0, sizeof(Buffer));
798 LxtCheckErrno(read(Pipes[0], Buffer, sizeof(Buffer)));
799 LxtCheckStringEqual(Buffer, PIPE_FIFO_MESSAGE);
800
801 //
802 // Check the result of stat.
803 //
804
805 LxtCheckErrnoZeroSuccess(fstat(Pipes[0], &PipeStat));
806 LxtCheckErrnoZeroSuccess(stat(Path, &FdStat));
807 LxtCheckMemoryEqual(&PipeStat, &FdStat, sizeof(struct stat));
808
809 //
810 // Failing variations.
811 //
812
813 sprintf(ChildPath, PIPE_CHILD_PATH_FORMAT, Path, ".");
814 LxtCheckErrnoFailure(open(ChildPath, O_RDONLY), ENOTDIR);
815 sprintf(ChildPath, PIPE_CHILD_PATH_FORMAT, Path, "..");
816 LxtCheckErrnoFailure(open(ChildPath, O_RDONLY), ENOTDIR);
817 sprintf(ChildPath, PIPE_CHILD_PATH_FORMAT, Path, "foo");
818 LxtCheckErrnoFailure(open(ChildPath, O_RDONLY), ENOTDIR);
819 LxtCheckErrnoFailure(openat(Fd, "foo", O_RDONLY), ENOTDIR);
820
821 //
822 // Pipes have permissions set to 0600, so they can only be reopened by the
823 // owner.
824 //
825
826 LxtCheckErrno(ChildPid = fork());
827 if (ChildPid == 0)
828 {
829 setuid(1000);
830 LxtCheckErrnoFailure(open(Path, O_RDONLY), EACCES);
831 goto ErrorExit;
832 }
833
834 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
835
836 ErrorExit:
837 if (Pipes[0] >= 0)
838 {
839 close(Pipes[0]);
840 }
841
842 if (Pipes[1] >= 0)
843 {
844 close(Pipes[1]);
845 }
846
847 if (Fd >= 0)
848 {
849 close(Fd);
850 }
851
852 if (ChildPid == 0)
853 {
854 exit(Result);
855 }
856
857 return Result;
858 }
859
860 int PipeStat(PLXT_ARGS Args)
861
862 /*++
863
864 Description:
865
866 This routine tests the results of fstat on a pipe.
867
868 Arguments:
869
870 Args - Supplies the command line arguments.
871
872 Return Value:
873
874 Returns 0 on success, -1 on failure.
875
876 --*/
877
878 {
879
880 int ChildPid;
881 int Pipes[2];
882 int Result;
883 struct stat Stat;
884
885 Pipes[0] = -1;
886 Pipes[1] = -1;
887 LxtCheckErrno(ChildPid = fork());
888 if (ChildPid == 0)
889 {
890 LxtCheckErrno(setfsgid(1001));
891 LxtCheckErrno(setfsuid(1000));
892 LxtCheckErrnoZeroSuccess(pipe(Pipes));
893 LxtCheckErrnoZeroSuccess(fstat(Pipes[0], &Stat));
894 LxtCheckGreater(Stat.st_ino, 0, "%lu");
895 LxtCheckEqual(Stat.st_uid, 1000, "%d");
896 LxtCheckEqual(Stat.st_gid, 1001, "%d");
897 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0600, "%d");
898 LxtCheckEqual(Stat.st_blksize, 4096, "%ld");
899 LxtCheckEqual(Stat.st_blocks, 0, "%ld");
900 LxtCheckEqual(Stat.st_size, 0, "%ld");
901 LxtCheckEqual(Stat.st_nlink, 1, "%u");
902 LxtCheckResult(PipeCheckFdPath(Pipes[0]));
903 LxtCheckResult(PipeCheckFdPath(Pipes[1]));
904 LxtCheckErrnoZeroSuccess(close(Pipes[0]));
905 LxtCheckErrnoZeroSuccess(close(Pipes[1]));
906 exit(0);
907 }
908
909 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
910
911 ErrorExit:
912 if (Pipes[0] >= 0)
913 {
914 close(Pipes[0]);
915 }
916
917 if (Pipes[1] >= 0)
918 {
919 close(Pipes[1]);
920 }
921
922 return Result;
923 }
924
925 int PipeTest(bool Polling, bool UsePipe2)
926
927 /*++
928 --*/
929
930 {
931
932 unsigned int* Buffer;
933 bool Child;
934 pid_t Pid;
935 int Pipes[2];
936 int Result;
937 int ReturnStatus;
938
939 Child = false;
940 Pid = -1;
941 Buffer = mmap(NULL, PIPE_BUFFER_LENGTH * sizeof(unsigned int), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
942
943 if (Buffer == MAP_FAILED)
944 {
945 Result = -1;
946 LxtLogError("Could not map buffer! %d", errno);
947 goto PipeTestEnd;
948 }
949
950 if (UsePipe2 == false)
951 {
952 Result = pipe(Pipes);
953 if (Result == -1)
954 {
955 LxtLogError("Could not create pipes with pipe! %d", errno);
956 goto PipeTestEnd;
957 }
958 }
959 else
960 {
961 Result = LxtPipe2(Pipes, 0);
962 if (Result == -1)
963 {
964 LxtLogError("Could not create pipes with pipe2! %d", errno);
965 goto PipeTestEnd;
966 }
967 }
968
969 if (Polling != false)
970 {
971 Result = fcntl(Pipes[0], F_SETFL, O_NONBLOCK);
972 if (Result == -1)
973 {
974 LxtLogError("Could not set pipe to non-blocking! %d", errno);
975 goto PipeTestEnd;
976 }
977
978 Result = fcntl(Pipes[1], F_SETFL, O_NONBLOCK);
979 if (Result == -1)
980 {
981 LxtLogError("Could not set pipe to non-blocking! %d", errno);
982 goto PipeTestEnd;
983 }
984 }
985
986 Pid = fork();
987 if (Pid == -1)
988 {
989 LxtLogError("Could not fork! %d", errno);
990 goto PipeTestEnd;
991 }
992
993 if (Pid > 0)
994 {
995 close(Pipes[0]);
996 Result = PipeWriter(Buffer, PIPE_BUFFER_LENGTH, Pipes[1], Polling);
997 if (Result == -1)
998 {
999 LxtLogError("PipeWriter failed! %d", errno);
1000 goto PipeTestEnd;
1001 }
1002 }
1003 else
1004 {
1005 Child = true;
1006 close(Pipes[1]);
1007 Result = PipeReader(Buffer, PIPE_BUFFER_LENGTH, Pipes[0], Polling);
1008 if (Result == -1)
1009 {
1010 LxtLogError("PipeReader failed! %d", errno);
1011 goto PipeTestEnd;
1012 }
1013 }
1014
1015 Result = LXT_RESULT_SUCCESS;
1016
1017 PipeTestEnd:
1018 if (Child != false)
1019 {
1020 _exit(0);
1021 }
1022 else if (Pid > 0)
1023 {
1024 Result = waitpid(Pid, &ReturnStatus, 0);
1025 if (Result == -1)
1026 {
1027 LxtLogError("PipeTest reader child failed: %d", errno);
1028 }
1029 else
1030 {
1031 LxtLogInfo("PipeTest read child has exited.");
1032 }
1033 }
1034
1035 if (Buffer != NULL)
1036 {
1037 munmap(Buffer, PIPE_BUFFER_LENGTH * sizeof(unsigned int));
1038 }
1039
1040 return Result;
1041 }
1042
1043 int PipeVariation0(PLXT_ARGS Args)
1044
1045 /*++
1046 --*/
1047
1048 {
1049
1050 return PipeTest(false, false);
1051 }
1052
1053 int PipeWriter(unsigned int* Buffer, size_t BufferLength, int Pipe, bool Polling)
1054
1055 /*++
1056 --*/
1057
1058 {
1059
1060 char* Current;
1061 size_t Index;
1062 size_t Loop;
1063 int Result;
1064 struct pollfd PollFd;
1065 size_t Size;
1066 size_t SizeRemaining;
1067 unsigned int Value;
1068 size_t WriteSize;
1069 ssize_t Written;
1070
1071 PollFd.fd = Pipe;
1072 PollFd.events = POLLOUT;
1073 Value = 0;
1074 Size = BufferLength * sizeof(unsigned int);
1075
1076 for (Loop = 0; Loop < PIPE_LOOPS; Loop += 1)
1077 {
1078 LxtLogInfo("Loop #%u...", Loop);
1079 for (Index = 0; Index < BufferLength; Index += 1)
1080 {
1081 Buffer[Index] = Value;
1082 Value += 1;
1083 }
1084
1085 if (Polling != false)
1086 {
1087 SizeRemaining = Size;
1088 Current = (char*)Buffer;
1089 while (SizeRemaining > 0)
1090 {
1091 Result = poll(&PollFd, 1, -1);
1092 if (Result == -1)
1093 {
1094 Result = errno;
1095 LxtLogError("Failed to poll for write! %d", Result);
1096 goto WriterEnd;
1097 }
1098
1099 if ((PollFd.revents & POLLOUT) == 0)
1100 {
1101 LxtLogError("Error condition on write poll!");
1102 Result = EINVAL;
1103 goto WriterEnd;
1104 }
1105
1106 while (SizeRemaining > 0)
1107 {
1108 WriteSize = min(SizeRemaining, _32KB);
1109 Written = write(Pipe, Current, WriteSize);
1110 if (Written == -1)
1111 {
1112 if (errno == EAGAIN)
1113 {
1114 LxtLogInfo("Write would have blocked");
1115 break;
1116 }
1117
1118 Result = errno;
1119 LxtLogError("Failed to write! %d", Result);
1120 goto WriterEnd;
1121 }
1122
1123 SizeRemaining -= Written;
1124 Current += Written;
1125 }
1126 }
1127 }
1128 else
1129 {
1130 Written = write(Pipe, Buffer, Size);
1131 if (Written != (ssize_t)Size)
1132 {
1133 if (Written >= 0)
1134 {
1135 LxtLogError("Wrote fewer bytes (%d) than expected (%d)!", Written, Size);
1136 Result = EINVAL;
1137 }
1138 else
1139 {
1140 Result = errno;
1141 LxtLogError("Failed to write! %d", Result);
1142 }
1143
1144 goto WriterEnd;
1145 }
1146 }
1147 }
1148
1149 Result = 0;
1150
1151 WriterEnd:
1152 if (Result != 0)
1153 {
1154 errno = Result;
1155 Result = -1;
1156 }
1157
1158 return Result;
1159 }
1160
1161 int PipeReader(unsigned int* Buffer, size_t BufferLength, int Pipe, bool Polling)
1162
1163 /*++
1164 --*/
1165
1166 {
1167
1168 int BytesAvailable;
1169 char* Current;
1170 size_t Index;
1171 size_t Loop;
1172 struct pollfd PollFd;
1173 ssize_t Read;
1174 int Result;
1175 size_t Size;
1176 size_t SizeRemaining;
1177 unsigned int Value;
1178
1179 PollFd.fd = Pipe;
1180 PollFd.events = POLLIN;
1181 Value = 0;
1182 Size = BufferLength * sizeof(unsigned int);
1183 for (Loop = 0; Loop < PIPE_LOOPS; Loop += 1)
1184 {
1185 LxtLogInfo("Loop #%u...", Loop);
1186 Current = (char*)Buffer;
1187 SizeRemaining = Size;
1188 while (SizeRemaining > 0)
1189 {
1190 if (Polling != false)
1191 {
1192 Result = poll(&PollFd, 1, -1);
1193 if (Result == -1)
1194 {
1195 Result = errno;
1196 LxtLogError("Failed to poll for read! %d", Result);
1197 goto ErrorExit;
1198 }
1199
1200 if ((PollFd.revents & POLLIN) == 0)
1201 {
1202 LxtLogError("Error condition on read poll: 0x%X!", PollFd.revents);
1203 Result = EINVAL;
1204 goto ErrorExit;
1205 }
1206 }
1207
1208 //
1209 // Query the number of bytes available via the FIONREAD ioctl.
1210 //
1211
1212 LxtCheckErrno(ioctl(Pipe, FIONREAD, &BytesAvailable));
1213 Read = read(Pipe, Current, _4KB);
1214 if (Read == -1)
1215 {
1216 Result = errno;
1217 LxtLogError("Failed to read! %d", Result);
1218 goto ErrorExit;
1219 }
1220
1221 if ((Read == 0) || (Read % sizeof(unsigned int) != 0))
1222 {
1223 LxtLogError("Read an invalid number of bytes (%d)!", Read);
1224 Result = EINVAL;
1225 goto ErrorExit;
1226 }
1227
1228 Current += Read;
1229 SizeRemaining -= Read;
1230 }
1231
1232 //
1233 // Validate the buffer.
1234 //
1235
1236 for (Index = 0; Index < BufferLength; Index += 1)
1237 {
1238 if (Buffer[Index] != Value)
1239 {
1240 LxtLogError("PipeReader buffer invalid - contains %u instead of expected %u!", Buffer[Index], Value);
1241 Result = EINVAL;
1242 goto ErrorExit;
1243 }
1244
1245 Value += 1;
1246 }
1247 }
1248
1249 LxtLogInfo("Reads finished");
1250 Result = 0;
1251
1252 ErrorExit:
1253 if (Result != 0)
1254 {
1255 errno = Result;
1256 Result = -1;
1257 }
1258
1259 return Result;
1260 }
1261
1262 int PipeVariation1(PLXT_ARGS Args)
1263
1264 /*++
1265 --*/
1266
1267 {
1268
1269 return PipeTest(true, true);
1270 }
1271
1272 int PipeReaderHangup(PLXT_ARGS Args)
1273
1274 /*++
1275
1276 Routine Description:
1277
1278 This routine validates the reader hangup epoll semantics.
1279
1280 Arguments:
1281
1282 Args - Supplies the command line arguments.
1283
1284 Return Value:
1285
1286 Returns 0 on success, -1 on failure.
1287
1288 --*/
1289
1290 {
1291
1292 ssize_t BytesRead;
1293 ssize_t BytesWritten;
1294 ssize_t ExpectedResult;
1295 char* Message = "This is a test string for piping";
1296 int Pipes[2] = {-1, -1};
1297 struct pollfd PollFd;
1298 char ReadBuffer[100];
1299 int Result;
1300
1301 //
1302 // Create a pipe.
1303 //
1304
1305 LxtCheckErrno(pipe(Pipes));
1306
1307 //
1308 // Set the pipe FD's to non-blocking.
1309 //
1310
1311 LxtLogInfo("Creating a pipe...");
1312 LxtCheckErrno(fcntl(Pipes[0], F_SETFL, O_NONBLOCK));
1313 LxtCheckErrno(fcntl(Pipes[1], F_SETFL, O_NONBLOCK));
1314
1315 //
1316 // Write some data to the pipe.
1317 //
1318
1319 LxtLogInfo("Writing some data to the pipe.");
1320 ExpectedResult = strlen(Message);
1321 LxtCheckErrno((BytesWritten = write(Pipes[1], Message, ExpectedResult)));
1322 LxtCheckEqual(ExpectedResult, BytesWritten, "%d");
1323
1324 //
1325 // Validate that the only epoll flag set on the reader end is EPOLLIN.
1326 //
1327
1328 LxtLogInfo(
1329 "Validating that the EPOLLIN is set on the reader end of the "
1330 "pipe.");
1331
1332 PollFd.revents = 0;
1333 PollFd.fd = Pipes[0];
1334 PollFd.events = POLLIN | POLLOUT;
1335 LxtCheckErrno(poll(&PollFd, 1, -1));
1336 if (PollFd.revents != POLLIN)
1337 {
1338 LxtLogError(
1339 "Error condition on reader poll: 0x%X, Expected: "
1340 "0x%X! (POLLIN)",
1341 PollFd.revents,
1342 POLLIN);
1343
1344 Result = EINVAL;
1345 goto ErrorExit;
1346 }
1347
1348 //
1349 // Read data from the other end of the pipe.
1350 //
1351
1352 LxtLogInfo("Reading the data from the reader end.") ExpectedResult = strlen(Message);
1353 LxtCheckErrno((BytesRead = read(Pipes[0], ReadBuffer, sizeof(ReadBuffer))));
1354 LxtCheckEqual(ExpectedResult, BytesRead, "%d");
1355
1356 //
1357 // Validate that the EPOLLIN is not set on the reader end now that the data
1358 // has been read. This call will block, so specify a timeout value.
1359 //
1360
1361 LxtLogInfo(
1362 "Validating that the EPOLLIN is *not* set on the reader end of "
1363 "the pipe.");
1364
1365 PollFd.revents = 0;
1366 PollFd.fd = Pipes[0];
1367 PollFd.events = POLLIN | POLLOUT;
1368 LxtCheckErrno(poll(&PollFd, 1, 1));
1369 if (PollFd.revents != 0)
1370 {
1371 LxtLogError("Error condition on reader poll: 0x%X, Expected: 0x%X!", PollFd.revents, 0);
1372
1373 Result = EINVAL;
1374 goto ErrorExit;
1375 }
1376
1377 //
1378 // Hangup the reader end.
1379 //
1380
1381 LxtLogInfo("Hanging the reader");
1382 close(Pipes[0]);
1383 Pipes[0] = -1;
1384
1385 //
1386 // Validate that when the reader hangs up, both EPOLLOUT and EPOLLERR are
1387 // set.
1388 //
1389
1390 LxtLogInfo(
1391 "Validating that the correct EPOLL flags are set on the writer "
1392 "end of the pipe.");
1393
1394 PollFd.revents = 0;
1395 PollFd.fd = Pipes[1];
1396 PollFd.events = POLLIN | POLLOUT;
1397 LxtCheckErrno(poll(&PollFd, 1, -1));
1398 if (PollFd.revents != (POLLOUT | POLLERR))
1399 {
1400 LxtLogError(
1401 "Error condition on writer poll: 0x%X, Expected: "
1402 "0x%X! (POLLHUP)",
1403 PollFd.revents,
1404 (POLLOUT | POLLERR));
1405
1406 Result = EINVAL;
1407 goto ErrorExit;
1408 }
1409
1410 Result = 0;
1411
1412 ErrorExit:
1413 if (Pipes[0] != -1)
1414 {
1415 close(Pipes[0]);
1416 }
1417
1418 if (Pipes[1] != -1)
1419 {
1420 close(Pipes[1]);
1421 }
1422
1423 return Result;
1424 }
1425
1426 int PipeWriterHangup(PLXT_ARGS Args)
1427
1428 /*++
1429
1430 Routine Description:
1431
1432 This routine validates the writer hangup epoll semantics.
1433
1434 Arguments:
1435
1436 Args - Supplies the command line arguments.
1437
1438 Return Value:
1439
1440 Returns 0 on success, -1 on failure.
1441
1442 --*/
1443
1444 {
1445
1446 ssize_t BytesRead;
1447 ssize_t BytesWritten;
1448 ssize_t ExpectedResult;
1449 char* Message = "This is a test string for piping";
1450 int Pipes[2] = {-1, -1};
1451 struct pollfd PollFd;
1452 char ReadBuffer[100] = {0};
1453 int Result;
1454
1455 //
1456 // Create a pipe.
1457 //
1458
1459 LxtCheckErrno(pipe(Pipes));
1460
1461 //
1462 // Set the pipe FD's to non-blocking.
1463 //
1464
1465 LxtLogInfo("Creating a pipe...");
1466 LxtCheckErrno(fcntl(Pipes[0], F_SETFL, O_NONBLOCK));
1467 LxtCheckErrno(fcntl(Pipes[1], F_SETFL, O_NONBLOCK));
1468
1469 //
1470 // Write some data to the pipe.
1471 //
1472
1473 LxtLogInfo("Writing some data to the pipe.");
1474 ExpectedResult = strlen(Message);
1475 LxtCheckErrno((BytesWritten = write(Pipes[1], Message, ExpectedResult)));
1476 LxtCheckEqual(ExpectedResult, BytesWritten, "%d");
1477
1478 //
1479 // Hangup the writer end.
1480 //
1481
1482 LxtLogInfo("Hanging the writer");
1483 close(Pipes[1]);
1484 Pipes[1] = -1;
1485
1486 //
1487 // Validate that both EPOLLIN and EPOLLHUP is set on the reader side.
1488 //
1489
1490 LxtLogInfo(
1491 "Validating that the correct EPOLL flags are set on the reader "
1492 "end of the pipe.");
1493
1494 PollFd.revents = 0;
1495 PollFd.fd = Pipes[0];
1496 PollFd.events = POLLIN | POLLOUT;
1497 LxtCheckErrno(poll(&PollFd, 1, -1));
1498 if (PollFd.revents != (POLLHUP | POLLIN))
1499 {
1500 LxtLogError(
1501 "Error condition on reader poll: 0x%X. Expected: "
1502 "0x%X (POLLHUP | POLLIN)",
1503 PollFd.revents,
1504 (POLLHUP | POLLIN));
1505
1506 Result = EINVAL;
1507 goto ErrorExit;
1508 }
1509
1510 //
1511 // Drain the read side of the pipe.
1512 //
1513
1514 LxtLogInfo("Reading all the data from the pipe.") ExpectedResult = strlen(Message);
1515 LxtCheckErrno((BytesRead = read(Pipes[0], ReadBuffer, sizeof(ReadBuffer))));
1516 LxtCheckEqual(ExpectedResult, BytesRead, "%d");
1517
1518 LxtLogInfo(
1519 "Validating that only EPOLLHUP is set on the reader side now "
1520 "that the pipe has been drained.");
1521
1522 PollFd.revents = 0;
1523 PollFd.fd = Pipes[0];
1524 PollFd.events = POLLIN | POLLOUT;
1525 LxtCheckErrno(poll(&PollFd, 1, -1));
1526 if (PollFd.revents != POLLHUP)
1527 {
1528 LxtLogError(
1529 "Error condition on reader poll: 0x%X. Expected: "
1530 "0x%X (POLLHUP)",
1531 PollFd.revents,
1532 POLLHUP);
1533
1534 Result = EINVAL;
1535 goto ErrorExit;
1536 }
1537
1538 Result = 0;
1539
1540 ErrorExit:
1541 if (Pipes[0] != -1)
1542 {
1543 close(Pipes[0]);
1544 }
1545
1546 if (Pipes[1] != -1)
1547 {
1548 close(Pipes[1]);
1549 }
1550
1551 return Result;
1552 }
1553
1554 int PipeVariationIoctl(PLXT_ARGS Args)
1555
1556 /*++
1557
1558 Routine Description:
1559
1560 This routine validates the pipe ioctls.
1561
1562 Arguments:
1563
1564 Args - Supplies the command line arguments.
1565
1566 Return Value:
1567
1568 Returns 0 on success, -1 on failure.
1569
1570 --*/
1571
1572 {
1573
1574 int Pipes[2] = {-1, -1};
1575 char Buffer[256] = {0};
1576 int Result;
1577
1578 //
1579 // Create a pipe and check the ioctls
1580 //
1581
1582 LxtCheckErrno(pipe(Pipes));
1583 LxtCheckErrnoFailure(ioctl(Pipes[0], TCGETS, Buffer), ENOTTY);
1584
1585 ErrorExit:
1586 if (Pipes[0] != -1)
1587 {
1588 close(Pipes[0]);
1589 }
1590
1591 if (Pipes[1] != -1)
1592 {
1593 close(Pipes[1]);
1594 }
1595
1596 return Result;
1597 }
1598
1599 int PipeFileLocking(PLXT_ARGS Args)
1600
1601 /*++
1602
1603 Routine Description:
1604
1605 This routine validates the pipe support for file locking.
1606
1607 Arguments:
1608
1609 Args - Supplies the command line arguments.
1610
1611 Return Value:
1612
1613 Returns 0 on success, -1 on failure.
1614
1615 --*/
1616
1617 {
1618
1619 int Pipes[2] = {-1, -1};
1620 int Result;
1621
1622 //
1623 // Create a pipe and check the flock and lockf (fnctl+F_*LK).
1624 //
1625
1626 LxtCheckErrno(pipe(Pipes));
1627 LxtCheckErrno(flock(Pipes[0], LOCK_SH));
1628 LxtCheckErrno(flock(Pipes[1], LOCK_SH));
1629 LxtCheckErrno(flock(Pipes[0], LOCK_UN));
1630 LxtCheckErrno(flock(Pipes[1], LOCK_UN));
1631 LxtCheckErrno(flock(Pipes[0], LOCK_EX));
1632 LxtCheckErrno(flock(Pipes[0], LOCK_UN));
1633 LxtCheckErrno(flock(Pipes[1], LOCK_EX));
1634 LxtCheckErrno(flock(Pipes[1], LOCK_UN));
1635 LxtCheckErrno(lockf(Pipes[0], F_TEST, 0));
1636 LxtCheckErrno(lockf(Pipes[1], F_TEST, 0));
1637 LxtCheckErrno(lockf(Pipes[1], F_LOCK, 0));
1638 LxtCheckErrno(lockf(Pipes[1], F_ULOCK, 0));
1639
1640 ErrorExit:
1641 if (Pipes[0] != -1)
1642 {
1643 close(Pipes[0]);
1644 }
1645
1646 if (Pipes[1] != -1)
1647 {
1648 close(Pipes[1]);
1649 }
1650
1651 return Result;
1652 }
1653
1654 int PipeZeroByteRead(PLXT_ARGS Args)
1655
1656 /*++
1657
1658 Description:
1659
1660 This routine tests zero byte read on pipes.
1661
1662 Arguments:
1663
1664 Args - Supplies the command line arguments.
1665
1666 Return Value:
1667
1668 Returns 0 on success, -1 on failure.
1669
1670 --*/
1671
1672 {
1673
1674 char Buffer;
1675 int Pipes[2];
1676 int Result;
1677
1678 Pipes[0] = -1;
1679 Pipes[1] = -1;
1680 LxtCheckErrnoZeroSuccess(pipe(Pipes));
1681 LxtCheckErrno(read(Pipes[0], &Buffer, 0));
1682
1683 ErrorExit:
1684 if (Pipes[0] >= 0)
1685 {
1686 close(Pipes[0]);
1687 }
1688
1689 if (Pipes[1] >= 0)
1690 {
1691 close(Pipes[1]);
1692 }
1693
1694 return Result;
1695 }
1696
1697 int PipeSecurityHelper(int Pipe, int Uid, int Gid)
1698
1699 /*++
1700
1701 Description:
1702
1703 This routine tests security attributes on pipes.
1704
1705 Arguments:
1706
1707 Args - Supplies the command line arguments.
1708
1709 Return Value:
1710
1711 Returns 0 on success, -1 on failure.
1712
1713 --*/
1714
1715 {
1716
1717 int Result;
1718 struct stat Stat;
1719
1720 //
1721 // Check the original values.
1722 //
1723
1724 LxtCheckErrnoZeroSuccess(fstat(Pipe, &Stat));
1725 LxtCheckEqual(Stat.st_uid, Uid, "%d");
1726 LxtCheckEqual(Stat.st_gid, Gid, "%d");
1727 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0600, "%d");
1728
1729 //
1730 // Check the values after chmod.
1731 //
1732
1733 LxtCheckErrnoZeroSuccess(fchmod(Pipe, 0777));
1734 LxtCheckErrnoZeroSuccess(fstat(Pipe, &Stat));
1735 LxtCheckEqual(Stat.st_uid, Uid, "%d");
1736 LxtCheckEqual(Stat.st_gid, Gid, "%d");
1737 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0777, "%d");
1738
1739 //
1740 // Check the values after chown to the current user\group.
1741 //
1742
1743 LxtCheckErrnoZeroSuccess(fchown(Pipe, Uid, Gid));
1744 LxtCheckErrnoZeroSuccess(fstat(Pipe, &Stat));
1745 LxtCheckEqual(Stat.st_uid, Uid, "%d");
1746 LxtCheckEqual(Stat.st_gid, Gid, "%d");
1747 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0777, "%d");
1748
1749 //
1750 // Update the user\group and check that it changes as root. As non-root
1751 // the user doesn't have permissions to make the updates.
1752 //
1753
1754 if (Uid == 0)
1755 {
1756 LxtCheckErrnoZeroSuccess(fchown(Pipe, Uid + 1, Gid));
1757 LxtCheckErrnoZeroSuccess(fstat(Pipe, &Stat));
1758 LxtCheckEqual(Stat.st_uid, Uid + 1, "%d");
1759 LxtCheckEqual(Stat.st_gid, Gid, "%d");
1760 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0777, "%d");
1761
1762 LxtCheckErrnoZeroSuccess(fchown(Pipe, Uid, Gid + 1));
1763 LxtCheckErrnoZeroSuccess(fstat(Pipe, &Stat));
1764 LxtCheckEqual(Stat.st_uid, Uid, "%d");
1765 LxtCheckEqual(Stat.st_gid, Gid + 1, "%d");
1766 LxtCheckEqual(Stat.st_mode, S_IFIFO | 0777, "%d");
1767 }
1768 else
1769 {
1770 LxtCheckErrnoFailure(fchown(Pipe, Uid + 1, Gid), EPERM);
1771 LxtCheckErrnoFailure(fchown(Pipe, Uid, Gid + 1), EPERM);
1772 }
1773
1774 //
1775 // Check user\group updates with -1.
1776 //
1777
1778 LxtCheckErrnoZeroSuccess(fchown(Pipe, Uid, -1));
1779 LxtCheckErrnoZeroSuccess(fchown(Pipe, -1, Gid));
1780 LxtCheckErrnoZeroSuccess(fchown(Pipe, -1, -1));
1781
1782 ErrorExit:
1783 return Result;
1784 }
1785
1786 int PipeSecurity(PLXT_ARGS Args)
1787
1788 /*++
1789
1790 Description:
1791
1792 This routine tests security attributes on pipes.
1793
1794 Arguments:
1795
1796 Args - Supplies the command line arguments.
1797
1798 Return Value:
1799
1800 Returns 0 on success, -1 on failure.
1801
1802 --*/
1803
1804 {
1805
1806 int ChildPid;
1807 int Pipes[2];
1808 int Result;
1809 struct stat Stat;
1810
1811 Pipes[0] = -1;
1812 Pipes[1] = -1;
1813 LxtCheckErrno(ChildPid = fork());
1814 if (ChildPid == 0)
1815 {
1816
1817 //
1818 // Check the security as root.
1819 //
1820
1821 LxtCheckErrnoZeroSuccess(pipe(Pipes));
1822 LxtCheckResult(PipeSecurityHelper(Pipes[0], 0, 0));
1823 LxtClose(Pipes[0]);
1824 Pipes[0] = -1;
1825 LxtClose(Pipes[1]);
1826 Pipes[1] = -1;
1827
1828 //
1829 // Check the security as a different user\group which drops
1830 // capabilities.
1831 //
1832
1833 LxtCheckErrno(setfsuid(1000));
1834 LxtCheckErrno(setfsgid(1001));
1835 LxtCheckErrnoZeroSuccess(pipe(Pipes));
1836 LxtCheckResult(PipeSecurityHelper(Pipes[0], 1000, 1001));
1837
1838 _exit(0);
1839 }
1840
1841 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
1842
1843 ErrorExit:
1844 if (Pipes[0] >= 0)
1845 {
1846 close(Pipes[0]);
1847 }
1848
1849 if (Pipes[1] >= 0)
1850 {
1851 close(Pipes[1]);
1852 }
1853
1854 if (ChildPid == 0)
1855 {
1856 _exit(Result);
1857 }
1858
1859 return Result;
1860 }
1861
1862 int PipeFcntlRoundUpToPower2(int Value)
1863 {
1864
1865 if (Value < 0)
1866 {
1867 Value = 0;
1868 }
1869 else
1870 {
1871 --Value;
1872 Value |= Value >> 1;
1873 Value |= Value >> 2;
1874 Value |= Value >> 4;
1875 Value |= Value >> 8;
1876 Value |= Value >> 16;
1877 Value += 1;
1878 }
1879
1880 return Value;
1881 }
1882
1883 int PipeFcntl(PLXT_ARGS Args)
1884
1885 /*++
1886
1887 Description:
1888
1889 This routine tests the pipe fcntl commands.
1890
1891 Arguments:
1892
1893 Args - Supplies the command line arguments.
1894
1895 Return Value:
1896
1897 Returns 0 on success, -1 on failure.
1898
1899 --*/
1900
1901 {
1902
1903 char Buffer[_4KB + 1];
1904 struct __user_cap_data_struct CapData[2];
1905 struct __user_cap_header_struct CapHeader;
1906 int ChildPid;
1907 int EventFd;
1908 int Index;
1909 int Pipes[2];
1910 int Result;
1911 int Size;
1912 int SizeSet;
1913 int SizesToSet[] = {
1914 0,
1915 1,
1916 _4KB - 1,
1917 _4KB,
1918 _64KB - 1,
1919 _64KB,
1920 _64KB + 1,
1921 _64KB * 2,
1922 _64KB * 2 + 1,
1923 _64KB * 4 - 1,
1924 _64KB * 4,
1925 _64KB * 4 + 1,
1926 PIPE_DEFAULT_MAX_SIZE - 1,
1927 PIPE_DEFAULT_MAX_SIZE,
1928 PIPE_DEFAULT_MAX_SIZE + 1,
1929 _64KB};
1930
1931 ChildPid = -1;
1932 EventFd = -1;
1933 Pipes[0] = -1;
1934 Pipes[1] = -1;
1935 LxtCheckErrnoZeroSuccess(pipe(Pipes));
1936 LxtCheckErrno(EventFd = eventfd(0, 0));
1937
1938 //
1939 // Check the initial values for F_GETPIPE_SZ.
1940 //
1941
1942 LxtCheckErrno(Size = fcntl(Pipes[0], F_GETPIPE_SZ));
1943 LxtCheckEqual(Size, _64KB, "%d");
1944 LxtCheckErrno(Size = fcntl(Pipes[1], F_GETPIPE_SZ));
1945 LxtCheckEqual(Size, _64KB, "%d");
1946
1947 //
1948 // Update the size and check for the expected values.
1949 //
1950 // From the man pages, "In the current implementation, the allocation is the
1951 // next higher power-of-two page-size multiple of the requested size"
1952 //
1953
1954 srand(time(NULL));
1955 for (Index = 0; Index < LXT_COUNT_OF(SizesToSet); ++Index)
1956 {
1957
1958 LxtCheckErrno(SizeSet = fcntl(Pipes[rand() % 2], F_SETPIPE_SZ, SizesToSet[Index]));
1959 LxtLogInfo("Setting %d -> %d", SizesToSet[Index], SizeSet);
1960
1961 Size = SizesToSet[Index];
1962 if (Size < PAGE_SIZE)
1963 {
1964 Size = PAGE_SIZE;
1965 }
1966 else
1967 {
1968 Size = PipeFcntlRoundUpToPower2(Size);
1969 }
1970
1971 LxtCheckEqual(SizeSet, Size, "%d");
1972 LxtCheckErrno(Size = fcntl(Pipes[0], F_GETPIPE_SZ));
1973 LxtCheckEqual(Size, SizeSet, "%d");
1974 LxtCheckErrno(Size = fcntl(Pipes[1], F_GETPIPE_SZ));
1975 LxtCheckEqual(Size, SizeSet, "%d");
1976 }
1977
1978 //
1979 // Try to shrink the data below the maximum amount.
1980 //
1981
1982 LxtCheckErrno(write(Pipes[1], Buffer, sizeof(Buffer)));
1983 LxtCheckErrnoFailure(fcntl(Pipes[1], F_SETPIPE_SZ, sizeof(Buffer) - 1), EBUSY);
1984
1985 //
1986 // Try to increase the buffer from an unprivileged thread.
1987 //
1988
1989 LxtCheckErrno(ChildPid = fork());
1990 if (ChildPid == 0)
1991 {
1992
1993 //
1994 // Drop the CAP_SYS_RESOURCE capability.
1995 //
1996
1997 memset(&CapHeader, 0, sizeof(CapHeader));
1998 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1999 LxtCheckErrno(LxtCapGet(&CapHeader, CapData)) LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
2000 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted &= ~CAP_TO_MASK(CAP_SYS_RESOURCE);
2001 CapData[0].effective = CapData[0].permitted;
2002 CapData[1].effective = CapData[1].permitted;
2003 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2004 LxtCheckErrnoFailure(fcntl(Pipes[1], F_SETPIPE_SZ, PIPE_DEFAULT_MAX_SIZE + 1), EPERM);
2005 _exit(0);
2006 }
2007
2008 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
2009
2010 //
2011 // Check the maximum value permissions check.
2012 //
2013
2014 //
2015 // Negative variations.
2016 //
2017
2018 LxtCheckErrnoFailure(fcntl(Pipes[1], F_SETPIPE_SZ, -1), EINVAL);
2019 LxtCheckErrnoFailure(Size = fcntl(EventFd, F_GETPIPE_SZ), EBADF);
2020 LxtCheckErrnoFailure(Size = fcntl(EventFd, F_SETPIPE_SZ, _64KB), EBADF);
2021
2022 ErrorExit:
2023 if (ChildPid == 0)
2024 {
2025 _exit(Result);
2026 }
2027
2028 LxtClose(EventFd);
2029 LxtClose(Pipes[0]);
2030 LxtClose(Pipes[1]);
2031
2032 return Result;
2033 }