首页 / 指南 / 错误排查 / Linux

"Permission denied" on /dev/kfd — the AMD GPU group fix

Linux

作者: Jakub Rusinowski · 最后更新: 2026年9月1日

AI 教育者、本地 LLM 部署工作坊讲师

The error

Unable to open /dev/kfd read-write: Permission denied
rocminfo: HSA_STATUS_ERROR_OUT_OF_RESOURCES

hsa api call failure at: ... HSA_STATUS_ERROR_OUT_OF_RESOURCES

你遇到的是哪一种?

如果你看到原因是前往
sudo rocminfo works and plain rocminfo does notYour user is not in the render and video groupsFix 1: add the groups — this asymmetry is the whole diagnosis
You ran usermod and groups still does not show themGroup membership is established at loginFix 2: log out and back in
It works for you but the Ollama service still cannot use the GPUThe service runs as the ollama user, which needs the groups tooFix 3: add the service user
Permission denied inside a container onlyHost group IDs were not passed into the containerFix 4: --group-add with numeric IDs
Neither group exists on this distributionDifferent distros name and own these nodes differentlyFix 5: a udev rule is the durable answer

When you see it

The tell is an asymmetry, and it is diagnostic on its own: run the exact same command with sudo and it works, run it as yourself and it fails. Nothing about ROCm, your card, or your driver is wrong. You cannot open the device file.

What's actually going on

ROCm reaches the GPU through two device nodes: /dev/kfd, the compute node the kernel fusion driver exposes, and /dev/dri/render*, the render nodes. Both are owned by system groups — conventionally render and video — precisely so that arbitrary local users cannot submit work to the GPU. Your account is in neither by default, so every ROCm call fails at open(). sudo bypasses the check, which is why the workaround appears to work and why so many people end up running inference as root without realising they never fixed anything. The error surfaces confusingly downstream: HSA_STATUS_ERROR_OUT_OF_RESOURCES sounds like a memory problem and is very often this permission problem seen one layer up.

How to fix it

1. Add your user to the render and video groups

One command, and it is the documented prerequisite in AMD's own ROCm installation guide. -a matters: without it, usermod -G replaces your entire group list rather than appending to it, which can remove you from sudo and lock you out of administration on the machine.

⚠️ Always include -a. sudo usermod -G video,render $LOGNAME without it replaces every secondary group you belong to, sudo included, and on a machine with no other administrator that is a recovery-media problem.

bash
# bash
sudo usermod -a -G video,render $LOGNAME

# Confirm the account record was updated (this does NOT mean it is active yet)
id -nG $LOGNAME
ls -l /dev/kfd /dev/dri/render*
生效了吗? id -nG lists render and video. Note this reads the account database — your current session still does not have them, which fix 2 is about.
id -nG $LOGNAME | tr ' ' '\n' | grep -E '^(render|video)

2. Log out and back in — this is the step that makes people think it failed

Group membership is established when your session is created. Your shell, and every process it will ever start, is still carrying the group list from before you ran usermod, and no amount of re-running the command changes that. Log out of your desktop session entirely, or reconnect your SSH session, and try again. newgrp render grants the group in the current shell only — useful for a quick test, not a fix, and a fresh terminal will not have it.

bash
# bash — quick test without logging out (this shell only)
newgrp render
rocminfo | grep -i "Marketing Name:"

# The real check, after logging out and back in
groups
rocminfo | grep -i "Marketing Name:"
生效了吗? groups — not id -nG — includes render and video in a brand-new terminal, and rocminfo names your card without sudo.
groups
rocminfo | grep -c gfx

3. Add the ollama service user too, not just your own

This is the half that gets missed. When Ollama runs as a systemd service it runs as the ollama user, and that account needs the same group membership. Fixing your own login does nothing for it — which is exactly why rocminfo succeeds in your terminal while the service insists there is no GPU. The service picks up new groups on restart rather than needing a login.

bash
# bash
sudo usermod -a -G render,video ollama
sudo systemctl restart ollama

# What groups does the service user actually have?
id -nG ollama
journalctl -u ollama --no-pager -n 40 | grep -i -E "gpu|rocm|vulkan"
生效了吗? The service log reports a GPU, and a loaded model shows GPU placement rather than CPU.
ollama run gemma3:1b "hi" && ollama ps

4. Pass the numeric group IDs into containers

Inside a container the group names mean nothing — the image has its own /etc/group and its render group, if it has one, will have a different number. What the kernel checks is the numeric GID, so pass those. Get them from ls -lnd, where -n prints numbers instead of names, and hand them to --group-add.

bash
# bash — -n gives numeric owners, which is what you need here
ls -lnd /dev/kfd /dev/dri /dev/dri/*

docker run --rm --device /dev/kfd --device /dev/dri \
  --group-add 44 --group-add 993 \
  rocm/dev-ubuntu-22.04 rocminfo
生效了吗? rocminfo inside the container lists a GPU agent. Only a CPU agent means the GIDs are still wrong.
docker run --rm --device /dev/kfd --device /dev/dri --group-add 44 --group-add 993 rocm/dev-ubuntu-22.04 rocminfo | grep -i "Marketing Name"

5. Write a udev rule where the distribution differs

Not every distribution uses the same names or ownership for these nodes, and on some the group can be reset by a driver package update. A udev rule pins the ownership yourself and survives updates, which makes it the durable answer on a machine you maintain. Check what the nodes actually look like first — the rule should match your system, not a copied example.

⚠️ A udev rule with mode 0666 makes the GPU compute node world-accessible to every local user. Set the group and use 0660 instead unless you have a specific reason not to.

bash
# bash — inspect first
ls -l /dev/kfd /dev/dri/render*

# Then pin ownership
sudo tee /etc/udev/rules.d/70-amdgpu-compute.rules >/dev/null <<'EOF'
KERNEL=="kfd", GROUP="render", MODE="0660"
SUBSYSTEM=="drm", KERNEL=="renderD*", GROUP="render", MODE="0660"
EOF
sudo udevadm control --reload-rules && sudo udevadm trigger
生效了吗? Both device nodes show group render and mode crw-rw----, and they keep those values after a reboot.
ls -l /dev/kfd /dev/dri/render*

6. Stop running inference as root Most common fix

Worth saying directly, because sudo ollama serve works and is therefore tempting. Running inference as root means every model you pull, every file the process writes, and every bug in a fast-moving stack executes with full system privileges — and it creates root-owned files in your model store that your normal user then cannot manage. It is not a fix; it is the diagnosis restated as a habit. The group change above takes one command and a logout.

bash
# bash — undo root-owned artefacts from earlier sudo runs
sudo chown -R $LOGNAME:$LOGNAME ~/.ollama
ls -ld ~/.ollama ~/.ollama/models
生效了吗? Your model directory is owned by you, and inference runs without sudo.
ls -ld ~/.ollama/models && rocminfo | grep -c gfx
Check what fits your hardware — see what your Radeon can run once ROCm can reach it
Open the VRAM checker →

如果以上都没用

If the permissions are right and ROCm still finds no GPU agent, the problem is support rather than access, and the override-and-Vulkan page is the next stop. If this only happens inside containers, the container page covers device passing and SELinux.

上报问题时请附上这些信息

相关内容

A model that fits most setups:
View model & requirements →

Frequently asked questions

Why does ROCm work with sudo but not as my user?

Because /dev/kfd and /dev/dri/render* are owned by the render and video groups, and root bypasses the check. Your account is in neither group by default, so every ROCm call fails at open(). That asymmetry is the diagnosis on its own.

I ran usermod and nothing changed. Did it fail?

No — group membership is established at login, so your current session still carries the old list. Log out and back in, or reconnect your SSH session. newgrp render grants it in one shell for testing but does not carry to new terminals.

Why is the Ollama service still not seeing the GPU?

Because it runs as the ollama user, not as you, and that account needs the same groups: sudo usermod -a -G render,video ollama, then restart the service. Fixing your own login has no effect on it.

What does HSA_STATUS_ERROR_OUT_OF_RESOURCES mean here?

Despite the wording it is frequently this permission failure seen one layer up, not a memory problem. If the same command succeeds under sudo, treat it as permissions and check group membership before you go looking at model sizes.

Why do containers need numeric group IDs?

Because the group name inside the image is unrelated to the host's, and the kernel checks the numeric GID. Read the numbers with ls -lnd /dev/kfd /dev/dri /dev/dri/* and pass each with --group-add.