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