]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Aug 2024 11:46:04 +0000 (13:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Aug 2024 11:46:04 +0000 (13:46 +0200)
added patches:
memcg-protect-concurrent-access-to-mem_cgroup_idr.patch
serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch
serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch
serial-sc16is7xx-fix-tx-fifo-corruption.patch
tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch

queue-6.10/memcg-protect-concurrent-access-to-mem_cgroup_idr.patch [new file with mode: 0644]
queue-6.10/serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch [new file with mode: 0644]
queue-6.10/serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch [new file with mode: 0644]
queue-6.10/serial-sc16is7xx-fix-tx-fifo-corruption.patch [new file with mode: 0644]
queue-6.10/series
queue-6.10/tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch [new file with mode: 0644]

diff --git a/queue-6.10/memcg-protect-concurrent-access-to-mem_cgroup_idr.patch b/queue-6.10/memcg-protect-concurrent-access-to-mem_cgroup_idr.patch
new file mode 100644 (file)
index 0000000..060e870
--- /dev/null
@@ -0,0 +1,104 @@
+From 9972605a238339b85bd16b084eed5f18414d22db Mon Sep 17 00:00:00 2001
+From: Shakeel Butt <shakeel.butt@linux.dev>
+Date: Fri, 2 Aug 2024 16:58:22 -0700
+Subject: memcg: protect concurrent access to mem_cgroup_idr
+
+From: Shakeel Butt <shakeel.butt@linux.dev>
+
+commit 9972605a238339b85bd16b084eed5f18414d22db upstream.
+
+Commit 73f576c04b94 ("mm: memcontrol: fix cgroup creation failure after
+many small jobs") decoupled the memcg IDs from the CSS ID space to fix the
+cgroup creation failures.  It introduced IDR to maintain the memcg ID
+space.  The IDR depends on external synchronization mechanisms for
+modifications.  For the mem_cgroup_idr, the idr_alloc() and idr_replace()
+happen within css callback and thus are protected through cgroup_mutex
+from concurrent modifications.  However idr_remove() for mem_cgroup_idr
+was not protected against concurrency and can be run concurrently for
+different memcgs when they hit their refcnt to zero.  Fix that.
+
+We have been seeing list_lru based kernel crashes at a low frequency in
+our fleet for a long time.  These crashes were in different part of
+list_lru code including list_lru_add(), list_lru_del() and reparenting
+code.  Upon further inspection, it looked like for a given object (dentry
+and inode), the super_block's list_lru didn't have list_lru_one for the
+memcg of that object.  The initial suspicions were either the object is
+not allocated through kmem_cache_alloc_lru() or somehow
+memcg_list_lru_alloc() failed to allocate list_lru_one() for a memcg but
+returned success.  No evidence were found for these cases.
+
+Looking more deeply, we started seeing situations where valid memcg's id
+is not present in mem_cgroup_idr and in some cases multiple valid memcgs
+have same id and mem_cgroup_idr is pointing to one of them.  So, the most
+reasonable explanation is that these situations can happen due to race
+between multiple idr_remove() calls or race between
+idr_alloc()/idr_replace() and idr_remove().  These races are causing
+multiple memcgs to acquire the same ID and then offlining of one of them
+would cleanup list_lrus on the system for all of them.  Later access from
+other memcgs to the list_lru cause crashes due to missing list_lru_one.
+
+Link: https://lkml.kernel.org/r/20240802235822.1830976-1-shakeel.butt@linux.dev
+Fixes: 73f576c04b94 ("mm: memcontrol: fix cgroup creation failure after many small jobs")
+Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
+Acked-by: Muchun Song <muchun.song@linux.dev>
+Reviewed-by: Roman Gushchin <roman.gushchin@linux.dev>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memcontrol.c |   22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -5568,11 +5568,28 @@ static struct cftype mem_cgroup_legacy_f
+ #define MEM_CGROUP_ID_MAX     ((1UL << MEM_CGROUP_ID_SHIFT) - 1)
+ static DEFINE_IDR(mem_cgroup_idr);
++static DEFINE_SPINLOCK(memcg_idr_lock);
++
++static int mem_cgroup_alloc_id(void)
++{
++      int ret;
++
++      idr_preload(GFP_KERNEL);
++      spin_lock(&memcg_idr_lock);
++      ret = idr_alloc(&mem_cgroup_idr, NULL, 1, MEM_CGROUP_ID_MAX + 1,
++                      GFP_NOWAIT);
++      spin_unlock(&memcg_idr_lock);
++      idr_preload_end();
++      return ret;
++}
+ static void mem_cgroup_id_remove(struct mem_cgroup *memcg)
+ {
+       if (memcg->id.id > 0) {
++              spin_lock(&memcg_idr_lock);
+               idr_remove(&mem_cgroup_idr, memcg->id.id);
++              spin_unlock(&memcg_idr_lock);
++
+               memcg->id.id = 0;
+       }
+ }
+@@ -5706,8 +5723,7 @@ static struct mem_cgroup *mem_cgroup_all
+       if (!memcg)
+               return ERR_PTR(error);
+-      memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL,
+-                               1, MEM_CGROUP_ID_MAX + 1, GFP_KERNEL);
++      memcg->id.id = mem_cgroup_alloc_id();
+       if (memcg->id.id < 0) {
+               error = memcg->id.id;
+               goto fail;
+@@ -5854,7 +5870,9 @@ static int mem_cgroup_css_online(struct
+        * publish it here at the end of onlining. This matches the
+        * regular ID destruction during offlining.
+        */
++      spin_lock(&memcg_idr_lock);
+       idr_replace(&mem_cgroup_idr, memcg, memcg->id.id);
++      spin_unlock(&memcg_idr_lock);
+       return 0;
+ offline_kmem:
diff --git a/queue-6.10/serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch b/queue-6.10/serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch
new file mode 100644 (file)
index 0000000..8120351
--- /dev/null
@@ -0,0 +1,68 @@
+From 6eabce6608d6f3440f4c03aa3d3ef50a47a3d193 Mon Sep 17 00:00:00 2001
+From: George Kennedy <george.kennedy@oracle.com>
+Date: Wed, 17 Jul 2024 07:24:38 -0500
+Subject: serial: core: check uartclk for zero to avoid divide by zero
+
+From: George Kennedy <george.kennedy@oracle.com>
+
+commit 6eabce6608d6f3440f4c03aa3d3ef50a47a3d193 upstream.
+
+Calling ioctl TIOCSSERIAL with an invalid baud_base can
+result in uartclk being zero, which will result in a
+divide by zero error in uart_get_divisor(). The check for
+uartclk being zero in uart_set_info() needs to be done
+before other settings are made as subsequent calls to
+ioctl TIOCSSERIAL for the same port would be impacted if
+the uartclk check was done where uartclk gets set.
+
+Oops: divide error: 0000  PREEMPT SMP KASAN PTI
+RIP: 0010:uart_get_divisor (drivers/tty/serial/serial_core.c:580)
+Call Trace:
+ <TASK>
+serial8250_get_divisor (drivers/tty/serial/8250/8250_port.c:2576
+    drivers/tty/serial/8250/8250_port.c:2589)
+serial8250_do_set_termios (drivers/tty/serial/8250/8250_port.c:502
+    drivers/tty/serial/8250/8250_port.c:2741)
+serial8250_set_termios (drivers/tty/serial/8250/8250_port.c:2862)
+uart_change_line_settings (./include/linux/spinlock.h:376
+    ./include/linux/serial_core.h:608 drivers/tty/serial/serial_core.c:222)
+uart_port_startup (drivers/tty/serial/serial_core.c:342)
+uart_startup (drivers/tty/serial/serial_core.c:368)
+uart_set_info (drivers/tty/serial/serial_core.c:1034)
+uart_set_info_user (drivers/tty/serial/serial_core.c:1059)
+tty_set_serial (drivers/tty/tty_io.c:2637)
+tty_ioctl (drivers/tty/tty_io.c:2647 drivers/tty/tty_io.c:2791)
+__x64_sys_ioctl (fs/ioctl.c:52 fs/ioctl.c:907
+    fs/ioctl.c:893 fs/ioctl.c:893)
+do_syscall_64 (arch/x86/entry/common.c:52
+    (discriminator 1) arch/x86/entry/common.c:83 (discriminator 1))
+entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
+
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: George Kennedy <george.kennedy@oracle.com>
+Rule: add
+Link: https://lore.kernel.org/stable/1721148848-9784-1-git-send-email-george.kennedy%40oracle.com
+Link: https://lore.kernel.org/r/1721219078-3209-1-git-send-email-george.kennedy@oracle.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/serial_core.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -881,6 +881,14 @@ static int uart_set_info(struct tty_stru
+       new_flags = (__force upf_t)new_info->flags;
+       old_custom_divisor = uport->custom_divisor;
++      if (!(uport->flags & UPF_FIXED_PORT)) {
++              unsigned int uartclk = new_info->baud_base * 16;
++              /* check needs to be done here before other settings made */
++              if (uartclk == 0) {
++                      retval = -EINVAL;
++                      goto exit;
++              }
++      }
+       if (!capable(CAP_SYS_ADMIN)) {
+               retval = -EPERM;
+               if (change_irq || change_port ||
diff --git a/queue-6.10/serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch b/queue-6.10/serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch
new file mode 100644 (file)
index 0000000..44ba360
--- /dev/null
@@ -0,0 +1,57 @@
+From 7d3b793faaab1305994ce568b59d61927235f57b Mon Sep 17 00:00:00 2001
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Date: Tue, 23 Jul 2024 08:53:01 -0400
+Subject: serial: sc16is7xx: fix invalid FIFO access with special register set
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+commit 7d3b793faaab1305994ce568b59d61927235f57b upstream.
+
+When enabling access to the special register set, Receiver time-out and
+RHR interrupts can happen. In this case, the IRQ handler will try to read
+from the FIFO thru the RHR register at address 0x00, but address 0x00 is
+mapped to DLL register, resulting in erroneous FIFO reading.
+
+Call graph example:
+    sc16is7xx_startup(): entry
+    sc16is7xx_ms_proc(): entry
+    sc16is7xx_set_termios(): entry
+    sc16is7xx_set_baud(): DLH/DLL = $009C --> access special register set
+    sc16is7xx_port_irq() entry            --> IIR is 0x0C
+    sc16is7xx_handle_rx() entry
+    sc16is7xx_fifo_read(): --> unable to access FIFO (RHR) because it is
+                               mapped to DLL (LCR=LCR_CONF_MODE_A)
+    sc16is7xx_set_baud(): exit --> Restore access to general register set
+
+Fix the problem by claiming the efr_lock mutex when accessing the Special
+register set.
+
+Fixes: dfeae619d781 ("serial: sc16is7xx")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Link: https://lore.kernel.org/r/20240723125302.1305372-3-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/sc16is7xx.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -591,6 +591,8 @@ static int sc16is7xx_set_baud(struct uar
+                             SC16IS7XX_MCR_CLKSEL_BIT,
+                             prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT);
++      mutex_lock(&one->efr_lock);
++
+       /* Backup LCR and access special register set (DLL/DLH) */
+       lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);
+       sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
+@@ -605,6 +607,8 @@ static int sc16is7xx_set_baud(struct uar
+       /* Restore LCR and access to general register set */
+       sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
++      mutex_unlock(&one->efr_lock);
++
+       return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
+ }
diff --git a/queue-6.10/serial-sc16is7xx-fix-tx-fifo-corruption.patch b/queue-6.10/serial-sc16is7xx-fix-tx-fifo-corruption.patch
new file mode 100644 (file)
index 0000000..96dd59a
--- /dev/null
@@ -0,0 +1,125 @@
+From 133f4c00b8b2bfcacead9b81e7e8edfceb4b06c4 Mon Sep 17 00:00:00 2001
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Date: Tue, 23 Jul 2024 08:53:00 -0400
+Subject: serial: sc16is7xx: fix TX fifo corruption
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+commit 133f4c00b8b2bfcacead9b81e7e8edfceb4b06c4 upstream.
+
+Sometimes, when a packet is received on channel A at almost the same time
+as a packet is about to be transmitted on channel B, we observe with a
+logic analyzer that the received packet on channel A is transmitted on
+channel B. In other words, the Tx buffer data on channel B is corrupted
+with data from channel A.
+
+The problem appeared since commit 4409df5866b7 ("serial: sc16is7xx: change
+EFR lock to operate on each channels"), which changed the EFR locking to
+operate on each channel instead of chip-wise.
+
+This commit has introduced a regression, because the EFR lock is used not
+only to protect the EFR registers access, but also, in a very obscure and
+undocumented way, to protect access to the data buffer, which is shared by
+the Tx and Rx handlers, but also by each channel of the IC.
+
+Fix this regression first by switching to kfifo_out_linear_ptr() in
+sc16is7xx_handle_tx() to eliminate the need for a shared Rx/Tx buffer.
+
+Secondly, replace the chip-wise Rx buffer with a separate Rx buffer for
+each channel.
+
+Fixes: 4409df5866b7 ("serial: sc16is7xx: change EFR lock to operate on each channels")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Link: https://lore.kernel.org/r/20240723125302.1305372-2-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/sc16is7xx.c |   21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -326,6 +326,7 @@ struct sc16is7xx_one {
+       struct kthread_work             reg_work;
+       struct kthread_delayed_work     ms_work;
+       struct sc16is7xx_one_config     config;
++      unsigned char                   buf[SC16IS7XX_FIFO_SIZE]; /* Rx buffer. */
+       unsigned int                    old_mctrl;
+       u8                              old_lcr; /* Value before EFR access. */
+       bool                            irda_mode;
+@@ -339,7 +340,6 @@ struct sc16is7xx_port {
+       unsigned long                   gpio_valid_mask;
+ #endif
+       u8                              mctrl_mask;
+-      unsigned char                   buf[SC16IS7XX_FIFO_SIZE];
+       struct kthread_worker           kworker;
+       struct task_struct              *kworker_task;
+       struct sc16is7xx_one            p[];
+@@ -611,18 +611,18 @@ static int sc16is7xx_set_baud(struct uar
+ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
+                               unsigned int iir)
+ {
+-      struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
++      struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
+       unsigned int lsr = 0, bytes_read, i;
+       bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false;
+       u8 ch, flag;
+-      if (unlikely(rxlen >= sizeof(s->buf))) {
++      if (unlikely(rxlen >= sizeof(one->buf))) {
+               dev_warn_ratelimited(port->dev,
+                                    "ttySC%i: Possible RX FIFO overrun: %d\n",
+                                    port->line, rxlen);
+               port->icount.buf_overrun++;
+               /* Ensure sanity of RX level */
+-              rxlen = sizeof(s->buf);
++              rxlen = sizeof(one->buf);
+       }
+       while (rxlen) {
+@@ -635,10 +635,10 @@ static void sc16is7xx_handle_rx(struct u
+                       lsr = 0;
+               if (read_lsr) {
+-                      s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG);
++                      one->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG);
+                       bytes_read = 1;
+               } else {
+-                      sc16is7xx_fifo_read(port, s->buf, rxlen);
++                      sc16is7xx_fifo_read(port, one->buf, rxlen);
+                       bytes_read = rxlen;
+               }
+@@ -671,7 +671,7 @@ static void sc16is7xx_handle_rx(struct u
+               }
+               for (i = 0; i < bytes_read; ++i) {
+-                      ch = s->buf[i];
++                      ch = one->buf[i];
+                       if (uart_handle_sysrq_char(port, ch))
+                               continue;
+@@ -689,10 +689,10 @@ static void sc16is7xx_handle_rx(struct u
+ static void sc16is7xx_handle_tx(struct uart_port *port)
+ {
+-      struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+       struct tty_port *tport = &port->state->port;
+       unsigned long flags;
+       unsigned int txlen;
++      unsigned char *tail;
+       if (unlikely(port->x_char)) {
+               sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
+@@ -717,8 +717,9 @@ static void sc16is7xx_handle_tx(struct u
+               txlen = 0;
+       }
+-      txlen = uart_fifo_out(port, s->buf, txlen);
+-      sc16is7xx_fifo_write(port, s->buf, txlen);
++      txlen = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen);
++      sc16is7xx_fifo_write(port, tail, txlen);
++      uart_xmit_advance(port, txlen);
+       uart_port_lock_irqsave(port, &flags);
+       if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
index 9bf6775a37172341dbed15ab81bed65b5d54f253..74833fdf22e25ab407687890aa8c834c52ed4777 100644 (file)
@@ -206,3 +206,8 @@ tracefs-fix-inode-allocation.patch
 tracefs-use-generic-inode-rcu-for-synchronizing-freeing.patch
 ntp-safeguard-against-time_constant-overflow.patch
 timekeeping-fix-bogus-clock_was_set-invocation-in-do_adjtimex.patch
+serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch
+serial-sc16is7xx-fix-tx-fifo-corruption.patch
+serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch
+tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch
+memcg-protect-concurrent-access-to-mem_cgroup_idr.patch
diff --git a/queue-6.10/tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch b/queue-6.10/tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch
new file mode 100644 (file)
index 0000000..182ea14
--- /dev/null
@@ -0,0 +1,88 @@
+From 6e20753da6bc651e02378a0cdb78f16c42098c88 Mon Sep 17 00:00:00 2001
+From: Max Krummenacher <max.krummenacher@toradex.com>
+Date: Thu, 25 Jul 2024 15:20:45 +0200
+Subject: tty: vt: conmakehash: cope with abs_srctree no longer in env
+
+From: Max Krummenacher <max.krummenacher@toradex.com>
+
+commit 6e20753da6bc651e02378a0cdb78f16c42098c88 upstream.
+
+conmakehash uses getenv("abs_srctree") from the environment to strip
+the absolute path from the generated sources.
+However since commit e2bad142bb3d ("kbuild: unexport abs_srctree and
+abs_objtree") this environment variable no longer gets set.
+Instead use basename() to indicate the used file in a comment of the
+generated source file.
+
+Fixes: 3bd85c6c97b2 ("tty: vt: conmakehash: Don't mention the full path of the input in output")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
+Link: https://lore.kernel.org/stable/20240725132056.9151-1-max.oss.09%40gmail.com
+Link: https://lore.kernel.org/r/20240725132056.9151-1-max.oss.09@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/vt/conmakehash.c | 20 +++++++-------------
+ 1 file changed, 7 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/tty/vt/conmakehash.c b/drivers/tty/vt/conmakehash.c
+index dc2177fec715..82d9db68b2ce 100644
+--- a/drivers/tty/vt/conmakehash.c
++++ b/drivers/tty/vt/conmakehash.c
+@@ -11,6 +11,8 @@
+  * Copyright (C) 1995-1997 H. Peter Anvin
+  */
++#include <libgen.h>
++#include <linux/limits.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sysexits.h>
+@@ -76,8 +78,8 @@ static void addpair(int fp, int un)
+ int main(int argc, char *argv[])
+ {
+   FILE *ctbl;
+-  const char *tblname, *rel_tblname;
+-  const char *abs_srctree;
++  const char *tblname;
++  char base_tblname[PATH_MAX];
+   char buffer[65536];
+   int fontlen;
+   int i, nuni, nent;
+@@ -102,16 +104,6 @@ int main(int argc, char *argv[])
+       }
+     }
+-  abs_srctree = getenv("abs_srctree");
+-  if (abs_srctree && !strncmp(abs_srctree, tblname, strlen(abs_srctree)))
+-    {
+-      rel_tblname = tblname + strlen(abs_srctree);
+-      while (*rel_tblname == '/')
+-      ++rel_tblname;
+-    }
+-  else
+-    rel_tblname = tblname;
+-
+   /* For now we assume the default font is always 256 characters. */
+   fontlen = 256;
+@@ -253,6 +245,8 @@ int main(int argc, char *argv[])
+   for ( i = 0 ; i < fontlen ; i++ )
+     nuni += unicount[i];
++  strncpy(base_tblname, tblname, PATH_MAX);
++  base_tblname[PATH_MAX - 1] = 0;
+   printf("\
+ /*\n\
+  * Do not edit this file; it was automatically generated by\n\
+@@ -264,7 +258,7 @@ int main(int argc, char *argv[])
+ #include <linux/types.h>\n\
+ \n\
+ u8 dfont_unicount[%d] = \n\
+-{\n\t", rel_tblname, fontlen);
++{\n\t", basename(base_tblname), fontlen);
+   for ( i = 0 ; i < fontlen ; i++ )
+     {
+-- 
+2.46.0
+