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