1f08c3bdfSopenharmony_ci/* Copyright (c) 2015 Red Hat, Inc. 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * This program is free software: you can redistribute it and/or modify 4f08c3bdfSopenharmony_ci * it under the terms of version 2 the GNU General Public License as 5f08c3bdfSopenharmony_ci * published by the Free Software Foundation. 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 8f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 9f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10f08c3bdfSopenharmony_ci * GNU General Public License for more details. 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 13f08c3bdfSopenharmony_ci * along with this program. If not, see <http://www.gnu.org/licenses/>. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * Written by Matus Marhefka <mmarhefk@redhat.com> 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci *********************************************************************** 18f08c3bdfSopenharmony_ci * Enters the namespace(s) of a process specified by a PID and then executes 19f08c3bdfSopenharmony_ci * the indicated program inside that namespace(s). 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci */ 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ci#define _GNU_SOURCE 24f08c3bdfSopenharmony_ci#include <sched.h> 25f08c3bdfSopenharmony_ci#include <sys/syscall.h> 26f08c3bdfSopenharmony_ci#include <sys/types.h> 27f08c3bdfSopenharmony_ci#include <sys/wait.h> 28f08c3bdfSopenharmony_ci#include <fcntl.h> 29f08c3bdfSopenharmony_ci#include <unistd.h> 30f08c3bdfSopenharmony_ci#include <string.h> 31f08c3bdfSopenharmony_ci#include <errno.h> 32f08c3bdfSopenharmony_ci#include "test.h" 33f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 34f08c3bdfSopenharmony_ci#include "lapi/namespaces_constants.h" 35f08c3bdfSopenharmony_ci#include "ns_common.h" 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cichar *TCID = "ns_exec"; 38f08c3bdfSopenharmony_ciint ns_fd[NS_TOTAL]; 39f08c3bdfSopenharmony_ciint ns_fds; 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_civoid print_help(void) 43f08c3bdfSopenharmony_ci{ 44f08c3bdfSopenharmony_ci int i; 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci printf("usage: ns_exec <NS_PID> <%s", params[0].name); 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci for (i = 1; params[i].name; i++) 49f08c3bdfSopenharmony_ci printf("|,%s", params[i].name); 50f08c3bdfSopenharmony_ci printf("> <PROGRAM> [ARGS]\nSecond argument indicates the types" 51f08c3bdfSopenharmony_ci " of a namespaces maintained by NS_PID\nand is specified" 52f08c3bdfSopenharmony_ci " as a comma separated list.\nExample: ns_exec 1234 net,ipc" 53f08c3bdfSopenharmony_ci " ip a\n"); 54f08c3bdfSopenharmony_ci} 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cistatic int open_ns_fd(const char *pid, const char *ns) 57f08c3bdfSopenharmony_ci{ 58f08c3bdfSopenharmony_ci int fd; 59f08c3bdfSopenharmony_ci char file_buf[30]; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci sprintf(file_buf, "%s/%s/ns/%s", PROC_PATH, pid, ns); 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci fd = open(file_buf, O_RDONLY); 64f08c3bdfSopenharmony_ci if (fd > 0) { 65f08c3bdfSopenharmony_ci ns_fd[ns_fds] = fd; 66f08c3bdfSopenharmony_ci ++ns_fds; 67f08c3bdfSopenharmony_ci return 0; 68f08c3bdfSopenharmony_ci } else if (fd == -1 && errno != ENOENT) { 69f08c3bdfSopenharmony_ci tst_resm(TINFO | TERRNO, "open"); 70f08c3bdfSopenharmony_ci return -1; 71f08c3bdfSopenharmony_ci } 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci return 0; 74f08c3bdfSopenharmony_ci} 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_cistatic void close_ns_fd(void) 77f08c3bdfSopenharmony_ci{ 78f08c3bdfSopenharmony_ci int i; 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci for (i = 0; i < ns_fds; i++) 81f08c3bdfSopenharmony_ci close(ns_fd[i]); 82f08c3bdfSopenharmony_ci} 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_cistatic int child_fn(void *arg) 85f08c3bdfSopenharmony_ci{ 86f08c3bdfSopenharmony_ci char **args = (char **)arg; 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci execvp(args[3], args+3); 89f08c3bdfSopenharmony_ci tst_resm(TINFO | TERRNO, "execvp"); 90f08c3bdfSopenharmony_ci return 1; 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci/* 94f08c3bdfSopenharmony_ci * ./ns_exec <NS_PID> <ipc,mnt,net,pid,user,uts> <PROGRAM> [ARGS] 95f08c3bdfSopenharmony_ci */ 96f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci int i, rv, pid; 99f08c3bdfSopenharmony_ci char *token; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci rv = syscall(__NR_setns, -1, 0); 102f08c3bdfSopenharmony_ci if (rv == -1 && errno == ENOSYS) { 103f08c3bdfSopenharmony_ci tst_resm(TINFO, "setns is not supported in the kernel"); 104f08c3bdfSopenharmony_ci return 1; 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci if (argc < 4) { 108f08c3bdfSopenharmony_ci print_help(); 109f08c3bdfSopenharmony_ci return 1; 110f08c3bdfSopenharmony_ci } 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci memset(ns_fd, 0, sizeof(ns_fd)); 113f08c3bdfSopenharmony_ci while ((token = strsep(&argv[2], ","))) { 114f08c3bdfSopenharmony_ci struct param *p = get_param(token); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci if (!p) { 117f08c3bdfSopenharmony_ci tst_resm(TINFO, "Unknown namespace: %s", token); 118f08c3bdfSopenharmony_ci print_help(); 119f08c3bdfSopenharmony_ci return 1; 120f08c3bdfSopenharmony_ci } 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci if (open_ns_fd(argv[1], token) != 0) 123f08c3bdfSopenharmony_ci return 1; 124f08c3bdfSopenharmony_ci } 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci if (ns_fds == 0) { 127f08c3bdfSopenharmony_ci tst_resm(TINFO, "no namespace entries in /proc/%s/ns/", 128f08c3bdfSopenharmony_ci argv[1]); 129f08c3bdfSopenharmony_ci return 1; 130f08c3bdfSopenharmony_ci } 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci for (i = 0; i < ns_fds; i++) { 133f08c3bdfSopenharmony_ci if (syscall(__NR_setns, ns_fd[i], 0) == -1) { 134f08c3bdfSopenharmony_ci tst_resm(TINFO | TERRNO, "setns"); 135f08c3bdfSopenharmony_ci close_ns_fd(); 136f08c3bdfSopenharmony_ci return 1; 137f08c3bdfSopenharmony_ci } 138f08c3bdfSopenharmony_ci } 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci pid = ltp_clone_quick(SIGCHLD, (void *)child_fn, (void *)argv); 141f08c3bdfSopenharmony_ci if (pid == -1) { 142f08c3bdfSopenharmony_ci tst_resm(TINFO | TERRNO, "ltp_clone_quick"); 143f08c3bdfSopenharmony_ci close_ns_fd(); 144f08c3bdfSopenharmony_ci return 1; 145f08c3bdfSopenharmony_ci } 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci if (waitpid(pid, &rv, 0) == -1) { 148f08c3bdfSopenharmony_ci tst_resm(TINFO | TERRNO, "waitpid"); 149f08c3bdfSopenharmony_ci return 1; 150f08c3bdfSopenharmony_ci } 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci close_ns_fd(); 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci if (WIFEXITED(rv)) 155f08c3bdfSopenharmony_ci return WEXITSTATUS(rv); 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci return 0; 158f08c3bdfSopenharmony_ci} 159