Every active logical volume on a Linux host exposes device nodes at /dev/mapper/<VG>-<LV> and /dev/<VG>/<LV>. The default permissions on these nodes are brw-rw---- root:disk (mode 0660). Anything more permissive than that, a mode like 0666, or a group assignment that includes unprivileged users, lets any local user read and write raw block data on the volume. Filesystem permissions, ACLs, and mount options do not apply at this layer. A user who can open the device node can read /etc/shadow straight off the disk or overwrite filesystem metadata directly.
This is not a theoretical concern. Operators change these permissions for legitimate reasons: a database that wants raw device access, a VM that runs as a non-root user, a backup tool that needs to read the block device. Each of those changes bypasses the entire filesystem permission model for that volume, and because device nodes are recreated from udev rules on every activation, the change tends to be invisible until someone audits the nodes directly.
This guide covers what the nodes are, why the defaults are what they are, where drift comes from, how to audit, and how to set custom permissions that survive activation cycles without opening more access than you intended.
What the device nodes are and why the permissions matter
An LV is a kernel device-mapper object. When it activates, the kernel creates a /dev/dm-N block device, and udev creates the stable names: /dev/mapper/<VG>-<LV> and the /dev/<VG>/<LV> symlink. (The dm-N numbering itself is not stable across reboots; see LVM dm-N device numbers change after reboot: use /dev/mapper, not /dev/dm-N.) Opening any of these paths gives you the same thing: direct access to the block device, with no filesystem in between.
That distinction is the whole point. When a process reads a file, the kernel checks the file’s permissions, the directory permissions along the path, ACLs, and mount options like noexec. When a process opens /dev/mapper/vg0-data for read, the only check is the permission bits and ownership on the device node itself. If that check passes, the process can read any byte on the volume, including blocks belonging to files it has no filesystem-level right to see.
flowchart TD
A[Local user process] -->|open /data/file.txt| B[Filesystem layer]
B -->|checks file perms, ACLs, mount opts| C{Allowed?}
C -->|no| D[EACCES denied]
C -->|yes| E[Block I/O]
A -->|open /dev/mapper/vg0-data| F[Device node check only]
F -->|0660 root:disk or looser| G{In disk group?}
G -->|yes| E
G -->|no| DTwo consequences follow:
The disk group is effectively root-equivalent for data access. With the default root:disk 0660, every member of the disk group can read and write every LV on the host. They can modify filesystem metadata, plant setuid binaries, or read any file’s contents, all without touching the filesystem permission layer. Treat disk group membership the way you treat sudo access.
Loosening the node defeats everything above it. Mode 0664 with a broad group, or 0666, or changing the group to something like users, hands raw volume access to accounts that were never meant to have it. This has been exploited in the past: CVE-2011-4127 allowed local users with access to an LVM volume’s device node to issue SG_IO SCSI commands through it, bypassing intended restrictions on disk operations. The concrete lesson is that device-node write access is not just file access, it is command-level access to the underlying storage in some kernel paths.
How the defaults get set
Device nodes for LVs are not persistent objects with persistent permissions. They are recreated on every activation: at boot, on lvchange -ay, on vgchange -ay, after deactivation and reactivation. The permissions come from udev rules evaluated at activation time, primarily the device-mapper and LVM rule sets under /lib/udev/rules.d/ (or /usr/lib/udev/rules.d/, depending on distribution). The playbook guidance is to check /lib/udev/rules.d/*lvm* for the configured permissions.
The practical consequences:
- A manual
chmodorchownon a device node does not survive. The next activation recreates the node from the udev rules and your change is gone. If someone “fixed” a permissions problem withchmod 666, the fix is temporary, but so is yourchmod 660correction. The rule set is the source of truth. - Drift usually means a modified rule. If a node comes up with permissions other than
brw-rw---- root:disk, someone (or some package, or some provisioning tool) changed a udev rule, added one to/etc/udev/rules.d/, or set permissions from a creation-time path that bypasses udev. - Some applications legitimately need custom ownership. Databases running as a dedicated user against raw LVs, and hypervisors handing LVs to VMs, are the common cases. The playbook explicitly calls these out as legitimate. The right pattern is a dedicated group (for example
oracle,mysql,qemu) applied to the specific LVs that need it, not a global loosening and not adding service accounts todisk.
The upstream LVM tree ships a template rule file, 12-dm-permissions.rules, for exactly this purpose. It is a commented-out example, typically installed under the documentation directory (for example /usr/share/doc/device-mapper-*/), not as an active rule. To use it, you copy it into /etc/udev/rules.d/ and uncomment or adapt the lines. The template matches on device-mapper environment variables such as ENV{DM_VG_NAME}, ENV{DM_LV_NAME}, ENV{DM_NAME}, and ENV{DM_UUID}, and assigns OWNER, GROUP, and MODE with := (overriding) assignments.
One caveat from the field: custom udev rules matching on DM_NAME, DM_VG_NAME, or DM_LV_NAME can silently fail to apply at boot on some init systems, because the device-mapper rules skip processing for coldplug “add” events that lack the DM_UDEV_PRIMARY_SOURCE_FLAG marker (documented in a long-open Gentoo bug). A udevadm trigger --action=change after activation is the usual workaround.
A second caveat: some tools set permissions at creation time through the device-mapper ioctl, before or outside udev rule processing. libvirtd, for example, has been observed creating LVM volumes whose /dev/dm-N node ends up mode 0600 owned by the qemu user regardless of what a 12-dm-permissions.rules-style rule specifies. If your rule “isn’t applying,” check whether the consumer of the volume is setting permissions itself.
Auditing the nodes on a running system
Audit is read-only and safe. The goal is to enumerate every LV device node, compare its mode and ownership against the root:disk 0660 baseline, and explain every deviation.
# List all mapper nodes with mode, owner, group
stat -c '%a %U %G %n' /dev/mapper/* | grep -v '/dev/mapper/control'
# Also check the underlying dm-N nodes
stat -c '%a %U %G %n' /dev/dm-* 2>/dev/null
# Show only nodes more permissive than 0660 or not root:disk
for n in /dev/mapper/* /dev/dm-*; do
[ "$n" = "/dev/mapper/control" ] && continue
mode=$(stat -c '%a' "$n" 2>/dev/null) || continue
owner=$(stat -c '%U:%G' "$n")
if [ "$mode" -gt 660 ] || [ "$owner" != "root:disk" ]; then
echo "DEVIATION: $mode $owner $n"
fi
done
# Find the rule that produced a given node's permissions
udevadm info --query=property --name=/dev/mapper/vg0-data | grep -E 'DM_VG_NAME|DM_LV_NAME'
# Inventory local rules that touch dm/LVM permissions
grep -rEl 'DM_LV_NAME|DM_VG_NAME|DM_NAME' /etc/udev/rules.d/ 2>/dev/null
grep -l -i lvm /lib/udev/rules.d/* 2>/dev/null
Then check who can actually reach the nodes:
# Who is in the disk group?
getent group disk
# Any world-accessible block devices anywhere?
find /dev -type b -perm -o+w 2>/dev/null
find /dev -type b -perm -o+r 2>/dev/null
Every deviation from the baseline needs one of three resolutions: a documented reason (a database group on a specific LV, backed by a rule in /etc/udev/rules.d/), a fix (remove the rule or tighten it), or an escalation (you cannot explain it, which on a production host is a security incident until proven otherwise).
Setting custom permissions the right way
When a workload genuinely needs non-default access, the procedure is:
- Create a dedicated group for the consumer (for example
vmdb), and put only the service account in it. Do not reusediskand do not reuse broad groups likeusers. - Write a rule scoped to the specific LV. Base it on the
12-dm-permissions.rulestemplate, place it in/etc/udev/rules.d/, and match onENV{DM_VG_NAME}andENV{DM_LV_NAME}so the rule applies to exactly one volume, not every dm device on the host. Use:=assignments forGROUP(andMODEif needed, but 0660 should stay). - Apply and verify. Reactivate the LV (
lvchange -anthenlvchange -ayon a volume you can afford to bounce, or wait for the next maintenance activation) and confirm withstat. Remember that deactivation/reactivation recreates the node, so verification must happen after an activation cycle, not just afterudevadm trigger. - Test the boot path. Reboot, or at minimum confirm the rule fires during the boot activation sequence, not only during interactive
lvchange. This is where the coldplug caveat above bites. - Document it. The next auditor (possibly you, at 3 a.m.) needs to know this deviation is intentional.
Keep the mode at 0660. If you find yourself wanting anything world-readable or world-writable, stop and redesign: use group membership, a bind mount of a specific file, or give the consumer access at the filesystem layer instead.
Signals to watch in production
Permissions drift is a classic “looks normal, is silently dangerous” condition. These are the signals worth wiring into regular checks:
| Signal | Why it matters | Warning sign |
|---|---|---|
| Device node mode/ownership per LV | The core drift signal; recreated each activation, so it reflects current rule state | Anything more permissive than 0660 root:disk without a documented rule |
Contents of /etc/udev/rules.d/ touching dm/LVM | This is where persistent drift lives | New or modified rules matching DM_LV_NAME/DM_VG_NAME outside change windows |
disk group membership | Group members hold root-equivalent raw access to all LVs | Any member that is not a deliberate, documented service account |
| Nodes after activation events | Permissions reset on every lvchange -ay / boot | A node that “was fine” reverting, or a custom rule silently not applying at boot |
| Unexpected LVM metadata changes | Unauthorized lvcreate/lvchange implies root-level activity | New entries in /etc/lvm/archive/ or journalctl -t lvm outside change windows |
How Netdata helps
Permissions themselves are file attributes, not time-series metrics, so the monitoring value is in the context around them:
- LVM state collection. Netdata’s LVM monitoring surfaces LV and VG state continuously, so you can correlate a permissions deviation with activation events (an LV that reactivated at 02:14 and changed ownership at 02:14 has a rule-based explanation to find).
- Change correlation. When an audit flags a deviant node, having per-second system metrics around the activation window, I/O to the device, processes that opened it, tells you whether the permissive node was actually accessed and by which workloads.
- Alerting context. Combining LVM health signals with host-level security checks (unexpected group membership changes, audit log anomalies) shortens the path from “weird device node” to “here is when and why it changed.”
- Baseline visibility. Because device nodes are recreated on each activation, a one-time audit is not enough; continuous collection of the surrounding signals is what makes drift detectable between audits.
Related guides
- How LVM actually works in production: a mental model for operators
- LVM dm-N device numbers change after reboot: use /dev/mapper, not /dev/dm-N
- LVM boot activation failure: emergency shell and missing mount points
- LVM commands hang: when lvs, vgs, and pvs block on locks or dead devices
- LVM lock contention: stale lock files and blocked commands
- LVM Couldn’t find device with uuid: a physical volume has gone missing
- LVM Found duplicate PV: multipath devices and the lvm.conf filter
- LVM cannot extend a logical volume: adding a PV when the VG is full
- LVM Insufficient free extents: the volume group is out of space
- LVM filesystem full while the volume group has space: the resize step everyone forgets
- LVM I/O hang: a suspended dm device and processes stuck in D state
- LVM dmeventd not running: the auto-extend safety net is offline






