// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2019 Federico Bonfiglio fedebonfi95@gmail.com */ /* * Test ioctl_ns with NS_GET_PARENT request. * * Parent process tries to get parent of initial namespace, which should * fail with EPERM because it has no parent. * * Child process has a new pid namespace, which should make the call fail * with EPERM error. * */ #define _GNU_SOURCE #include #include #include #include "tst_test.h" #include "lapi/ioctl_ns.h" #include "lapi/namespaces_constants.h" #define STACK_SIZE (1024 * 1024) static char *child_stack; static void setup(void) { int exists = access("/proc/self/ns/pid", F_OK); if (exists < 0) tst_res(TCONF, "namespace not available"); child_stack = ltp_alloc_stack(STACK_SIZE); if (!child_stack) tst_brk(TBROK|TERRNO, "stack alloc"); } static void cleanup(void) { free(child_stack); } static void test_ns_get_parent(void) { int fd, parent_fd; fd = SAFE_OPEN("/proc/self/ns/pid", O_RDONLY); parent_fd = ioctl(fd, NS_GET_PARENT); if (parent_fd == -1) { if (errno == ENOTTY) tst_brk(TCONF, "ioctl(NS_GET_PARENT) not implemented"); if (errno == EPERM) tst_res(TPASS, "NS_GET_PARENT fails with EPERM"); else tst_res(TFAIL | TERRNO, "unexpected ioctl error"); } else { SAFE_CLOSE(fd); tst_res(TFAIL, "call to ioctl succeded"); } } static int child(void *arg LTP_ATTRIBUTE_UNUSED) { test_ns_get_parent(); return 0; } static void run(void) { test_ns_get_parent(); if (ltp_clone(CLONE_NEWPID | SIGCHLD, &child, 0, STACK_SIZE, child_stack) == -1) tst_brk(TBROK | TERRNO, "ltp_clone failed"); } static struct tst_test test = { .test_all = run, .forks_child = 1, .needs_root = 1, .min_kver = "4.9", .setup = setup, .cleanup = cleanup, };