clinuxlinux-kernelmountmount-point

How can i mount cgroup controller by mount()


I want to mount cgroup controller by mount() in c language.

code like this and mount_path has already give 777 permissions and run by root(host not container, with full capabilities),but program return "mount failed: Operation not permitted",and i try to use mount command is work well, but code not

Is some error in my code?

mount("none", mount_path, "cgroup", 0, "none,name=memory")

just want same effect like mount -t cgroup -o memory cgroup /tmp

I find stackoverflow and github but could not find the answer.

Thanks

code is very simple like this

// if(mount("none", mount_path, "cgroup", 0, "none,name=memory")){
if(mount("cgroup", "/tmp/b", "cgroup", 0, "memory")){
        perror("mount failed");
    }

strace mount result strace -o trace.txt mount -t cgroup -o memory cgroup /tmp

execve("/usr/bin/mount", ["mount", "-t", "cgroup", "-o", "memory", "cgroup", "/tmp/a/"], 0xffffd37390c0 /* 50 vars */) = 0
brk(NULL)                               = 0xaaab1a331000
faccessat(AT_FDCWD, "/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=69312, ...}) = 0
mmap(NULL, 69312, PROT_READ, MAP_PRIVATE, 3, 0) = 0xffff9d7aa000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libmount.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\340\263\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=383480, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xffff9d7e7000
mmap(NULL, 447832, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xffff9d73c000
mprotect(0xffff9d797000, 65536, PROT_NONE) = 0
mmap(0xffff9d7a7000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5b000) = 0xffff9d7a7000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0`\17\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1450832, ...}) = 0
mmap(NULL, 1519552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xffff9d5c9000
mprotect(0xffff9d724000, 61440, PROT_NONE) = 0
mmap(0xffff9d733000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15a000) = 0xffff9d733000
mmap(0xffff9d739000, 12224, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xffff9d739000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libblkid.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\360\236\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=355240, ...}) = 0
mmap(NULL, 419600, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xffff9d562000
mprotect(0xffff9d5b3000, 65536, PROT_NONE) = 0
mmap(0xffff9d5c3000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x51000) = 0xffff9d5c3000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0 e\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=154872, ...}) = 0
mmap(NULL, 227800, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xffff9d52a000
mprotect(0xffff9d54f000, 61440, PROT_NONE) = 0
mmap(0xffff9d55e000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x24000) = 0xffff9d55e000
mmap(0xffff9d560000, 6616, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xffff9d560000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\0\"\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=514504, ...}) = 0
mmap(NULL, 578176, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xffff9d49c000
mprotect(0xffff9d518000, 65536, PROT_NONE) = 0
mmap(0xffff9d528000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7c000) = 0xffff9d528000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0P\17\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=14560, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xffff9d7e5000
mmap(NULL, 78080, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xffff9d488000
mprotect(0xffff9d48b000, 61440, PROT_NONE) = 0
mmap(0xffff9d49a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0xffff9d49a000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0Ha\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=164304, ...}) = 0
mmap(NULL, 197624, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xffff9d457000
mprotect(0xffff9d473000, 61440, PROT_NONE) = 0
mmap(0xffff9d482000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b000) = 0xffff9d482000
mmap(0xffff9d484000, 13304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xffff9d484000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xffff9d7e3000
mprotect(0xffff9d733000, 16384, PROT_READ) = 0
mprotect(0xffff9d482000, 4096, PROT_READ) = 0
mprotect(0xffff9d49a000, 4096, PROT_READ) = 0
mprotect(0xffff9d528000, 4096, PROT_READ) = 0
mprotect(0xffff9d55e000, 4096, PROT_READ) = 0
mprotect(0xffff9d5c3000, 20480, PROT_READ) = 0
mprotect(0xffff9d7a7000, 8192, PROT_READ) = 0
mprotect(0xaaaae690a000, 4096, PROT_READ) = 0
mprotect(0xffff9d7ec000, 4096, PROT_READ) = 0
munmap(0xffff9d7aa000, 69312)           = 0
set_tid_address(0xffff9d7e30e0)         = 16344
set_robust_list(0xffff9d7e30f0, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0xffff9d45cbd0, sa_mask=[], sa_flags=SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0xffff9d45cc90, sa_mask=[], sa_flags=SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
statfs("/sys/fs/selinux", 0xffffff7f4740) = -1 ENOENT (No such file or directory)
statfs("/selinux", 0xffffff7f4740)      = -1 ENOENT (No such file or directory)
brk(NULL)                               = 0xaaab1a331000
brk(0xaaab1a352000)                     = 0xaaab1a352000
openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "nodev\tsysfs\nnodev\ttmpfs\nnodev\tbd"..., 1024) = 413
read(3, "", 1024)                       = 0
close(3)                                = 0
faccessat(AT_FDCWD, "/etc/selinux/config", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3035952, ...}) = 0
mmap(NULL, 3035952, PROT_READ, MAP_PRIVATE, 3, 0) = 0xffff9d171000
close(3)                                = 0
getuid()                                = 0
geteuid()                               = 0
faccessat(AT_FDCWD, "/sys/fs/smackfs", F_OK) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "/tmp/a", {st_mode=S_IFDIR|0755, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "/sbin/mount.cgroup", 0xffffff7f2418, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/sbin/fs.d/mount.cgroup", 0xffffff7f2418, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/sbin/fs/mount.cgroup", 0xffffff7f2418, 0) = -1 ENOENT (No such file or directory)
getuid()                                = 0
geteuid()                               = 0
getgid()                                = 0
getegid()                               = 0
prctl(PR_GET_DUMPABLE)                  = 1 (SUID_DUMP_USER)
newfstatat(AT_FDCWD, "/run", {st_mode=S_IFDIR|0755, st_size=1000, ...}, 0) = 0
newfstatat(AT_FDCWD, "/run/mount/utab", {st_mode=S_IFREG|0644, st_size=500, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "/run/mount/utab", {st_mode=S_IFREG|0644, st_size=500, ...}, 0) = 0
geteuid()                               = 0
getegid()                               = 0
getuid()                                = 0
getgid()                                = 0
faccessat(AT_FDCWD, "/run/mount/utab", R_OK|W_OK) = 0
mount("cgroup", "/tmp/a", "cgroup", 0, "memory") = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

Edit mount("none", mount_path, "cgroup", 0, "none,name=memory") to mount("cgroup", "/tmp/b", "cgroup", 0, "memory") mount() return 0,but no file in mount path


Solution

  • If I build an executable from the following code:

    #include <stdio.h>
    #include <sys/mount.h>
    
    int main() {
        if(mount("cgroup", "/tmp/b", "cgroup", 0, "memory")){
            perror("mount failed");
        }
    }
    

    And run it as a non-root user, I get:

    $ ./mounttest
    mount failed: Operation not permitted
    

    If I run it as root on a system that is using cgroupsv2, I see:

    $ sudo ./mounttest
    mount failed: Device or resource busy
    

    We can verify whether or not a system is using cgroupsv2 by running mount -t cgroup2. If we see a mount...

    cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)
    

    ...then we're using cgroupsv2 and we don't be able to use the -o memory option.

    On a system using cgroupsv1, it works as expected:

    $ sudo ./mounttest
    $ ls /tmp/b
    cgroup.clone_children           memory.kmem.tcp.failcnt             memory.soft_limit_in_bytes
    cgroup.event_control            memory.kmem.tcp.limit_in_bytes      memory.stat
    cgroup.procs                    memory.kmem.tcp.max_usage_in_bytes  memory.swappiness
    cgroup.sane_behavior            memory.kmem.tcp.usage_in_bytes      memory.usage_in_bytes
    init.scope                      memory.kmem.usage_in_bytes          memory.use_hierarchy
    memory.failcnt                  memory.limit_in_bytes               notify_on_release
    memory.force_empty              memory.max_usage_in_bytes           release_agent
    memory.kmem.failcnt             memory.move_charge_at_immigrate     system.slice
    memory.kmem.limit_in_bytes      memory.numa_stat                    tasks
    memory.kmem.max_usage_in_bytes  memory.oom_control                  user.slice
    memory.kmem.slabinfo            memory.pressure_level