1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Provide access to virtual console memory. 4 * /dev/vcs: the screen as it is being viewed right now (possibly scrolled) 5 * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63) 6 * [minor: N] 7 * 8 * /dev/vcsaN: idem, but including attributes, and prefixed with 9 * the 4 bytes lines,columns,x,y (as screendump used to give). 10 * Attribute/character pair is in native endianity. 11 * [minor: N+128] 12 * 13 * /dev/vcsuN: similar to /dev/vcsaN but using 4-byte unicode values 14 * instead of 1-byte screen glyph values. 15 * [minor: N+64] 16 * 17 * /dev/vcsuaN: same idea as /dev/vcsaN for unicode (not yet implemented). 18 * 19 * This replaces screendump and part of selection, so that the system 20 * administrator can control access using file system permissions. 21 * 22 * aeb@cwi.nl - efter Friedas begravelse - 950211 23 * 24 * machek@k332.feld.cvut.cz - modified not to send characters to wrong console 25 * - fixed some fatal off-by-one bugs (0-- no longer == -1 -> looping and looping and looping...) 26 * - making it shorter - scr_readw are macros which expand in PRETTY long code 27 */ 28 29 #include <linux/kernel.h> 30 #include <linux/major.h> 31 #include <linux/errno.h> 32 #include <linux/export.h> 33 #include <linux/tty.h> 34 #include <linux/interrupt.h> 35 #include <linux/mm.h> 36 #include <linux/init.h> 37 #include <linux/vt_kern.h> 38 #include <linux/selection.h> 39 #include <linux/kbd_kern.h> 40 #include <linux/console.h> 41 #include <linux/device.h> 42 #include <linux/sched.h> 43 #include <linux/fs.h> 44 #include <linux/poll.h> 45 #include <linux/signal.h> 46 #include <linux/slab.h> 47 #include <linux/notifier.h> 48 49 #include <linux/uaccess.h> 50 #include <asm/byteorder.h> 51 #include <linux/unaligned.h> 52 53 #define HEADER_SIZE 4u 54 #define CON_BUF_SIZE (IS_ENABLED(CONFIG_BASE_SMALL) ? 256 : PAGE_SIZE) 55 56 DEFINE_FREE(free_page_ptr, void *, if (_T) free_page((unsigned long)_T)); 57 58 /* 59 * Our minor space: 60 * 61 * 0 ... 63 glyph mode without attributes 62 * 64 ... 127 unicode mode without attributes 63 * 128 ... 191 glyph mode with attributes 64 * 192 ... 255 unused (reserved for unicode with attributes) 65 * 66 * This relies on MAX_NR_CONSOLES being <= 63, meaning 63 actual consoles 67 * with minors 0, 64, 128 and 192 being proxies for the foreground console. 68 */ 69 #if MAX_NR_CONSOLES > 63 70 #warning "/dev/vcs* devices may not accommodate more than 63 consoles" 71 #endif 72 73 #define console(inode) (iminor(inode) & 63) 74 #define use_unicode(inode) (iminor(inode) & 64) 75 #define use_attributes(inode) (iminor(inode) & 128) 76 77 struct vcs_poll_data { 78 struct notifier_block notifier; 79 unsigned int cons_num; 80 int event; 81 wait_queue_head_t waitq; 82 struct fasync_struct *fasync; 83 }; 84 85 static int 86 vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param) 87 { 88 struct vt_notifier_param *param = _param; 89 struct vc_data *vc = param->vc; 90 struct vcs_poll_data *poll = 91 container_of(nb, struct vcs_poll_data, notifier); 92 int currcons = poll->cons_num; 93 int fa_band; 94 95 switch (code) { 96 case VT_UPDATE: 97 fa_band = POLL_PRI; 98 break; 99 case VT_DEALLOCATE: 100 fa_band = POLL_HUP; 101 break; 102 default: 103 return NOTIFY_DONE; 104 } 105 106 if (currcons == 0) 107 currcons = fg_console; 108 else 109 currcons--; 110 if (currcons != vc->vc_num) 111 return NOTIFY_DONE; 112 113 poll->event = code; 114 wake_up_interruptible(&poll->waitq); 115 kill_fasync(&poll->fasync, SIGIO, fa_band); 116 return NOTIFY_OK; 117 } 118 119 static void 120 vcs_poll_data_free(struct vcs_poll_data *poll) 121 { 122 unregister_vt_notifier(&poll->notifier); 123 kfree(poll); 124 } 125 126 static struct vcs_poll_data * 127 vcs_poll_data_get(struct file *file) 128 { 129 struct vcs_poll_data *poll = file->private_data, *kill = NULL; 130 131 if (poll) 132 return poll; 133 134 poll = kzalloc(sizeof(*poll), GFP_KERNEL); 135 if (!poll) 136 return NULL; 137 poll->cons_num = console(file_inode(file)); 138 init_waitqueue_head(&poll->waitq); 139 poll->notifier.notifier_call = vcs_notifier; 140 /* 141 * In order not to lose any update event, we must pretend one might 142 * have occurred before we have a chance to register our notifier. 143 * This is also how user space has come to detect which kernels 144 * support POLLPRI on /dev/vcs* devices i.e. using poll() with 145 * POLLPRI and a zero timeout. 146 */ 147 poll->event = VT_UPDATE; 148 149 if (register_vt_notifier(&poll->notifier) != 0) { 150 kfree(poll); 151 return NULL; 152 } 153 154 /* 155 * This code may be called either through ->poll() or ->fasync(). 156 * If we have two threads using the same file descriptor, they could 157 * both enter this function, both notice that the structure hasn't 158 * been allocated yet and go ahead allocating it in parallel, but 159 * only one of them must survive and be shared otherwise we'd leak 160 * memory with a dangling notifier callback. 161 */ 162 spin_lock(&file->f_lock); 163 if (!file->private_data) { 164 file->private_data = poll; 165 } else { 166 /* someone else raced ahead of us */ 167 kill = poll; 168 poll = file->private_data; 169 } 170 spin_unlock(&file->f_lock); 171 if (kill) 172 vcs_poll_data_free(kill); 173 174 return poll; 175 } 176 177 /** 178 * vcs_vc - return VC for @inode 179 * @inode: inode for which to return a VC 180 * @viewed: returns whether this console is currently foreground (viewed) 181 * 182 * Must be called with console_lock. 183 */ 184 static struct vc_data *vcs_vc(struct inode *inode, bool *viewed) 185 { 186 unsigned int currcons = console(inode); 187 188 WARN_CONSOLE_UNLOCKED(); 189 190 if (currcons == 0) { 191 currcons = fg_console; 192 if (viewed) 193 *viewed = true; 194 } else { 195 currcons--; 196 if (viewed) 197 *viewed = false; 198 } 199 return vc_cons[currcons].d; 200 } 201 202 /** 203 * vcs_size - return size for a VC in @vc 204 * @vc: which VC 205 * @attr: does it use attributes? 206 * @unicode: is it unicode? 207 * 208 * Must be called with console_lock. 209 */ 210 static int vcs_size(const struct vc_data *vc, bool attr, bool unicode) 211 { 212 int size; 213 214 WARN_CONSOLE_UNLOCKED(); 215 216 size = vc->vc_rows * vc->vc_cols; 217 218 if (attr) { 219 if (unicode) 220 return -EOPNOTSUPP; 221 222 size = 2 * size + HEADER_SIZE; 223 } else if (unicode) 224 size *= 4; 225 226 return size; 227 } 228 229 static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) 230 { 231 struct inode *inode = file_inode(file); 232 struct vc_data *vc; 233 int size; 234 235 scoped_guard(console_lock) { 236 vc = vcs_vc(inode, NULL); 237 if (!vc) 238 return -ENXIO; 239 240 size = vcs_size(vc, use_attributes(inode), use_unicode(inode)); 241 } 242 if (size < 0) 243 return size; 244 return fixed_size_llseek(file, offset, orig, size); 245 } 246 247 static int vcs_read_buf_uni(struct vc_data *vc, char *con_buf, 248 unsigned int pos, unsigned int count, bool viewed) 249 { 250 unsigned int nr, row, col, maxcol = vc->vc_cols; 251 int ret; 252 253 ret = vc_uniscr_check(vc); 254 if (ret) 255 return ret; 256 257 pos /= 4; 258 row = pos / maxcol; 259 col = pos % maxcol; 260 nr = maxcol - col; 261 do { 262 if (nr > count / 4) 263 nr = count / 4; 264 vc_uniscr_copy_line(vc, con_buf, viewed, row, col, nr); 265 con_buf += nr * 4; 266 count -= nr * 4; 267 row++; 268 col = 0; 269 nr = maxcol; 270 } while (count); 271 272 return 0; 273 } 274 275 static void vcs_read_buf_noattr(const struct vc_data *vc, char *con_buf, 276 unsigned int pos, unsigned int count, bool viewed) 277 { 278 u16 *org; 279 unsigned int col, maxcol = vc->vc_cols; 280 281 org = screen_pos(vc, pos, viewed); 282 col = pos % maxcol; 283 pos += maxcol - col; 284 285 while (count-- > 0) { 286 *con_buf++ = (vcs_scr_readw(vc, org++) & 0xff); 287 if (++col == maxcol) { 288 org = screen_pos(vc, pos, viewed); 289 col = 0; 290 pos += maxcol; 291 } 292 } 293 } 294 295 static unsigned int vcs_read_buf(const struct vc_data *vc, char *con_buf, 296 unsigned int pos, unsigned int count, bool viewed, 297 unsigned int *skip) 298 { 299 u16 *org, *con_buf16; 300 unsigned int col, maxcol = vc->vc_cols; 301 unsigned int filled = count; 302 303 if (pos < HEADER_SIZE) { 304 /* clamp header values if they don't fit */ 305 con_buf[0] = min(vc->vc_rows, 0xFFu); 306 con_buf[1] = min(vc->vc_cols, 0xFFu); 307 getconsxy(vc, con_buf + 2); 308 309 *skip += pos; 310 count += pos; 311 if (count > CON_BUF_SIZE) { 312 count = CON_BUF_SIZE; 313 filled = count - pos; 314 } 315 316 /* Advance state pointers and move on. */ 317 count -= min(HEADER_SIZE, count); 318 pos = HEADER_SIZE; 319 con_buf += HEADER_SIZE; 320 /* If count >= 0, then pos is even... */ 321 } else if (pos & 1) { 322 /* 323 * Skip first byte for output if start address is odd. Update 324 * region sizes up/down depending on free space in buffer. 325 */ 326 (*skip)++; 327 if (count < CON_BUF_SIZE) 328 count++; 329 else 330 filled--; 331 } 332 333 if (!count) 334 return filled; 335 336 pos -= HEADER_SIZE; 337 pos /= 2; 338 col = pos % maxcol; 339 340 org = screen_pos(vc, pos, viewed); 341 pos += maxcol - col; 342 343 /* 344 * Buffer has even length, so we can always copy character + attribute. 345 * We do not copy last byte to userspace if count is odd. 346 */ 347 count = (count + 1) / 2; 348 con_buf16 = (u16 *)con_buf; 349 350 while (count) { 351 *con_buf16++ = vcs_scr_readw(vc, org++); 352 count--; 353 if (++col == maxcol) { 354 org = screen_pos(vc, pos, viewed); 355 col = 0; 356 pos += maxcol; 357 } 358 } 359 360 return filled; 361 } 362 363 static ssize_t 364 vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 365 { 366 struct inode *inode = file_inode(file); 367 struct vc_data *vc; 368 struct vcs_poll_data *poll; 369 unsigned int read; 370 ssize_t ret; 371 loff_t pos; 372 bool viewed, attr, uni_mode; 373 374 char *con_buf __free(free_page_ptr) = (char *)__get_free_page(GFP_KERNEL); 375 if (!con_buf) 376 return -ENOMEM; 377 378 pos = *ppos; 379 380 /* Select the proper current console and verify 381 * sanity of the situation under the console lock. 382 */ 383 guard(console_lock)(); 384 385 uni_mode = use_unicode(inode); 386 attr = use_attributes(inode); 387 388 if (pos < 0) 389 return -EINVAL; 390 /* we enforce 32-bit alignment for pos and count in unicode mode */ 391 if (uni_mode && (pos | count) & 3) 392 return -EINVAL; 393 394 poll = file->private_data; 395 if (count && poll) 396 poll->event = 0; 397 read = 0; 398 ret = 0; 399 while (count) { 400 unsigned int this_round, skip = 0; 401 int size; 402 403 vc = vcs_vc(inode, &viewed); 404 if (!vc) { 405 ret = -ENXIO; 406 break; 407 } 408 409 /* Check whether we are above size each round, 410 * as copy_to_user at the end of this loop 411 * could sleep. 412 */ 413 size = vcs_size(vc, attr, uni_mode); 414 if (size < 0) { 415 ret = size; 416 break; 417 } 418 if (pos >= size) 419 break; 420 if (count > size - pos) 421 count = size - pos; 422 423 this_round = count; 424 if (this_round > CON_BUF_SIZE) 425 this_round = CON_BUF_SIZE; 426 427 /* Perform the whole read into the local con_buf. 428 * Then we can drop the console spinlock and safely 429 * attempt to move it to userspace. 430 */ 431 432 if (uni_mode) { 433 ret = vcs_read_buf_uni(vc, con_buf, pos, this_round, 434 viewed); 435 if (ret) 436 break; 437 } else if (!attr) { 438 vcs_read_buf_noattr(vc, con_buf, pos, this_round, 439 viewed); 440 } else { 441 this_round = vcs_read_buf(vc, con_buf, pos, this_round, 442 viewed, &skip); 443 } 444 445 /* Finally, release the console semaphore while we push 446 * all the data to userspace from our temporary buffer. 447 * 448 * AKPM: Even though it's a semaphore, we should drop it because 449 * the pagefault handling code may want to call printk(). 450 */ 451 452 console_unlock(); 453 ret = copy_to_user(buf, con_buf + skip, this_round); 454 console_lock(); 455 456 if (ret) { 457 read += this_round - ret; 458 ret = -EFAULT; 459 break; 460 } 461 buf += this_round; 462 pos += this_round; 463 read += this_round; 464 count -= this_round; 465 } 466 *ppos += read; 467 if (read) 468 return read; 469 470 return ret; 471 } 472 473 static u16 *vcs_write_buf_noattr(struct vc_data *vc, const char *con_buf, 474 unsigned int pos, unsigned int count, bool viewed, u16 **org0) 475 { 476 u16 *org; 477 unsigned int col, maxcol = vc->vc_cols; 478 479 *org0 = org = screen_pos(vc, pos, viewed); 480 col = pos % maxcol; 481 pos += maxcol - col; 482 483 while (count > 0) { 484 unsigned char c = *con_buf++; 485 486 count--; 487 vcs_scr_writew(vc, 488 (vcs_scr_readw(vc, org) & 0xff00) | c, org); 489 org++; 490 if (++col == maxcol) { 491 org = screen_pos(vc, pos, viewed); 492 col = 0; 493 pos += maxcol; 494 } 495 } 496 497 return org; 498 } 499 500 /* 501 * Compilers (gcc 10) are unable to optimize the swap in cpu_to_le16. So do it 502 * the poor man way. 503 */ 504 static inline u16 vc_compile_le16(u8 hi, u8 lo) 505 { 506 #ifdef __BIG_ENDIAN 507 return (lo << 8u) | hi; 508 #else 509 return (hi << 8u) | lo; 510 #endif 511 } 512 513 static u16 *vcs_write_buf(struct vc_data *vc, const char *con_buf, 514 unsigned int pos, unsigned int count, bool viewed, u16 **org0) 515 { 516 u16 *org; 517 unsigned int col, maxcol = vc->vc_cols; 518 unsigned char c; 519 520 /* header */ 521 if (pos < HEADER_SIZE) { 522 char header[HEADER_SIZE]; 523 524 getconsxy(vc, header + 2); 525 while (pos < HEADER_SIZE && count > 0) { 526 count--; 527 header[pos++] = *con_buf++; 528 } 529 if (!viewed) 530 putconsxy(vc, header + 2); 531 } 532 533 if (!count) 534 return NULL; 535 536 pos -= HEADER_SIZE; 537 col = (pos/2) % maxcol; 538 539 *org0 = org = screen_pos(vc, pos/2, viewed); 540 541 /* odd pos -- the first single character */ 542 if (pos & 1) { 543 count--; 544 c = *con_buf++; 545 vcs_scr_writew(vc, vc_compile_le16(c, vcs_scr_readw(vc, org)), 546 org); 547 org++; 548 pos++; 549 if (++col == maxcol) { 550 org = screen_pos(vc, pos/2, viewed); 551 col = 0; 552 } 553 } 554 555 pos /= 2; 556 pos += maxcol - col; 557 558 /* even pos -- handle attr+character pairs */ 559 while (count > 1) { 560 unsigned short w; 561 562 w = get_unaligned(((unsigned short *)con_buf)); 563 vcs_scr_writew(vc, w, org++); 564 con_buf += 2; 565 count -= 2; 566 if (++col == maxcol) { 567 org = screen_pos(vc, pos, viewed); 568 col = 0; 569 pos += maxcol; 570 } 571 } 572 573 if (!count) 574 return org; 575 576 /* odd pos -- the remaining character */ 577 c = *con_buf++; 578 vcs_scr_writew(vc, vc_compile_le16(vcs_scr_readw(vc, org) >> 8, c), 579 org); 580 581 return org; 582 } 583 584 static ssize_t 585 vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 586 { 587 struct inode *inode = file_inode(file); 588 struct vc_data *vc; 589 u16 *org0, *org; 590 unsigned int written; 591 int size; 592 ssize_t ret; 593 loff_t pos; 594 bool viewed, attr; 595 596 if (use_unicode(inode)) 597 return -EOPNOTSUPP; 598 599 char *con_buf __free(free_page_ptr) = (char *)__get_free_page(GFP_KERNEL); 600 if (!con_buf) 601 return -ENOMEM; 602 603 pos = *ppos; 604 605 /* Select the proper current console and verify 606 * sanity of the situation under the console lock. 607 */ 608 guard(console_lock)(); 609 610 attr = use_attributes(inode); 611 vc = vcs_vc(inode, &viewed); 612 if (!vc) 613 return -ENXIO; 614 615 size = vcs_size(vc, attr, false); 616 if (size < 0) 617 return size; 618 if (pos < 0 || pos > size) 619 return -EINVAL; 620 if (count > size - pos) 621 count = size - pos; 622 written = 0; 623 while (count) { 624 unsigned int this_round = count; 625 626 if (this_round > CON_BUF_SIZE) 627 this_round = CON_BUF_SIZE; 628 629 /* Temporarily drop the console lock so that we can read 630 * in the write data from userspace safely. 631 */ 632 console_unlock(); 633 ret = copy_from_user(con_buf, buf, this_round); 634 console_lock(); 635 636 if (ret) { 637 this_round -= ret; 638 if (!this_round) { 639 /* Abort loop if no data were copied. Otherwise 640 * fail with -EFAULT. 641 */ 642 if (written) 643 break; 644 return -EFAULT; 645 } 646 } 647 648 /* The vc might have been freed or vcs_size might have changed 649 * while we slept to grab the user buffer, so recheck. 650 * Return data written up to now on failure. 651 */ 652 vc = vcs_vc(inode, &viewed); 653 if (!vc) { 654 if (written) 655 break; 656 return -ENXIO; 657 } 658 size = vcs_size(vc, attr, false); 659 if (size < 0) { 660 if (written) 661 break; 662 return size; 663 } 664 if (pos >= size) 665 break; 666 if (this_round > size - pos) 667 this_round = size - pos; 668 669 /* OK, now actually push the write to the console 670 * under the lock using the local kernel buffer. 671 */ 672 673 if (attr) 674 org = vcs_write_buf(vc, con_buf, pos, this_round, 675 viewed, &org0); 676 else 677 org = vcs_write_buf_noattr(vc, con_buf, pos, this_round, 678 viewed, &org0); 679 680 count -= this_round; 681 written += this_round; 682 buf += this_round; 683 pos += this_round; 684 if (org) 685 update_region(vc, (unsigned long)(org0), org - org0); 686 } 687 *ppos += written; 688 ret = written; 689 if (written) 690 vcs_scr_updated(vc); 691 692 return ret; 693 } 694 695 static __poll_t 696 vcs_poll(struct file *file, poll_table *wait) 697 { 698 struct vcs_poll_data *poll = vcs_poll_data_get(file); 699 __poll_t ret = DEFAULT_POLLMASK|EPOLLERR; 700 701 if (poll) { 702 poll_wait(file, &poll->waitq, wait); 703 switch (poll->event) { 704 case VT_UPDATE: 705 ret = DEFAULT_POLLMASK|EPOLLPRI; 706 break; 707 case VT_DEALLOCATE: 708 ret = DEFAULT_POLLMASK|EPOLLHUP|EPOLLERR; 709 break; 710 case 0: 711 ret = DEFAULT_POLLMASK; 712 break; 713 } 714 } 715 return ret; 716 } 717 718 static int 719 vcs_fasync(int fd, struct file *file, int on) 720 { 721 struct vcs_poll_data *poll = file->private_data; 722 723 if (!poll) { 724 /* don't allocate anything if all we want is disable fasync */ 725 if (!on) 726 return 0; 727 poll = vcs_poll_data_get(file); 728 if (!poll) 729 return -ENOMEM; 730 } 731 732 return fasync_helper(fd, file, on, &poll->fasync); 733 } 734 735 static int 736 vcs_open(struct inode *inode, struct file *filp) 737 { 738 unsigned int currcons = console(inode); 739 bool attr = use_attributes(inode); 740 bool uni_mode = use_unicode(inode); 741 742 /* we currently don't support attributes in unicode mode */ 743 if (attr && uni_mode) 744 return -EOPNOTSUPP; 745 746 guard(console_lock)(); 747 748 if (currcons && !vc_cons_allocated(currcons - 1)) 749 return -ENXIO; 750 751 return 0; 752 } 753 754 static int vcs_release(struct inode *inode, struct file *file) 755 { 756 struct vcs_poll_data *poll = file->private_data; 757 758 if (poll) 759 vcs_poll_data_free(poll); 760 return 0; 761 } 762 763 static const struct file_operations vcs_fops = { 764 .llseek = vcs_lseek, 765 .read = vcs_read, 766 .write = vcs_write, 767 .poll = vcs_poll, 768 .fasync = vcs_fasync, 769 .open = vcs_open, 770 .release = vcs_release, 771 }; 772 773 static const struct class vc_class = { 774 .name = "vc", 775 }; 776 777 void vcs_make_sysfs(int index) 778 { 779 device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL, "vcs%u", index + 1); 780 device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, index + 65), NULL, "vcsu%u", index + 1); 781 device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL, "vcsa%u", index + 1); 782 } 783 784 void vcs_remove_sysfs(int index) 785 { 786 device_destroy(&vc_class, MKDEV(VCS_MAJOR, index + 1)); 787 device_destroy(&vc_class, MKDEV(VCS_MAJOR, index + 65)); 788 device_destroy(&vc_class, MKDEV(VCS_MAJOR, index + 129)); 789 } 790 791 int __init vcs_init(void) 792 { 793 unsigned int i; 794 795 if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops)) 796 panic("unable to get major %d for vcs device", VCS_MAJOR); 797 if (class_register(&vc_class)) 798 panic("unable to create vc_class"); 799 800 device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); 801 device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, 64), NULL, "vcsu"); 802 device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); 803 for (i = 0; i < MIN_NR_CONSOLES; i++) 804 vcs_make_sysfs(i); 805 return 0; 806 } 807