1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 */ 5 6 #include <unistd.h> 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <poll.h> 10 #include <pty.h> 11 #include <sched.h> 12 #include <signal.h> 13 #include <string.h> 14 #include <kern_util.h> 15 #include <init.h> 16 #include <os.h> 17 #include <sigio.h> 18 #include <um_malloc.h> 19 20 /* 21 * Protected by sigio_lock(), also used by sigio_cleanup, which is an 22 * exitcall. 23 */ 24 static int write_sigio_pid = -1; 25 static unsigned long write_sigio_stack; 26 27 /* 28 * These arrays are initialized before the sigio thread is started, and 29 * the descriptors closed after it is killed. So, it can't see them change. 30 * On the UML side, they are changed under the sigio_lock. 31 */ 32 #define SIGIO_FDS_INIT {-1, -1} 33 34 static int write_sigio_fds[2] = SIGIO_FDS_INIT; 35 static int sigio_private[2] = SIGIO_FDS_INIT; 36 37 struct pollfds { 38 struct pollfd *poll; 39 int size; 40 int used; 41 }; 42 43 /* 44 * Protected by sigio_lock(). Used by the sigio thread, but the UML thread 45 * synchronizes with it. 46 */ 47 static struct pollfds current_poll; 48 static struct pollfds next_poll; 49 static struct pollfds all_sigio_fds; 50 51 static int write_sigio_thread(void *unused) 52 { 53 struct pollfds *fds, tmp; 54 struct pollfd *p; 55 int i, n, respond_fd; 56 char c; 57 58 os_set_pdeathsig(); 59 os_fix_helper_signals(); 60 fds = ¤t_poll; 61 while (1) { 62 n = poll(fds->poll, fds->used, -1); 63 if (n < 0) { 64 if (errno == EINTR) 65 continue; 66 printk(UM_KERN_ERR "write_sigio_thread : poll returned " 67 "%d, errno = %d\n", n, errno); 68 } 69 for (i = 0; i < fds->used; i++) { 70 p = &fds->poll[i]; 71 if (p->revents == 0) 72 continue; 73 if (p->fd == sigio_private[1]) { 74 CATCH_EINTR(n = read(sigio_private[1], &c, 75 sizeof(c))); 76 if (n != sizeof(c)) 77 printk(UM_KERN_ERR 78 "write_sigio_thread : " 79 "read on socket failed, " 80 "err = %d\n", errno); 81 tmp = current_poll; 82 current_poll = next_poll; 83 next_poll = tmp; 84 respond_fd = sigio_private[1]; 85 } 86 else { 87 respond_fd = write_sigio_fds[1]; 88 fds->used--; 89 memmove(&fds->poll[i], &fds->poll[i + 1], 90 (fds->used - i) * sizeof(*fds->poll)); 91 } 92 93 CATCH_EINTR(n = write(respond_fd, &c, sizeof(c))); 94 if (n != sizeof(c)) 95 printk(UM_KERN_ERR "write_sigio_thread : " 96 "write on socket failed, err = %d\n", 97 errno); 98 } 99 } 100 101 return 0; 102 } 103 104 static int need_poll(struct pollfds *polls, int n) 105 { 106 struct pollfd *new; 107 108 if (n <= polls->size) 109 return 0; 110 111 new = uml_kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); 112 if (new == NULL) { 113 printk(UM_KERN_ERR "need_poll : failed to allocate new " 114 "pollfds\n"); 115 return -ENOMEM; 116 } 117 118 memcpy(new, polls->poll, polls->used * sizeof(struct pollfd)); 119 kfree(polls->poll); 120 121 polls->poll = new; 122 polls->size = n; 123 return 0; 124 } 125 126 /* 127 * Must be called with sigio_lock held, because it's needed by the marked 128 * critical section. 129 */ 130 static void update_thread(void) 131 { 132 unsigned long flags; 133 int n; 134 char c; 135 136 flags = um_set_signals_trace(0); 137 CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c))); 138 if (n != sizeof(c)) { 139 printk(UM_KERN_ERR "update_thread : write failed, err = %d\n", 140 errno); 141 goto fail; 142 } 143 144 CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c))); 145 if (n != sizeof(c)) { 146 printk(UM_KERN_ERR "update_thread : read failed, err = %d\n", 147 errno); 148 goto fail; 149 } 150 151 um_set_signals_trace(flags); 152 return; 153 fail: 154 /* Critical section start */ 155 if (write_sigio_pid != -1) { 156 os_kill_process(write_sigio_pid, 1); 157 free_stack(write_sigio_stack, 0); 158 } 159 write_sigio_pid = -1; 160 close(sigio_private[0]); 161 close(sigio_private[1]); 162 close(write_sigio_fds[0]); 163 close(write_sigio_fds[1]); 164 /* Critical section end */ 165 um_set_signals_trace(flags); 166 } 167 168 int __add_sigio_fd(int fd) 169 { 170 struct pollfd *p; 171 int err, i, n; 172 173 for (i = 0; i < all_sigio_fds.used; i++) { 174 if (all_sigio_fds.poll[i].fd == fd) 175 break; 176 } 177 if (i == all_sigio_fds.used) 178 return -ENOSPC; 179 180 p = &all_sigio_fds.poll[i]; 181 182 for (i = 0; i < current_poll.used; i++) { 183 if (current_poll.poll[i].fd == fd) 184 return 0; 185 } 186 187 n = current_poll.used; 188 err = need_poll(&next_poll, n + 1); 189 if (err) 190 return err; 191 192 memcpy(next_poll.poll, current_poll.poll, 193 current_poll.used * sizeof(struct pollfd)); 194 next_poll.poll[n] = *p; 195 next_poll.used = n + 1; 196 update_thread(); 197 198 return 0; 199 } 200 201 202 int add_sigio_fd(int fd) 203 { 204 int err; 205 206 sigio_lock(); 207 err = __add_sigio_fd(fd); 208 sigio_unlock(); 209 210 return err; 211 } 212 213 int __ignore_sigio_fd(int fd) 214 { 215 struct pollfd *p; 216 int err, i, n = 0; 217 218 /* 219 * This is called from exitcalls elsewhere in UML - if 220 * sigio_cleanup has already run, then update_thread will hang 221 * or fail because the thread is no longer running. 222 */ 223 if (write_sigio_pid == -1) 224 return -EIO; 225 226 for (i = 0; i < current_poll.used; i++) { 227 if (current_poll.poll[i].fd == fd) 228 break; 229 } 230 if (i == current_poll.used) 231 return -ENOENT; 232 233 err = need_poll(&next_poll, current_poll.used - 1); 234 if (err) 235 return err; 236 237 for (i = 0; i < current_poll.used; i++) { 238 p = ¤t_poll.poll[i]; 239 if (p->fd != fd) 240 next_poll.poll[n++] = *p; 241 } 242 next_poll.used = current_poll.used - 1; 243 244 update_thread(); 245 246 return 0; 247 } 248 249 int ignore_sigio_fd(int fd) 250 { 251 int err; 252 253 sigio_lock(); 254 err = __ignore_sigio_fd(fd); 255 sigio_unlock(); 256 257 return err; 258 } 259 260 static struct pollfd *setup_initial_poll(int fd) 261 { 262 struct pollfd *p; 263 264 p = uml_kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); 265 if (p == NULL) { 266 printk(UM_KERN_ERR "setup_initial_poll : failed to allocate " 267 "poll\n"); 268 return NULL; 269 } 270 *p = ((struct pollfd) { .fd = fd, 271 .events = POLLIN, 272 .revents = 0 }); 273 return p; 274 } 275 276 static void write_sigio_workaround(void) 277 { 278 struct pollfd *p; 279 int err; 280 int l_write_sigio_fds[2]; 281 int l_sigio_private[2]; 282 int l_write_sigio_pid; 283 284 /* We call this *tons* of times - and most ones we must just fail. */ 285 sigio_lock(); 286 l_write_sigio_pid = write_sigio_pid; 287 sigio_unlock(); 288 289 if (l_write_sigio_pid != -1) 290 return; 291 292 err = os_pipe(l_write_sigio_fds, 1, 1); 293 if (err < 0) { 294 printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, " 295 "err = %d\n", -err); 296 return; 297 } 298 err = os_pipe(l_sigio_private, 1, 1); 299 if (err < 0) { 300 printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, " 301 "err = %d\n", -err); 302 goto out_close1; 303 } 304 305 p = setup_initial_poll(l_sigio_private[1]); 306 if (!p) 307 goto out_close2; 308 309 sigio_lock(); 310 311 /* 312 * Did we race? Don't try to optimize this, please, it's not so likely 313 * to happen, and no more than once at the boot. 314 */ 315 if (write_sigio_pid != -1) 316 goto out_free; 317 318 current_poll = ((struct pollfds) { .poll = p, 319 .used = 1, 320 .size = 1 }); 321 322 if (write_sigio_irq(l_write_sigio_fds[0])) 323 goto out_clear_poll; 324 325 memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); 326 memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); 327 328 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 329 CLONE_FILES | CLONE_VM, 330 &write_sigio_stack); 331 332 if (write_sigio_pid < 0) 333 goto out_clear; 334 335 sigio_unlock(); 336 return; 337 338 out_clear: 339 write_sigio_pid = -1; 340 write_sigio_fds[0] = -1; 341 write_sigio_fds[1] = -1; 342 sigio_private[0] = -1; 343 sigio_private[1] = -1; 344 out_clear_poll: 345 current_poll = ((struct pollfds) { .poll = NULL, 346 .size = 0, 347 .used = 0 }); 348 out_free: 349 sigio_unlock(); 350 kfree(p); 351 out_close2: 352 close(l_sigio_private[0]); 353 close(l_sigio_private[1]); 354 out_close1: 355 close(l_write_sigio_fds[0]); 356 close(l_write_sigio_fds[1]); 357 } 358 359 void sigio_broken(int fd) 360 { 361 int err; 362 363 write_sigio_workaround(); 364 365 sigio_lock(); 366 err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1); 367 if (err) { 368 printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd " 369 "for descriptor %d\n", fd); 370 goto out; 371 } 372 373 all_sigio_fds.poll[all_sigio_fds.used++] = 374 ((struct pollfd) { .fd = fd, 375 .events = POLLIN, 376 .revents = 0 }); 377 out: 378 sigio_unlock(); 379 } 380 381 /* Changed during early boot */ 382 static int pty_output_sigio; 383 384 void maybe_sigio_broken(int fd) 385 { 386 if (!isatty(fd)) 387 return; 388 389 if (pty_output_sigio) 390 return; 391 392 sigio_broken(fd); 393 } 394 395 static void sigio_cleanup(void) 396 { 397 if (write_sigio_pid == -1) 398 return; 399 400 os_kill_process(write_sigio_pid, 1); 401 free_stack(write_sigio_stack, 0); 402 write_sigio_pid = -1; 403 } 404 405 __uml_exitcall(sigio_cleanup); 406 407 /* Used as a flag during SIGIO testing early in boot */ 408 static int got_sigio; 409 410 static void __init handler(int sig) 411 { 412 got_sigio = 1; 413 } 414 415 struct openpty_arg { 416 int master; 417 int slave; 418 int err; 419 }; 420 421 static void openpty_cb(void *arg) 422 { 423 struct openpty_arg *info = arg; 424 425 info->err = 0; 426 if (openpty(&info->master, &info->slave, NULL, NULL, NULL)) 427 info->err = -errno; 428 } 429 430 static int async_pty(int master, int slave) 431 { 432 int flags; 433 434 flags = fcntl(master, F_GETFL); 435 if (flags < 0) 436 return -errno; 437 438 if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || 439 (fcntl(master, F_SETOWN, os_getpid()) < 0)) 440 return -errno; 441 442 if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) 443 return -errno; 444 445 return 0; 446 } 447 448 static void __init check_one_sigio(void (*proc)(int, int)) 449 { 450 struct sigaction old, new; 451 struct openpty_arg pty = { .master = -1, .slave = -1 }; 452 int master, slave, err; 453 454 initial_thread_cb(openpty_cb, &pty); 455 if (pty.err) { 456 printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n", 457 -pty.err); 458 return; 459 } 460 461 master = pty.master; 462 slave = pty.slave; 463 464 if ((master == -1) || (slave == -1)) { 465 printk(UM_KERN_ERR "check_one_sigio failed to allocate a " 466 "pty\n"); 467 return; 468 } 469 470 /* Not now, but complain so we now where we failed. */ 471 err = raw(master); 472 if (err < 0) { 473 printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n", 474 -err); 475 return; 476 } 477 478 err = async_pty(master, slave); 479 if (err < 0) { 480 printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, " 481 "err = %d\n", -err); 482 return; 483 } 484 485 if (sigaction(SIGIO, NULL, &old) < 0) { 486 printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, " 487 "errno = %d\n", errno); 488 return; 489 } 490 491 new = old; 492 new.sa_handler = handler; 493 if (sigaction(SIGIO, &new, NULL) < 0) { 494 printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, " 495 "errno = %d\n", errno); 496 return; 497 } 498 499 got_sigio = 0; 500 (*proc)(master, slave); 501 502 close(master); 503 close(slave); 504 505 if (sigaction(SIGIO, &old, NULL) < 0) 506 printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, " 507 "errno = %d\n", errno); 508 } 509 510 static void tty_output(int master, int slave) 511 { 512 int n; 513 char buf[512]; 514 515 printk(UM_KERN_INFO "Checking that host ptys support output SIGIO..."); 516 517 memset(buf, 0, sizeof(buf)); 518 519 while (write(master, buf, sizeof(buf)) > 0) ; 520 if (errno != EAGAIN) 521 printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n", 522 errno); 523 while (((n = read(slave, buf, sizeof(buf))) > 0) && 524 !({ barrier(); got_sigio; })) 525 ; 526 527 if (got_sigio) { 528 printk(UM_KERN_CONT "Yes\n"); 529 pty_output_sigio = 1; 530 } else if (n == -EAGAIN) 531 printk(UM_KERN_CONT "No, enabling workaround\n"); 532 else 533 printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n); 534 } 535 536 static void __init check_sigio(void) 537 { 538 if ((access("/dev/ptmx", R_OK) < 0) && 539 (access("/dev/ptyp0", R_OK) < 0)) { 540 printk(UM_KERN_WARNING "No pseudo-terminals available - " 541 "skipping pty SIGIO check\n"); 542 return; 543 } 544 check_one_sigio(tty_output); 545 } 546 547 /* Here because it only does the SIGIO testing for now */ 548 void __init os_check_bugs(void) 549 { 550 check_sigio(); 551 } 552