Last active
December 10, 2015 03:48
-
-
Save mshroyer/4377173 to your computer and use it in GitHub Desktop.
This fails on OpenBSD 5.2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * ptycheck.c - Demonstrate possible problem in OpenBSD's ptcwrite | |
| * | |
| * Opens a pseudoterminal pair in "raw" mode, then forks off a child | |
| * process which attempts to write MESSAGE_LEN random bytes to the pty | |
| * master; meanwhile the parent process tries to read the same number of | |
| * bytes from the slave. Once the parent has received the expected number | |
| * of bytes, it compares the message received against the original to | |
| * ensure that all data shuffled across the pseudoterminal successfully. | |
| * | |
| * On OpenBSD 5.2 i386 and amd64, this fails with the parent process | |
| * blocking indefinitely after reading only 4088 bytes (out of 4096 | |
| * expected) from the pty slave. The same behavior is observed on 4.7 and | |
| * 4.8 i386, and can be seen when MESSAGE_LEN is 1024 or larger. | |
| * | |
| * Compile with `gcc -o ptycheck ptycheck.c -lutil`. | |
| * | |
| * Mark Shroyer | |
| * Tue Dec 25 20:04:48 EST 2012 | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <sys/types.h> | |
| #include <termios.h> | |
| #include <unistd.h> | |
| #include <util.h> | |
| /* Number of pseudorandom bytes to try sending */ | |
| #define MESSAGE_LEN 4096 | |
| int | |
| main(int argc, char *argv) | |
| { | |
| int fd, sfd, pid; | |
| char *send_buf, *recv_buf; | |
| ssize_t n; | |
| size_t i; | |
| struct termios t; | |
| if ((send_buf = malloc(MESSAGE_LEN)) == NULL) | |
| return 1; | |
| if ((recv_buf = malloc(MESSAGE_LEN)) == NULL) | |
| return 1; | |
| for (i = 0; i < MESSAGE_LEN; i++) | |
| send_buf[i] = random() % 256; | |
| if (openpty(&fd, &sfd, NULL, NULL, NULL) < 0) { | |
| perror("Failed to open PTY pair"); | |
| return 1; | |
| } | |
| if (tcgetattr(sfd, &t) < 0) | |
| return 1; | |
| cfmakeraw(&t); | |
| if (tcsetattr(sfd, TCSAFLUSH, &t) < 0) | |
| return 1; | |
| i = 0; | |
| switch (pid = fork()) { | |
| case -1: | |
| perror("Unable to fork child process"); | |
| return 1; | |
| case 0: | |
| /* Child process writes to pty master */ | |
| while (i < MESSAGE_LEN) { | |
| if ((n = write(fd, send_buf + i, MESSAGE_LEN - i)) < 0) { | |
| perror("Couldn't write to pty master"); | |
| return 1; | |
| } | |
| i += n; | |
| printf("-> master: %zd bytes\n", i); | |
| } | |
| printf("Done writing.\n"); | |
| return 0; | |
| default: | |
| /* Parent process reads from pty slave */ | |
| while (i < MESSAGE_LEN) { | |
| if ((n = read(sfd, recv_buf + i, MESSAGE_LEN - i)) < 0) { | |
| perror("Couldn't read from pty slave"); | |
| return 1; | |
| } | |
| i += n; | |
| printf("<- slave: %zd bytes\n", i); | |
| } | |
| printf("Done reading.\n"); | |
| if (memcmp(send_buf, recv_buf, MESSAGE_LEN) != 0) { | |
| printf("Message altered in transit!\n"); | |
| return 1; | |
| } | |
| printf("Message transferred successfully.\n"); | |
| waitpid(pid, NULL, 0); | |
| return 0; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment