DF-3533 / ttyprobe.c
/* ttyprobe.c -- DF-3533: v1 ng_tty failed-open path. * Pre-create a netgraph node named "ttyN" to force ng_name_node() failure * inside ngt_open(), then TIOCSETD netgraph on a pty slave: * - 1st TIOCSETD: expect error (name collision) -> error path runs * ng_rmnode -> ngt_shutdown frees sc while tp->t_sc still points at it * (latent dangling; no dispatch should occur -> no crash). * - 2nd TIOCSETD: name now free -> expect success (t_sc replaced). * - Final TIOCSETD back to ttydisc (0): cleanup. */ #include <sys/types.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <termios.h> #include <sys/ttycom.h> int main(int argc, char **argv) { int mfd, sfd, disc, old; char pts[128]; mfd = open("/dev/ptmx", O_RDWR); if (mfd < 0) { perror("ptmx"); return 1; } if (grantpt(mfd) < 0 || unlockpt(mfd) < 0) { perror("grant/unlock"); return 1; } { char *pp = ptsname(mfd); if (pp == NULL) { perror("ptsname"); return 1; } strlcpy(pts, pp, sizeof(pts)); } sfd = open(pts, O_RDWR | O_NOCTTY); if (sfd < 0) { perror(pts); return 1; } if (ioctl(sfd, TIOCGETD, &old) < 0) { perror("TIOCGETD"); return 1; } printf("slave %s initial line discipline: %d\n", pts, old); disc = NETGRAPHDISC; errno = 0; int rc = ioctl(sfd, TIOCSETD, &disc); printf("TIOCSETD NETGRAPHDISC #1 (colliding node exists): rc=%d errno=%d (%s)\n", rc, errno, rc ? strerror(errno) : "ok"); if (ioctl(sfd, TIOCGETD, &disc) == 0) printf("discipline now: %d (expected unchanged %d)\n", disc, old); /* second attempt: node name tty1 free -> should succeed */ errno = 0; rc = ioctl(sfd, TIOCSETD, &disc); printf("TIOCSETD NETGRAPHDISC #2: rc=%d errno=%d (%s)\n", rc, errno, rc ? strerror(errno) : "ok"); if (ioctl(sfd, TIOCGETD, &disc) == 0) printf("discipline now: %d\n", disc); /* write garbage through the tty while ng discipline active (no crash * expected; exercises ngt_input on the LIVE sc) */ if (disc == NETGRAPHDISC) { write(sfd, "hello-netgraph-tty\r\n", 20); printf("wrote 20 bytes through ng discipline: no crash\n"); } /* restore */ disc = old; rc = ioctl(sfd, TIOCSETD, &disc); printf("restore discipline %d: rc=%d\n", old, rc); printf("TTYPROBE-DONE guest alive\n"); return 0; } |