int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) { int (*orig_mount)(const char *, const char *, const char *, unsigned long, const void *); int targetfd = -1; orig_mount = dlsym(RTLD_NEXT, "mount"); if (!strcmp("fuse.glusterfs", filesystemtype)) { openlog ("mount.so", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); if (!open_target_fd(&targetfd, "/proc/1/ns/mnt")){ if (setns(targetfd, CLONE_NEWNS)){ syslog(LOG_NOTICE, "setns failed for filesystem: %s", filesystemtype); }else { syslog(LOG_NOTICE, "setns succeeded for filesystem: %s", filesystemtype); } }else { syslog(LOG_NOTICE, "failed to open ns for filesystem: %s", filesystemtype); } closelog(); } if (orig_mount) { return orig_mount(source, target, filesystemtype, mountflags, data); }else { return -ENOENT; } }
/** * This function is called whenever the tasklet wants to change its net namespace. The * caller must hold the mutex. We need to assert that... * @param[in] name * @return 0 if success * @return errno if failed */ int rwnetns_change(const char *name) { int new_netfd = 0; static int tried = 0; int ret = -1; if (!name || name[0] == 0){ return 0; } tryagain: //AKKI assert that the pthread lock has been taken. new_netfd = rwnetns_get_netfd(name); if (new_netfd > 0){ setns(new_netfd, CLONE_NEWNET); ret = 0; }else if (!tried){ RWNETNS_UNLOCK(); rwnetns_create_context(name); RWNETNS_LOCK(); tried = 1; goto tryagain; } if (new_netfd > 0){ close(new_netfd); } return ret; }
int set_netns(char *ns) { int nsfd, perm_issue; char *nspath; if (bad_nsname(ns)) { fprintf(stderr, PROGRAM ": namespace names can't contain '/', be empty, or be '.' or '..'.\n"); return 0; } if (asprintf(&nspath, "%s/%s", NS_PATH, ns) == -1) { perror(PROGRAM ": asprintf"); return 0; } if ((nsfd = open(nspath, O_RDONLY | O_CLOEXEC)) == -1) { fprintf(stderr, PROGRAM ": open(\"%s\"): %s\n", nspath, strerror(errno)); return 0; } free(nspath); if (setns(nsfd, CLONE_NEWNET) == -1) { perm_issue = errno == EPERM; perror(PROGRAM ": setns"); if (perm_issue) fprintf(stderr, "\nis the " PROGRAM " binary missing the setuid bit?\n"); return 0; } else { return 1; } }
Node * mkimplstmt(Srcloc loc, Node *name, Type *t, Type **aux, size_t naux, Node **decls, size_t ndecls) { Node *n; size_t i; n = mknode(loc, Nimpl); n->impl.traitname = name; n->impl.type = t; n->impl.aux = aux; n->impl.naux = naux; n->impl.decls = decls; n->impl.ndecls = ndecls; lappend(&impltab, &nimpltab, n); if (hasparams(t)) { n->impl.env = mkenv(); bindtype(n->impl.env, t); } for (i = 0; i < naux; i++) if (hasparams(aux[i])) bindtype(n->impl.env, aux[i]); for (i = 0; i < ndecls; i++) { if (name->name.ns) setns(decls[i]->decl.name, name->name.ns); if (decls[i]->decl.env) decls[i]->decl.env->super = n->impl.env; } return n; }
/** * This function is called whenever the tasklet wants to change its net namespace. The caller must hold the pthread mutex. We need to assert that... * @param[in] fd * @return 0 if success * @return errno if failed */ int rwnetns_change_fd(int fd) { //AKKI assert that the pthread lock has been taken. RW_ASSERT(fd > 0); setns(fd, CLONE_NEWNET); return 0; }
static ERL_NIF_TERM nif_setns(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { #ifdef HAVE_SETNS int fd; ErlNifBinary buf = {0}; int nstype = 0; int errnum = 0; if (!enif_inspect_iolist_as_binary(env, argv[0], &buf)) return enif_make_badarg(env); if (!enif_get_int(env, argv[1], &nstype)) return enif_make_badarg(env); PROCKET_REALLOC(buf, buf.size+1); buf.data[buf.size-1] = '\0'; fd = open((const char*)buf.data, O_RDONLY); /* Get descriptor for namespace */ if (fd < 0) return error_tuple(env, errno); if (setns(fd, nstype) == -1) { errnum = errno; (void)close(fd); return error_tuple(env, errnum); } (void)close(fd); return atom_ok; #else return error_tuple(env, ENOTSUP); #endif }
int virProcessSetNamespaces(size_t nfdlist, int *fdlist) { size_t i; if (nfdlist == 0) { virReportInvalidArg(nfdlist, "%s", _("Expected at least one file descriptor")); return -1; } for (i = 0; i < nfdlist; i++) { if (fdlist[i] < 0) continue; /* We get EINVAL if new NS is same as the current * NS, or if the fd namespace doesn't match the * type passed to setns()'s second param. Since we * pass 0, we know the EINVAL is harmless */ if (setns(fdlist[i], 0) < 0 && errno != EINVAL) { virReportSystemError(errno, "%s", _("Unable to join domain namespace")); return -1; } } return 0; }
int lxc_attach_to_ns(pid_t pid) { char path[MAXPATHLEN]; char *ns[] = { "pid", "mnt", "net", "ipc", "uts" }; const int size = sizeof(ns) / sizeof(char *); int fd[size]; int i; snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid); if (access(path, X_OK)) { ERROR("Does this kernel version support 'attach' ?"); return -1; } for (i = 0; i < size; i++) { snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]); fd[i] = open(path, O_RDONLY); if (fd[i] < 0) { SYSERROR("failed to open '%s'", path); return -1; } } for (i = 0; i < size; i++) { if (setns(fd[i], 0)) { SYSERROR("failed to set namespace '%s'", ns[i]); return -1; } close(fd[i]); } return 0; }
static int netns_exec(int argc, char **argv) { /* Setup the proper environment for apps that are not netns * aware, and execute a program in that environment. */ const char *name, *cmd; char net_path[MAXPATHLEN]; int netns; if (argc < 1) { fprintf(stderr, "No netns name specified\n"); return EXIT_FAILURE; } if (argc < 2) { fprintf(stderr, "No command specified\n"); return EXIT_FAILURE; } name = argv[0]; cmd = argv[1]; snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); netns = open(net_path, O_RDONLY); if (netns < 0) { fprintf(stderr, "Cannot open network namespace \"%s\": %s\n", name, strerror(errno)); return EXIT_FAILURE; } if (setns(netns, CLONE_NEWNET) < 0) { fprintf(stderr, "seting the network namespace \"%s\" failed: %s\n", name, strerror(errno)); return EXIT_FAILURE; } if (unshare(CLONE_NEWNS) < 0) { fprintf(stderr, "unshare failed: %s\n", strerror(errno)); return EXIT_FAILURE; } /* Don't let any mounts propogate back to the parent */ if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) { fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n", strerror(errno)); return EXIT_FAILURE; } /* Mount a version of /sys that describes the network namespace */ if (umount2("/sys", MNT_DETACH) < 0) { fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); return EXIT_FAILURE; } if (mount(name, "/sys", "sysfs", 0, NULL) < 0) { fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno)); return EXIT_FAILURE; } /* Setup bind mounts for config files in /etc */ bind_etc(name); if (execvp(cmd, argv + 1) < 0) fprintf(stderr, "exec of \"%s\" failed: %s\n", cmd, strerror(errno)); return EXIT_FAILURE; }
/** * This function is called to open a socket in a given namespace * @param[in] namespace name * @param[in] domain * @param[in] type * @param[in] protocol * @return fd value */ int rwnetns_socket(const char *name, int domain, int type, int proto) { int new_netfd = 0; int ret_fd = -1; int currfd = 0; int tried = 0; RWNETNS_LOCK(); currfd = rwnetns_get_current_netfd(); tryagain: if (!name || name[0] == 0){ new_netfd = 0; }else{ new_netfd = rwnetns_get_netfd(name); } if (new_netfd > 0){ setns(new_netfd, CLONE_NEWNET); ret_fd = socket(domain, type, proto); setns(currfd, CLONE_NEWNET); }else if (new_netfd < 0){ if (!tried){ RWNETNS_UNLOCK(); rwnetns_create_context(name); RWNETNS_LOCK(); tried = 1; goto tryagain; }else{ goto ret; } }else if (new_netfd == 0){ ret_fd = socket(domain, type, proto); } ret: if (currfd > 0){ close(currfd); } if (new_netfd > 0){ close(new_netfd); } RWNETNS_UNLOCK(); return ret_fd; }
/** * This function is called to open a socket in a given namespace * @param[in] namespace name * @param[in] domain * @param[in] type * @param[in] protocol * @return fd value */ int rwnetns_open(const char *name, char *pathname, int flags) { int new_netfd = 0; int ret_fd = -1; int currfd = 0; static int tried = 0; RWNETNS_LOCK(); currfd = rwnetns_get_current_netfd(); tryagain: if (!name || name[0] == 0){ new_netfd = 0; }else{ new_netfd = rwnetns_get_netfd(name); } if (new_netfd > 0){ setns(new_netfd, CLONE_NEWNET); ret_fd = open(pathname, flags); setns(currfd, CLONE_NEWNET); }else if (new_netfd < 0){ if (!tried){ RWNETNS_UNLOCK(); rwnetns_create_context(name); RWNETNS_LOCK(); tried = 1; goto tryagain; }else{ goto ret; } }else if (new_netfd == 0){ ret_fd = open(pathname, flags); } ret: if (currfd > 0){ close(currfd); } if (new_netfd > 0){ close(new_netfd); } RWNETNS_UNLOCK(); return ret_fd; }
static int lxc_attach_to_ns(pid_t pid, int which) { int fd[LXC_NS_MAX]; int i, j, saved_errno; if (access("/proc/self/ns", X_OK)) { ERROR("Does this kernel version support namespaces?"); return -1; } for (i = 0; i < LXC_NS_MAX; i++) { /* Ignore if we are not supposed to attach to that namespace. */ if (which != -1 && !(which & ns_info[i].clone_flag)) { fd[i] = -1; continue; } fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name); if (fd[i] < 0) { saved_errno = errno; /* Close all already opened file descriptors before we * return an error, so we don't leak them. */ for (j = 0; j < i; j++) close(fd[j]); errno = saved_errno; SYSERROR("Failed to open namespace: \"%s\".", ns_info[i].proc_name); return -1; } } for (i = 0; i < LXC_NS_MAX; i++) { if (fd[i] < 0) continue; if (setns(fd[i], 0) < 0) { saved_errno = errno; for (j = i; j < LXC_NS_MAX; j++) close(fd[j]); errno = saved_errno; SYSERROR("Failed to attach to namespace \"%s\".", ns_info[i].proc_name); return -1; } DEBUG("Attached to namespace \"%s\".", ns_info[i].proc_name); close(fd[i]); } return 0; }
/* * This routine is to create PF_UNIX/SOCK_SEQPACKET socket * in the target net namespace */ static int make_sock_for(int pid) { int ret, mfd, fd, sk = -1; char p[32]; pr_debug("Preparing seqsk for %d\n", pid); sprintf(p, "/proc/%d/ns/net", pid); fd = open(p, O_RDONLY); if (fd < 0) { pr_perror("Can't open %p", p); goto out; } mfd = open("/proc/self/ns/net", O_RDONLY); if (mfd < 0) { pr_perror("Can't open self netns"); goto out_c; } if (setns(fd, CLONE_NEWNET)) { pr_perror("Can't setup target netns"); goto out_cm; } sk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); if (sk < 0) pr_perror("Can't create seqsk"); ret = setns(mfd, CLONE_NEWNET); if (ret) { pr_perror("Can't restore former netns"); if (sk >= 0) close(sk); sk = -1; } out_cm: close(mfd); out_c: close(fd); out: return sk; }
static int child(void *arg) { int fd; fd = open((char *) arg, O_RDONLY); setns(fd, 0); execlp("bash", "bash", (char *) NULL); return 0; }
static int netns_change(const char *nsname, int fd_global_netns) { /* If you need to change current netns to global netns: * set the first argument "NULL", the second argument * is file descriptor of global netns (it must be saved * before first call of this function) * If you need to change current netns to another netns: * set the first argument as netns which you need, * the second argument may be any */ char netns_path[MAXPATHLEN]; int fd; /* Join to global network namespace * if (network namespace "nsname" == NULL && * file descriptor of global network namespace * "fd_global_netns" >-1) * else exit function with error -1 * if (file descriptor of global network namespace * "fd_global_netns" < 0) */ if (nsname == NULL) { fprintf(stdout,"*** fd_global_netns is:%d\n",fd_global_netns); if (setns(fd_global_netns, CLONE_NEWNET) == -1) { fprintf(stderr, "*** Failed to set a global network namespace : %s\n", strerror(errno)); return -2; } return 0; } /* Get path for network namespace "nsname" */ snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname); /* Create the base netns directory if it doesn't exist */ mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); /* Create the filesystem state */ fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0); if (fd < 0) { fprintf(stderr, "*** Cannot create namespace file \"%s\": %s\n", netns_path, strerror(errno)); return -1; } close(fd); /* Join to network namespace "nsname" */ if (unshare(CLONE_NEWNET) < 0) { fprintf(stderr, "*** Failed to create a new network namespace \"%s\": %s\n", nsname, strerror(errno)); return -1; } return 0; }
static int netns_exec(int argc, char **argv) { /* Setup the proper environment for apps that are not netns * aware, and execute a program in that environment. */ const char *name, *cmd; char net_path[MAXPATHLEN]; int netns; if (argc < 1) { fprintf(stderr, "No netns name specified\n"); return -1; } if (argc < 2) { fprintf(stderr, "No cmd specified\n"); return -1; } name = argv[0]; cmd = argv[1]; snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); netns = open(net_path, O_RDONLY); if (netns < 0) { fprintf(stderr, "Cannot open network namespace: %s\n", strerror(errno)); return -1; } if (setns(netns, CLONE_NEWNET) < 0) { fprintf(stderr, "seting the network namespace failed: %s\n", strerror(errno)); return -1; } /* if (unshare(CLONE_NEWNS) < 0) { fprintf(stderr, "unshare failed: %s\n", strerror(errno)); return -1; } */ /* Mount a version of /sys that describes the network namespace */ if (umount2("/sys", MNT_DETACH) < 0) { fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); return -1; } if (mount(name, "/sys", "sysfs", 0, NULL) < 0) { fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno)); return -1; } /* Setup bind mounts for config files in /etc */ bind_etc(name); if (execvp(cmd, argv + 1) < 0) fprintf(stderr, "exec of %s failed: %s\n", cmd, strerror(errno)); exit(-1); }
void sc_reassociate_with_pid1_mount_ns(void) { int init_mnt_fd SC_CLEANUP(sc_cleanup_close) = -1; int self_mnt_fd SC_CLEANUP(sc_cleanup_close) = -1; debug("checking if the current process shares mount namespace" " with the init process"); init_mnt_fd = open("/proc/1/ns/mnt", O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_PATH); if (init_mnt_fd < 0) { die("cannot open mount namespace of the init process (O_PATH)"); } self_mnt_fd = open("/proc/self/ns/mnt", O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_PATH); if (self_mnt_fd < 0) { die("cannot open mount namespace of the current process (O_PATH)"); } char init_buf[128] = { 0 }; char self_buf[128] = { 0 }; memset(init_buf, 0, sizeof init_buf); if (readlinkat(init_mnt_fd, "", init_buf, sizeof init_buf) < 0) { if (errno == ENOENT) { // According to namespaces(7) on a pre 3.8 kernel the namespace // files are hardlinks, not sylinks. If that happens readlinkat // fails with ENOENT. As a quick workaround for this special-case // functionality, just bail out and do nothing without raising an // error. return; } die("cannot perform readlinkat() on the mount namespace file " "descriptor of the init process"); } memset(self_buf, 0, sizeof self_buf); if (readlinkat(self_mnt_fd, "", self_buf, sizeof self_buf) < 0) { die("cannot perform readlinkat() on the mount namespace file " "descriptor of the current process"); } if (memcmp(init_buf, self_buf, sizeof init_buf) != 0) { debug("the current process does not share mount namespace with " "the init process, re-association required"); // NOTE: we cannot use O_NOFOLLOW here because that file will always be a // symbolic link. We actually want to open it this way. int init_mnt_fd_real SC_CLEANUP(sc_cleanup_close) = -1; init_mnt_fd_real = open("/proc/1/ns/mnt", O_RDONLY | O_CLOEXEC); if (init_mnt_fd_real < 0) { die("cannot open mount namespace of the init process"); } if (setns(init_mnt_fd_real, CLONE_NEWNS) < 0) { die("cannot re-associate the mount namespace with the init process"); } } else { debug("re-associating is not required"); } }
int restore_ns(int rst, struct ns_desc *nd) { int ret; ret = setns(rst, nd->cflag); if (ret < 0) pr_perror("Can't restore ns back"); close(rst); return ret; }
/* Attach to the specified namespace FD path */ int attachToNS(char *path) { int nsid; nsid = open(path, O_RDONLY); if (nsid < 0) { perror(path); return 1; } if (setns(nsid, 0) != 0) { perror("setns"); return 1; } return 0; }
static int _setns (NMPNetns *self, int type) { char buf[100]; int fd; NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE (self); nm_assert (NM_IN_SET (type, _CLONE_NS_ALL_V)); fd = (type == CLONE_NEWNET) ? priv->fd_net : priv->fd_mnt; _LOGt (self, "set netns(%s, %d)", _ns_types_to_str (type, 0, buf), fd); return setns (fd, type); }
static PyObject * _setns(PyObject *self, PyObject *args) { int fd, nstype; if (!PyArg_ParseTuple(args, "ii", &fd, &nstype)) return NULL; if (setns(fd, nstype) == -1) { PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; } else { Py_INCREF(Py_None); return Py_None; } }
static int attach_ns(const int ns_fd[LXC_NS_MAX]) { int i; for (i = 0; i < LXC_NS_MAX; i++) { if (ns_fd[i] < 0) continue; if (setns(ns_fd[i], 0) != 0) goto error; } return 0; error: SYSERROR("failed to set namespace '%s'", ns_info[i].proc_name); return -1; }
int main(int argc, char *argv[]) { int fd; struct utsname uts; if (argc < 2) return 1; fd = open(argv[1], O_RDONLY); setns(fd, 0); uname(&uts); printf("hostname of this (%ld): %s\n", (long) getpid(), uts.nodename); return 0; }
void nsinfo__mountns_exit(struct nscookie *nc) { if (nc == NULL || nc->oldns == -1 || nc->newns == -1) return; setns(nc->oldns, CLONE_NEWNS); if (nc->oldns > -1) { close(nc->oldns); nc->oldns = -1; } if (nc->newns > -1) { close(nc->newns); nc->newns = -1; } }
int netns_switch(char *name) { char net_path[MAXPATHLEN]; int netns; snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); netns = open(net_path, O_RDONLY | O_CLOEXEC); if (netns < 0) { fprintf(stderr, "Cannot open network namespace \"%s\": %s\n", name, strerror(errno)); return -1; } if (setns(netns, CLONE_NEWNET) < 0) { fprintf(stderr, "setting the network namespace \"%s\" failed: %s\n", name, strerror(errno)); return -1; } if (unshare(CLONE_NEWNS) < 0) { fprintf(stderr, "unshare failed: %s\n", strerror(errno)); return -1; } /* Don't let any mounts propagate back to the parent */ if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) { fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n", strerror(errno)); return -1; } /* Mount a version of /sys that describes the network namespace */ if (umount2("/sys", MNT_DETACH) < 0) { fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); return -1; } if (mount(name, "/sys", "sysfs", 0, NULL) < 0) { fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno)); return -1; } /* Setup bind mounts for config files in /etc */ bind_etc(name); return 0; }
int main(int argc, char *argv[]) { int fd; if (argc == 2 && strncmp(argv[1], "-V", 3) == 0) { printf("%s\n", VERSION); exit(0); } if (argc < 3) { fprintf(stderr, "%s <mount_namespace_fd> <-m|-u> <mount_args>\n", argv[0]); exit(-1); } fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open mount namespace fd failed"); exit(-1); } if (setns(fd, 0) != 0) { perror("failed to switch namespace"); exit(-1); } if (strncmp(argv[2], "-m", 2) == 0) { argv[2] = "mount"; if (execvp("mount", &argv[2]) != 0) { perror("mount failed"); exit(-1); } } else if (strncmp(argv[2], "-u", 2) == 0) { argv[2] = "umount"; if (execvp("umount", &argv[2]) != 0) { perror("umount failed"); exit(-1); } } else { fprintf(stderr, "unrecognize parameter!"); exit(-1); } }
int procket_open_ns(PROCKET_STATE *ps) { #ifdef HAVE_SETNS int fd = 0; if (ps->ns == NULL) return 0; fd = open(ps->ns, O_RDONLY); if (fd < 0) return -1; if (setns(fd, 0 /* join all namespaces */) < 0) return -1; #endif return 0; }
int main(int argc, char *argv[]) { int ret, targetfd; char ns[PATH_MAX]; if (argc <= 3) error (EXIT_FAILURE, 0, "Not enough params"); sprintf (ns, "/proc/%s/ns/mnt", argv[1]); targetfd = open (ns, O_RDONLY); if (setns (targetfd, CLONE_NEWNS)) error (EXIT_FAILURE, errno, "setns"); umount2 (argv[3], MNT_DETACH); ret = mount (argv[2], argv[3], NULL, MS_MGC_VAL | MS_BIND | MS_REC, NULL); if (ret < 0) error (EXIT_FAILURE, errno, "mount"); return 0; }
void *thread_run(void *arg) { block_t *block = (block_t*) arg; int fd = open(block->path, O_RDONLY); if (fd < 0) { perror("open"); return 0; } if (setns(fd, 0) < 0) { perror("setns"); close(fd); return 0; } block->fd = tun_open(block->device); close(fd); return 0; }
static int enter_ns(pid_t pid, const char *ns_str, int nstype) { char *nsfile; int fd; if (asprintf(&nsfile, "/proc/%d/ns/%s", pid, ns_str) < 0) die("can't allocate memory\n"); fd = open(nsfile, O_RDONLY); free(nsfile); if (fd < 0) return -1; if (setns(fd, nstype) < 0) { close(fd); return -1; } close(fd); return 0; }