Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/linux/cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ static inline void cgroup_kthread_ready(void)
}

void cgroup_path_from_kernfs_id(u64 id, char *buf, size_t buflen);
struct cgroup *cgroup_get_from_id(u64 id);
struct cgroup *cgroup_get_from_id(u64 id, bool root_cgns);
#else /* !CONFIG_CGROUPS */

struct cgroup_subsys_state;
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/cgroup_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static int bpf_iter_attach_cgroup(struct bpf_prog *prog,
if (fd)
cgrp = cgroup_v1v2_get_from_fd(fd);
else if (id)
cgrp = cgroup_get_from_id(id);
cgrp = cgroup_get_from_id(id, false);
else /* walk the entire hierarchy by default. */
cgrp = cgroup_get_from_path("/");

Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -2537,7 +2537,7 @@ __bpf_kfunc struct cgroup *bpf_cgroup_from_id(u64 cgid)
{
struct cgroup *cgrp;

cgrp = cgroup_get_from_id(cgid);
cgrp = cgroup_get_from_id(cgid, true);
if (IS_ERR(cgrp))
return NULL;
return cgrp;
Expand Down
7 changes: 6 additions & 1 deletion kernel/cgroup/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -6345,10 +6345,11 @@ void cgroup_path_from_kernfs_id(u64 id, char *buf, size_t buflen)
/*
* cgroup_get_from_id : get the cgroup associated with cgroup id
* @id: cgroup id
* @root_cgns: Select root cgroup namespace instead of current's.
* On success return the cgrp or ERR_PTR on failure
* Only cgroups within current task's cgroup NS are valid.
*/
struct cgroup *cgroup_get_from_id(u64 id)
struct cgroup *cgroup_get_from_id(u64 id, bool root_cgns)
{
struct kernfs_node *kn;
struct cgroup *cgrp, *root_cgrp;
Expand All @@ -6374,6 +6375,10 @@ struct cgroup *cgroup_get_from_id(u64 id)
if (!cgrp)
return ERR_PTR(-ENOENT);

/* We don't need to namespace this operation against current. */
if (root_cgns)
return cgrp;

root_cgrp = current_cgns_cgroup_dfl();
if (!cgroup_is_descendant(cgrp, root_cgrp)) {
cgroup_put(cgrp);
Expand Down
76 changes: 76 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/cgrp_kfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define _GNU_SOURCE
#include <cgroup_helpers.h>
#include <test_progs.h>
#include <sched.h>

#include "cgrp_kfunc_failure.skel.h"
#include "cgrp_kfunc_success.skel.h"
Expand Down Expand Up @@ -87,6 +88,78 @@ static const char * const success_tests[] = {
"test_cgrp_from_id",
};

static void test_cgrp_from_id_ns(void)
{
LIBBPF_OPTS(bpf_test_run_opts, opts);
struct cgrp_kfunc_success *skel;
struct bpf_program *prog;
int fd, pid, pipe_fd[2];

skel = open_load_cgrp_kfunc_skel();
if (!ASSERT_OK_PTR(skel, "open_load_skel"))
return;

if (!ASSERT_OK(skel->bss->err, "pre_mkdir_err"))
goto cleanup;

prog = bpf_object__find_program_by_name(skel->obj, "test_cgrp_from_id_ns");
if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
goto cleanup;

if (!ASSERT_OK(pipe(pipe_fd), "pipe"))
goto cleanup;

pid = fork();
if (!ASSERT_GE(pid, 0, "fork result"))
goto pipe_cleanup;

if (pid == 0) {
int ret = 1;

close(pipe_fd[0]);
fd = create_and_get_cgroup("cgrp_from_id_ns");
if (!ASSERT_GE(fd, 0, "cgrp_fd"))
_exit(1);

if (!ASSERT_OK(join_cgroup("cgrp_from_id_ns"), "join cgrp"))
goto fail;

if (!ASSERT_OK(unshare(CLONE_NEWCGROUP), "unshare cgns"))
goto fail;

ret = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts);
if (!ASSERT_OK(ret, "test run ret"))
goto fail;

remove_cgroup("cgrp_from_id_ns");

if (!ASSERT_OK(opts.retval, "test run retval"))
_exit(1);
ret = 0;
close(fd);
if (!ASSERT_EQ(write(pipe_fd[1], &ret, sizeof(ret)), sizeof(ret), "write pipe"))
_exit(1);

_exit(0);
fail:
remove_cgroup("cgrp_from_id_ns");
_exit(1);
} else {
int res;

close(pipe_fd[1]);
if (!ASSERT_EQ(read(pipe_fd[0], &res, sizeof(res)), sizeof(res), "read res"))
goto pipe_cleanup;
if (!ASSERT_OK(res, "result from run"))
goto pipe_cleanup;
}

pipe_cleanup:
close(pipe_fd[1]);
cleanup:
cgrp_kfunc_success__destroy(skel);
}

void test_cgrp_kfunc(void)
{
int i, err;
Expand All @@ -102,6 +175,9 @@ void test_cgrp_kfunc(void)
run_success_test(success_tests[i]);
}

if (test__start_subtest("test_cgrp_from_id_ns"))
test_cgrp_from_id_ns();

RUN_TESTS(cgrp_kfunc_failure);

cleanup:
Expand Down
12 changes: 12 additions & 0 deletions tools/testing/selftests/bpf/progs/cgrp_kfunc_success.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,15 @@ int BPF_PROG(test_cgrp_from_id, struct cgroup *cgrp, const char *path)

return 0;
}

SEC("syscall")
int test_cgrp_from_id_ns(void *ctx)
{
struct cgroup *cg;

cg = bpf_cgroup_from_id(1);
if (!cg)
return 42;
bpf_cgroup_release(cg);
return 0;
}
Loading