Karel Zak [Wed, 10 Jun 2026 08:52:44 +0000 (10:52 +0200)]
fdisk: (resize) avoid redundant error on partnum failure
fdisk_ask_partnum() already prints its own diagnostics on failure,
so go directly to 'out' instead of 'err' which would print a
redundant "Could not resize partition" message with a meaningless
partition number.
Also removes the need for the i=0 initialization from the previous
commit, since 'i' is no longer used on the fdisk_ask_partnum()
error path.
Addresses: https://github.com/util-linux/util-linux/pull/4394 Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak [Wed, 10 Jun 2026 07:47:21 +0000 (09:47 +0200)]
Merge branch 'PR/libmount-more-restrict' of https://github.com/karelzak/util-linux-work
* 'PR/libmount-more-restrict' of https://github.com/karelzak/util-linux-work:
build: warn when libmount udev support is disabled
libmount: disable libblkid probing for non-root users
libblkid: add blkid_evaluate_tag2() with flags
umount: restrict non-root users to mountpoint paths only
aizu-m [Tue, 9 Jun 2026 19:24:04 +0000 (00:54 +0530)]
libfdisk: clamp out-of-range d_npartitions in bsd_readlabel
d_npartitions is a uint16 partition count read straight from an on-disk
BSD disklabel. bsd_readlabel() warns when it is larger than
BSD_MAXPARTITIONS but leaves the value untouched, so the bogus count
survives into the rest of the label handling.
bsd_dkcksum() walks the label up to &lp->d_partitions[d_npartitions]
when the label is written back. d_partitions[] holds 16 entries
(256 bytes); a crafted disklabel can set the count to 65535 and push
that end pointer about 1 MB past the array, an out-of-bounds read.
Clamp the count to BSD_MAXPARTITIONS in the block that already emits the
warning, the same upper bound sun/sgi/gpt enforce on their arrays.
Karel Zak [Tue, 9 Jun 2026 13:03:04 +0000 (15:03 +0200)]
tests: remove loop devices from lsblk bcachefs dump
The loop device infrastructure does not support sysfs dump-based data.
When lsblk runs with --sysroot, the ignore_empty() function calls
loopdev_has_backing_file() which operates on the real /dev/loopN
device rather than the sysroot data. This causes host-dependent test
results -- if the CI machine has a loop device with a backing file,
the device appears in the output despite having size 0 in the dump.
Remove loop0 and loop1 entries from the multi-devs-bcachefs sysfs
dump to avoid this false positive.
The setsid completion used the old manual COMP_WORDS/COMP_CWORD pattern
and never delegated to the sub-command's own completion. When typing e.g.
"setsid -f rm -<Tab>", completion would show setsid options instead of rm
options.
Rewrite to use _init_completion and _command_offset, matching the pattern
used by unshare and other wrapper commands. This correctly detects where
the sub-command begins and delegates completion to it.
The sub-command detection loop explicitly enumerates known options via
NOARGOPTS/NOARGOPTS_SHORT (pipe-separated for regex matching), ensuring that
short options like -f, -c, -w are properly skipped rather than being treated
as the sub-command start.
Fixes: #4073 Signed-off-by: Liu Zheng <liuzheng@uniontech.com>
Karel Zak [Tue, 2 Jun 2026 10:30:21 +0000 (12:30 +0200)]
build: warn when libmount udev support is disabled
Non-root tag resolution (LABEL=, UUID=) in mount/umount depends on
udev support in libmount. Without it, suid mount/umount cannot
resolve tags for unprivileged users since direct device probing
is disabled for security reasons.
Karel Zak [Tue, 2 Jun 2026 10:27:15 +0000 (12:27 +0200)]
libmount: disable libblkid probing for non-root users
Add noprobe flag to struct libmnt_cache that disables low-level
device probing via libblkid. When the mount context is restricted
(non-root user), the flag is set automatically on cache creation
and on externally provided caches.
With noprobe enabled:
- read_from_blkid() is skipped (device I/O blocked)
- mnt_resolve_tag() uses blkid_evaluate_tag2() with
BLKID_EVALUATE_NOPROBE, so tags are resolved only via
udev /dev/disk/by-* symlinks without device scanning
This minimizes the libblkid attack surface for suid mount/umount
binaries.
Karel Zak [Tue, 2 Jun 2026 10:25:27 +0000 (12:25 +0200)]
libblkid: add blkid_evaluate_tag2() with flags
Add blkid_evaluate_tag2() that accepts flags to control tag
evaluation behavior. The BLKID_EVALUATE_NOPROBE flag disables
low-level device scanning (evaluate_by_scan), while keeping
udev symlink-based evaluation (evaluate_by_udev) functional.
The original blkid_evaluate_tag() is now a thin wrapper around
the new function with flags=0.
Karel Zak [Mon, 1 Jun 2026 13:22:53 +0000 (15:22 +0200)]
umount: restrict non-root users to mountpoint paths only
Non-root users should only specify mountpoints when calling umount.
Device names, tags (LABEL=, UUID=, etc.) and loop device resolution
are disabled for unprivileged users to avoid processing untrusted
input through tag resolution code paths before permission checks.
In umount.c, reject tag arguments and disable swapmatch for
restricted users. In libmount, skip source and loopdev swapmatch
lookups for restricted contexts as defense in depth.
Bash automatically unsets the MKFDS_PID variable when the coproc
terminates. If the multiplexer syscall is not available at runtime
(e.g., select on ppc64le with kernel 6.18 returns ENOSYS despite
__NR_select being defined at compile time), the coproc exits
immediately and MKFDS_PID becomes empty, causing:
wait: '': not a pid or valid job spec
Save MKFDS_PID to a regular variable (MKFDS_CPID) immediately after
starting the coproc.
Additionally, add a kill -0 liveness check after reading the PID to
detect when the multiplexer process died early (e.g., due to ENOSYS)
and skip the subtest cleanly.
Karel Zak [Mon, 8 Jun 2026 12:10:04 +0000 (14:10 +0200)]
Merge branch 'chcpu_tests' of https://github.com/cgoesche/util-linux-fork
* 'chcpu_tests' of https://github.com/cgoesche/util-linux-fork:
tests: (chcpu) add missing tests
chcpu: add a helper function to read the CPU 'online' bitmap
chcpu: add --sysroot option
Karel Zak [Mon, 8 Jun 2026 11:41:26 +0000 (13:41 +0200)]
man pages: avoid troff warning about undefined 'Aq' string
Asciidoctor's manpage backend places the .TH line (which references
\*(Aq for the apostrophe in "Programmer's Manual") before the .ds Aq
definition. This causes troff warning:
name 'Aq' not defined [-w mac]
Replace "Programmer's Manual" with "Library Calls" to avoid the
apostrophe. This also aligns with man(7) convention for section 3
and is consistent with how other sections already avoid possessives
(e.g. "User Commands", "System Administration").
Reported-by: Bjarni Ingi Gislason <bjarniig@simnet.is> Signed-off-by: Karel Zak <kzak@redhat.com>
Wang Yu [Tue, 2 Jun 2026 12:57:43 +0000 (20:57 +0800)]
lsblk: truncate long ID-LINK columns
The udev by-id link can be very long for some USB devices. Mark the ID
and ID-LINK columns as truncatable so extreme values do not stretch the
entire table.
This patch makes it possible to configure the CPUs on a Linux
system other than the one on which the chcpu command is called.
To achieve this users can simply define the root directory of
the sys/ directory with the --sysroot command line option. It
is also beneficial for regression tests, as these make use of
sysfs tar archive dumps.
To properly implement this new feature, the syspath initialization
had to be deferred until after all option arguments, especially
--sysroot, have been parsed, which simplified the path access check.
Along the way a small refactoring of the enable,disable,configure &
deconfigure option parsing had been done, more precisely the CPU list
option argument is now saved in a variable 'cpu_list_arg' to defer
the CPU list validity check until after all option arguments have
been parsed to simplify the logic. Lastly, getopt(3)'s 'optarg' variable
is used instead of argv[optind-1] to store the options argument, which
is more idiomatic and readable.
Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Karel Zak [Tue, 2 Jun 2026 11:34:00 +0000 (13:34 +0200)]
Merge branch 'PR/hexdump-color-overflow' of https://github.com/karelzak/util-linux-work
* 'PR/hexdump-color-overflow' of https://github.com/karelzak/util-linux-work:
tests: (hexdump) use arrays for OPTS and ADDRFMT
hexdump: fix buffer overflow in color_cond()
Karel Zak [Tue, 2 Jun 2026 11:32:44 +0000 (13:32 +0200)]
Merge branch 'PR/lscpu-arm-nooverwrite' of https://github.com/karelzak/util-linux-work
* 'PR/lscpu-arm-nooverwrite' of https://github.com/karelzak/util-linux-work:
lscpu: set nooverwrite for Phytium ARM implementer
lscpu: add nooverwrite flag for ARM implementer table
lscpu: add find_implementer() for ARM implementer lookup
Liu Zheng [Tue, 2 Jun 2026 06:26:28 +0000 (14:26 +0800)]
hardlink: preserve timestamps when reflinking files
When using --reflink=always, the destination file gets the current
timestamp instead of preserving the original file's atime and mtime.
This differs from both hardlink behavior and "cp -p --reflink=always".
Add futimens() call after successful reflink to restore the original
timestamps from the target file's stat data.
Commit ded434a63f3eee7fd7805b18d6c9bb912016c3c8 ("include/mount-api-utils:
add statmount and listmount") introduce a fallback definition for the
LSMT_ROOT defined, but a small typo makes this fallback definition
ineffective:
Karel Zak [Mon, 1 Jun 2026 09:23:57 +0000 (11:23 +0200)]
readprofile: replace popen() with fork/exec for .gz map files
Security scanners repeatedly flag the popen("zcat %s", name) pattern
as a command injection vulnerability (CWE-78). While this is a false
positive -- readprofile is not installed with elevated privileges and
the filename comes from the user's own command line -- the reports are
a recurring nuisance.
The root cause is that popen() passes the command through /bin/sh,
which makes scanners flag it regardless of whether the input is
actually untrusted. Replace popen() with fork()/execlp() to invoke
zcat directly without shell interpretation. This eliminates the
shell from the execution path and silences the scanners without
adding any new dependencies.
Also use ul_endswith() for the .gz suffix check, and handle fdopen()
failure after fork to avoid fd leak and zombie process.
Karel Zak [Mon, 1 Jun 2026 11:52:33 +0000 (13:52 +0200)]
tests: (hexdump) use arrays for OPTS and ADDRFMT
Convert OPTS and ADDRFMT from plain strings to bash arrays and use
proper "${…[@]}" expansion to fix shellcheck SC2090/SC2086 warnings
about unquoted variables containing quotes/backslashes.
Karel Zak [Thu, 28 May 2026 12:01:53 +0000 (14:01 +0200)]
fstrim: resolve non-device sources to real block devices
When fstrim reads fstab entries (--fstab, --listed-in), bind mount
entries use directory paths as sources (e.g. /data/ssd/ldap) rather
than device names. Source de-duplication compares path strings, so
these never match the real device paths (e.g. /dev/mapper/foo),
causing the same filesystem to be trimmed multiple times.
Use statmount(STATMOUNT_SB_SOURCE) to resolve directory source paths
to their real block device before de-duplication. Fall back to the
original source when statmount() is unavailable.
Addresses: https://github.com/util-linux/util-linux/issues/857 Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak [Thu, 28 May 2026 14:09:20 +0000 (16:09 +0200)]
hexdump: fix buffer overflow in color_cond()
Widen the color condition value from int (4 bytes) to int64_t (8 bytes)
to accommodate format strings with 8-byte conversion units (e.g.,
1/8 "%016x"). The memcpy() in color_cond() copies clr->range bytes
into a local variable, and for 8-byte units this overflows a 4-byte
int.
Also switch strtoul() to strtoll() in the color format parser to
correctly parse 64-bit values into the widened int64_t field.
Change hexdump_clr.range from int to size_t (a byte count should never
be negative), add a defensive guard against memcpy overflow in
color_cond(), and add an 8-byte color condition regression test.
Reported-by: Michał Majchrowicz (AFINE Team) Reported-by: Marcin Wyczechowski (AFINE Team) Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak [Thu, 28 May 2026 10:03:28 +0000 (12:03 +0200)]
lscpu: add nooverwrite flag for ARM implementer table
Add a nooverwrite flag to struct hw_impl. When set, vendor and model
name already provided by the kernel in /proc/cpuinfo are preserved
rather than being overwritten by the hardcoded lookup tables. The
tables serve as a fallback when the kernel does not provide the
information.
This approach keeps all implementer entries in the table, which is
also required for "lscpu --arm-id" to list all known vendors and
part IDs.
Addresses: https://github.com/util-linux/util-linux/pull/4362 Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak [Mon, 1 Jun 2026 10:15:53 +0000 (12:15 +0200)]
Merge branch 'PR/libmount-no-symlinks' of https://github.com/karelzak/util-linux-work
* 'PR/libmount-no-symlinks' of https://github.com/karelzak/util-linux-work:
loopdev: use openat2(RESOLVE_NO_SYMLINKS) for backing file
lib/fileutils: add ul_open_no_symlinks()
Furkan Caliskan [Sun, 31 May 2026 08:36:58 +0000 (11:36 +0300)]
uclampset: fix lost-update race in set_uclamp_one()
The function unconditionally sets both SCHED_FLAG_UTIL_CLAMP_MIN and
SCHED_FLAG_UTIL_CLAMP_MAX in sa.sched_flags regardless of which values
the user actually requested to change.
This creates a lost-update race: sched_getattr() fetches the current
clamp values, but between that call and sched_setattr(), another thread
may legitimately update the value we did not intend to touch. Because
both flags are always set, sched_setattr() forces the kernel to apply
the stale cached value, silently overwriting the concurrent update.
Brian Mak [Thu, 28 May 2026 19:08:04 +0000 (12:08 -0700)]
dmesg: fix off-by-one read buffer size
PRINTK_MESSAGE_MAX is 2048 in the kernel. In a formatted record that is
exactly 2048 bytes, reading /proc/kmsg with a size of PRINTK_MESSAGE_MAX
- 1 (2047) will result in the read syscall returning -EINVAL.
We see such a case when using a large initrd, for which the kernel
outputs loading spinner characters, based on the size of the initrd. For
a large enough initrd, there will be enough spinner characters to create
several formatted records of size 2048.
We fix this by increasing the kmsg_buf size by 1, which increases the
size used by the read syscall to PRINTK_MESSAGE_MAX (2048).
Karel Zak [Thu, 28 May 2026 10:01:01 +0000 (12:01 +0200)]
lscpu: add find_implementer() for ARM implementer lookup
Refactor ARM implementer lookup into a dedicated find_implementer()
function and use it in is_arm() and arm_ids_decode() to simplify
the code and avoid open-coded linear searches.
Addresses: https://github.com/util-linux/util-linux/pull/4362 Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak [Thu, 28 May 2026 09:05:55 +0000 (11:05 +0200)]
tests: use tar --no-same-owner for sysfs dump extraction
Use --no-same-owner when extracting sysfs dump tarballs so that
extracted files are owned by the current user rather than preserving
the original (often root) ownership from the archive.
This allows chmem tests to run without root since they only operate
on a local sysfs dump via --sysroot. The valid_zones file (0444 in
real sysfs) needs an explicit chmod u+w before the test can write
to it. Apply --no-same-owner to lsblk, lscpu, lsmem, and hardlink
tests for consistency.
Karel Zak [Thu, 28 May 2026 08:54:33 +0000 (10:54 +0200)]
chmem: simplify have_mem_blk_zones()
Use ul_path_accessf() instead of manual ul_strconcat() + ul_path_access()
+ free(). This avoids a potential NULL dereference if ul_strconcat() fails
on memory allocation.
Karel Zak [Thu, 28 May 2026 08:52:28 +0000 (10:52 +0200)]
Merge branch 'chmem_tests' of https://github.com/cgoesche/util-linux-fork
* 'chmem_tests' of https://github.com/cgoesche/util-linux-fork:
tests: (chmem) add tests for aarch64 16K 16G memory layout
chmem: add helper function to sensibly detect the 'valid_zones' attribute
tests: (chmem) add missing tests
chmem: add a new --sysroot command line option
Karel Zak [Wed, 27 May 2026 13:15:22 +0000 (15:15 +0200)]
loopdev: use openat2(RESOLVE_NO_SYMLINKS) for backing file
Use ul_open_no_symlinks() instead of open(O_NOFOLLOW) when
LOOPDEV_FL_NOFOLLOW is set. O_NOFOLLOW only rejects symlinks at the
last path component, but TOCTOU attacks swap intermediate components.
openat2(RESOLVE_NO_SYMLINKS) rejects symlinks at any component.
Karel Zak [Wed, 27 May 2026 08:35:39 +0000 (10:35 +0200)]
lib/fileutils: add ul_open_no_symlinks()
Add a helper that opens a path rejecting symlinks at any component,
not just the last one. Uses openat2(RESOLVE_NO_SYMLINKS) when
available (Linux >= 5.6), falls back to open(O_NOFOLLOW).
Karel Zak [Thu, 28 May 2026 08:14:29 +0000 (10:14 +0200)]
Merge branch 'PR/getino-op-types' of https://github.com/karelzak/util-linux-work
* 'PR/getino-op-types' of https://github.com/karelzak/util-linux-work:
getino: cleanup whitespace
getino: rename GETINO_*_NAMESPACE to GETINO_NS_*
getino: split operation type and namespace type
Karel Zak [Tue, 26 May 2026 08:57:09 +0000 (10:57 +0200)]
getino: split operation type and namespace type
Separate the single GETINO_* enum into two levels: a basic operation
type (GETINO_OP_PIDFS vs GETINO_OP_NAMESPACE) and a namespace sub-type
that directly indexes the ns_info[] array starting at 0.
This eliminates the IS_NAMESPACE_OP() macro, the get_pidfd_ns_ioctl()
and pidfd_get_nsfd_or_err() helper functions, and the unused pidfd_ioctl
field from getino_context. The dispatch in print_inode() now uses a
clean switch on ctx->op.
Karel Zak [Tue, 26 May 2026 14:16:03 +0000 (16:16 +0200)]
libfdisk: fix use of on-disk sizeof_partition_entry in GPT
The GPT code hardcodes sizeof(struct gpt_entry) (128 bytes) in
several places instead of using the on-disk sizeof_partition_entry
field from the GPT header. The UEFI specification allows entry sizes
larger than 128 bytes.
- reject GPT headers where sizeof_partition_entry is smaller than
sizeof(struct gpt_entry) to prevent out-of-bounds reads when
accessing entry array elements
- use the on-disk entry size as the qsort element stride in
gpt_reorder() to avoid corrupting entries when sizeof_partition_entry
differs from 128
- use the on-disk entry size in gpt_copy_header() when calculating
the backup partition entry array LBA
chmem: add helper function to sensibly detect the 'valid_zones' attribute
On some systems the first available memory blocks start at an index
greater than 0, and on such systems we fail to properly detect the
valid_zones attribute, because we naively checked for the presence
of the memory block directory 'memory0'. To sensibly and reliably
detect the first memory block, we can use the directory sysmem->dirs
that are sorted in numeric order, so we can assume that the first
entry is the first memory block, i.e. sysmem->dirs[0]->d_name is
the name of the first configurable memory block.
Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
This new option allows an administrator to configure memory
on a Linux instance other than the one on which chmem(1) is
executed. Additionally, it facilitates regression testing
with sysfs dumps.
Signed-off-by: Christian Goeschel Ndjomouo <cgoesc2@wgu.edu>
Karel Zak [Tue, 26 May 2026 10:21:49 +0000 (12:21 +0200)]
chrt: always use sched_setattr() for all policies
Remove the set_sched_one_by_setscheduler() shortcut for non-deadline
policies from the HAVE_SCHED_SETATTR code path. The original reason
(2016, commit 88b60f0bdee6) was that sched_setattr() reset the nice
value, causing EPERM for non-root users. But getpriority() already
preserves the nice setting, making the shortcut unnecessary.
The shortcut caused --clamp-min/--clamp-max (SCHED_FLAG_UTIL_CLAMP)
to be silently ignored for SCHED_FIFO and SCHED_RR, because those
policies were routed through sched_setscheduler() which cannot pass
sched_flags at all.
Using sched_setattr() unconditionally ensures all sched_flags work
with all policies and prevents the same class of bug for future flag
additions.
Addresses: https://github.com/util-linux/util-linux/pull/4351 Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak [Tue, 26 May 2026 10:10:42 +0000 (12:10 +0200)]
Merge branch 'chrt-util-clamp' of https://github.com/1frn10/util-linux-fork
* 'chrt-util-clamp' of https://github.com/1frn10/util-linux-fork:
chrt: Add uclamp reset support via -1 sentinel
Update schedutils/chrt.c
Update schedutils/chrt.c
chrt: Add support for SCHED_FLAG_UTIL_CLAMP
Karel Zak [Tue, 26 May 2026 09:29:46 +0000 (11:29 +0200)]
Merge branch 'PR/agetty-split' of https://github.com/karelzak/util-linux-work
* 'PR/agetty-split' of https://github.com/karelzak/util-linux-work: (24 commits)
agetty: guard conditional function declarations in header
agetty: fix path_cxt leak in credential loading
agetty: move fakehost to struct agetty_options
agetty: make longopts[] static const
agetty: move usage() and parse_args() before main()
agetty: clean up includes in agetty.c
agetty: add public domain header to all source files
agetty: remove duplicate ISSUEDIR_EXT from agetty.c
agetty: move login argv initialization to utils.c
agetty: move username to struct agetty_options
agetty: move parse_speeds() to utils.c
agetty: move init_special_char() to utils.c
agetty: move FIRST_SPEED to tty.c
agetty: use bool for struct agetty_issue bitfields
agetty: split out issue file functions to issuefile.c
agetty: move struct issue and related defines to agetty.h
agetty: split out terminal functions to tty.c
agetty: split out speed table and baud code to tty.c
agetty: move utility functions to utils.c
agetty: split out credential loading to credentials.c
...
Karel Zak [Mon, 25 May 2026 11:33:34 +0000 (13:33 +0200)]
pipesz: merge help/version getopt loop into main loop
The main() function scanned command-line options in two passes: the
first pass checked for --help/--version, and the second processed
normal options. When getopt_long encountered an unknown option in the
first pass, it printed an error message. The same error was then
printed again during the second pass, resulting in a duplicate
"unrecognized option" message.
Fix this by merging the first getopt_long loop into the main one,
following the standard util-linux convention.
Fixes: https://github.com/util-linux/util-linux/issues/3817 Signed-off-by: Karel Zak <kzak@redhat.com>
Furkan Caliskan [Fri, 15 May 2026 05:37:25 +0000 (08:37 +0300)]
chrt: Add uclamp reset support via -1 sentinel
Passing -1 to --clamp-min or --clamp-max sets the corresponding
sched_attr field to UINT32_MAX, which tells the kernel to reset
the utilization clamp to its system default. Resetting requires
kernel >= 5.11, otherwise the syscall will fail with EINVAL.
Karel Zak [Wed, 20 May 2026 10:44:21 +0000 (12:44 +0200)]
agetty: guard conditional function declarations in header
Wrap agetty_update_utmp() declaration with #ifdef SYSV_STYLE and
agetty_issue_is_changed()/agetty_reload() with #ifdef AGETTY_RELOAD
to match the guards on their definitions.