aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/vt/consolemap.c
diff options
context:
space:
mode:
authorLiz Clark <liz.clark@hp.com>2012-03-15 13:33:29 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-15 16:28:52 -0400
commit4a4c61b7ce26bfc9d49ea4bd121d52114bad9f99 (patch)
tree9ba4849babb673b14724e5ab202ca3d330d46eb2 /drivers/tty/vt/consolemap.c
parent9b96fbacda34079dea0638ee1e92c56286f6114a (diff)
TTY: Wrong unicode value copied in con_set_unimap()
Bugzilla 40012: PIO_UNIMAP bug: error updating Unicode-to-font map https://bugzilla.kernel.org/show_bug.cgi?id=40012 The unicode font map for the virtual console is a 32x32x64 table which allocates rows dynamically as entries are added. The unicode value increases sequentially and should count all entries even in empty rows. The defect is when copying the unicode font map in con_set_unimap(), the unicode value is not incremented properly. The wrong unicode value is entered in the new font map. Signed-off-by: Liz Clark <liz.clark@hp.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/vt/consolemap.c')
-rw-r--r--drivers/tty/vt/consolemap.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index a0f3d6c4d39d..8308fc7cdc26 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -516,6 +516,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
516 int err = 0, err1, i; 516 int err = 0, err1, i;
517 struct uni_pagedir *p, *q; 517 struct uni_pagedir *p, *q;
518 518
519 /* Save original vc_unipagdir_loc in case we allocate a new one */
519 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; 520 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
520 if (p->readonly) return -EIO; 521 if (p->readonly) return -EIO;
521 522
@@ -528,26 +529,57 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
528 err1 = con_clear_unimap(vc, NULL); 529 err1 = con_clear_unimap(vc, NULL);
529 if (err1) return err1; 530 if (err1) return err1;
530 531
532 /*
533 * Since refcount was > 1, con_clear_unimap() allocated a
534 * a new uni_pagedir for this vc. Re: p != q
535 */
531 q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; 536 q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
532 for (i = 0, l = 0; i < 32; i++) 537
538 /*
539 * uni_pgdir is a 32*32*64 table with rows allocated
540 * when its first entry is added. The unicode value must
541 * still be incremented for empty rows. We are copying
542 * entries from "p" (old) to "q" (new).
543 */
544 l = 0; /* unicode value */
545 for (i = 0; i < 32; i++)
533 if ((p1 = p->uni_pgdir[i])) 546 if ((p1 = p->uni_pgdir[i]))
534 for (j = 0; j < 32; j++) 547 for (j = 0; j < 32; j++)
535 if ((p2 = p1[j])) 548 if ((p2 = p1[j])) {
536 for (k = 0; k < 64; k++, l++) 549 for (k = 0; k < 64; k++, l++)
537 if (p2[k] != 0xffff) { 550 if (p2[k] != 0xffff) {
551 /*
552 * Found one, copy entry for unicode
553 * l with fontpos value p2[k].
554 */
538 err1 = con_insert_unipair(q, l, p2[k]); 555 err1 = con_insert_unipair(q, l, p2[k]);
539 if (err1) { 556 if (err1) {
540 p->refcount++; 557 p->refcount++;
541 *vc->vc_uni_pagedir_loc = (unsigned long)p; 558 *vc->vc_uni_pagedir_loc = (unsigned long)p;
542 con_release_unimap(q); 559 con_release_unimap(q);
543 kfree(q); 560 kfree(q);
544 return err1; 561 return err1;
545 } 562 }
546 } 563 }
547 p = q; 564 } else {
548 } else if (p == dflt) 565 /* Account for row of 64 empty entries */
566 l += 64;
567 }
568 else
569 /* Account for empty table */
570 l += 32 * 64;
571
572 /*
573 * Finished copying font table, set vc_uni_pagedir to new table
574 */
575 p = q;
576 } else if (p == dflt) {
549 dflt = NULL; 577 dflt = NULL;
550 578 }
579
580 /*
581 * Insert user specified unicode pairs into new table.
582 */
551 while (ct--) { 583 while (ct--) {
552 unsigned short unicode, fontpos; 584 unsigned short unicode, fontpos;
553 __get_user(unicode, &list->unicode); 585 __get_user(unicode, &list->unicode);
@@ -557,11 +589,14 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
557 list++; 589 list++;
558 } 590 }
559 591
592 /*
593 * Merge with fontmaps of any other virtual consoles.
594 */
560 if (con_unify_unimap(vc, p)) 595 if (con_unify_unimap(vc, p))
561 return err; 596 return err;
562 597
563 for (i = 0; i <= 3; i++) 598 for (i = 0; i <= 3; i++)
564 set_inverse_transl(vc, p, i); /* Update all inverse translations */ 599 set_inverse_transl(vc, p, i); /* Update inverse translations */
565 set_inverse_trans_unicode(vc, p); 600 set_inverse_trans_unicode(vc, p);
566 601
567 return err; 602 return err;