Skip to content

Commit 0e1051d

Browse files
committed
fix(container): handle EPERM from mknodat in configure_device
Rootless containers lack CAP_MKNOD so mknodat fails with EPERM. Fallback to bind mounting the host device instead, matching crun's behavior for user-namespace containers. Also remove the unconditional bind mount that ran after successful mknodat — it redundantly mounted over the freshly created device node. Signed-off-by: Yuming He <ComixHe1895@outlook.com>
1 parent c9c111e commit 0e1051d

1 file changed

Lines changed: 22 additions & 16 deletions

File tree

src/linyaps_box/container.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,27 +1195,33 @@ class mounter
11951195
return;
11961196
}
11971197

1198+
// In user namespace, mknodat fails with EPERM because CAP_MKNOD is
1199+
// not available. Fallback to bind mount the host device.
1200+
if (ec == std::errc::operation_not_permitted) {
1201+
LINYAPS_BOX_DEBUG() << "fallback to bind mount device";
1202+
linyaps_box::config::mount_t mount;
1203+
mount.source = destination;
1204+
mount.destination = destination;
1205+
mount.type = "bind";
1206+
mount.flags = MS_BIND | MS_PRIVATE | MS_NOEXEC | MS_NOSUID;
1207+
this->mount(mount);
1208+
return;
1209+
}
1210+
11981211
throw std::system_error(ec, "mknodat");
11991212
}
12001213

1201-
auto new_dev = linyaps_box::utils::open_at(root, path);
1202-
path = new_dev.proc_path();
1203-
if (UNLIKELY(chmod(path.c_str(), mode) < 0)) {
1204-
throw std::system_error(errno, std::system_category(), "chmod");
1205-
}
1214+
{
1215+
auto new_dev = linyaps_box::utils::open_at(root, path);
1216+
auto new_path = new_dev.proc_path();
1217+
if (UNLIKELY(chmod(new_path.c_str(), mode) < 0)) {
1218+
throw std::system_error(errno, std::system_category(), "chmod");
1219+
}
12061220

1207-
if (UNLIKELY(chown(path.c_str(), uid, gid) < 0)) {
1208-
throw std::system_error(errno, std::system_category(), "chown");
1221+
if (UNLIKELY(chown(new_path.c_str(), uid, gid) < 0)) {
1222+
throw std::system_error(errno, std::system_category(), "chown");
1223+
}
12091224
}
1210-
1211-
// NOTE: fallback to bind mount host device into container
1212-
LINYAPS_BOX_DEBUG() << "fallback to bind mount device";
1213-
linyaps_box::config::mount_t mount;
1214-
mount.source = destination;
1215-
mount.destination = destination;
1216-
mount.type = "bind";
1217-
mount.flags = MS_BIND | MS_PRIVATE | MS_NOEXEC | MS_NOSUID;
1218-
this->mount(mount);
12191225
}
12201226

12211227
// https://github.com/opencontainers/runtime-spec/blob/main/config-linux.md#default-devices

0 commit comments

Comments
 (0)