diff --git a/Makefile b/Makefile index 5c4dc86..ea79beb 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ MOUNTNS := mountns UTILS := utils MOUNTNS := mountns PIDNS := pidns +NETNS := networkns # Directories SRCDIR :=src @@ -23,7 +24,7 @@ ROOTFSDIR := rootfs CFLAGS := -Wall -Wextra -Werror=format-security -grecord-gcc-switches -fstack-clash-protection -pipe -g -O2 -D_GNU_SOURCE #Defauilt Make -all: rootfs utils pidns mountns mountns userns $(TARGET) +all: rootfs utils pidns mountns mountns userns networkns $(TARGET) rootfs: @$(RM) -rf $(ROOTFSIMAGE) $(ROOTFSDIR) @@ -55,14 +56,15 @@ userns: $(SRCDIR)/$(USERNS).c @echo "[+] Compiling User Namespace Program" $(CC) $(CFLAGS) -I ${INCDIR} -c -o $(OBJDIR)/$(USERNS).o $(SRCDIR)/$(USERNS).c +networkns: $(SRCDIR)/$(NETNS).c + @mkdir -p $(OBJDIR) + @echo "[+] Compiling Network Namespace Program" + $(CC) $(CFLAGS) -I ${INCDIR} -c -o $(OBJDIR)/$(NETNS).o $(SRCDIR)/$(NETNS).c -lnetlink $(TARGET): $(SRCDIR)/$(TARGET).c $(OBJDIR)/$(USERNS).o $(OBJDIR)/$(MOUNTNS).o $(OBJDIR)/$(UTILS).o @echo "[+] Compiling" $(CC) $(CFLAGS) -I ${INCDIR} -c -o $(OBJDIR)/$(TARGET).o $(SRCDIR)/$(TARGET).c - $(CC) $(CFLAGS) $(OBJDIR)/$(USERNS).o $(OBJDIR)/$(MOUNTNS).o $(OBJDIR)/$(TARGET).o $(OBJDIR)/$(UTILS).o $(OBJDIR)/$(PIDNS).o -o $(TARGET) - - - + $(CC) $(CFLAGS) $(OBJDIR)/$(USERNS).o $(OBJDIR)/$(MOUNTNS).o $(OBJDIR)/$(TARGET).o $(OBJDIR)/$(UTILS).o $(OBJDIR)/$(PIDNS).o $(OBJDIR)/$(NETNS).o -o $(TARGET) #Non-File Targets .PHONY: clean rootfs diff --git a/include/networkns.h b/include/networkns.h index 0778991..5432e46 100644 --- a/include/networkns.h +++ b/include/networkns.h @@ -1,172 +1,22 @@ -/* The Holy Bible which helped me through this: -https://maz-programmersdiary.blogspot.com/2011/09/netlink-sockets.html - -God protect the precious soul who wrote this -*/ -#include -#include -#include -#include -#include -#include -#include -#include +#ifndef __NETWORK_NS +#define __NETWORK_NS #include "utils.h" // Netlink Message Payload #define MAX_PAYLOAD 1024 - -/* -Struct referencing the Netlink message -See https://github.com/shemminger/iproute2/blob/main/ip/ip_common.h -*/ -struct iplink_req{ - // See:https://datatracker.ietf.org/doc/html/rfc3549#section-2.3.2 - struct nlmsghdr n; // Netlink message header - // See https://elixir.bootlin.com/linux/v4.9/source/include/uapi/linux/rtnetlink.h#L481 - struct ifinfomsg i; - char buf[MAX_PAYLOAD]; -}; - -// Check response from Kernel -void check_response(int sock_fd){ - struct iovec iov; - struct msghdr msg = { - .msg_name = NULL, - .msg_namelen = 0, - .msg_iov = &iov, - .msg_iovlen = 1 - }; - -} - - -// send Netlink message -static void send_nlmsg(int sock_fd, struct nlmsghdr *n){ - struct iovec iov = { - .iov_base = n, /* Starting address */ - .iov_len = n->nlmsg_len /* Starting address */ - }; - - struct msghdr msg = { - .msg_name = NULL, - .msg_namelen = 0, - .msg_iov = &iov, - .msg_iovlen = 1 - }; - - n->nlmsg_seq++; - - if (sendmsg(sock_fd, &msg, 0) < 0){ - exit_on_error("[-] Netlink Request Failed"); - } - - check_response(sock_fd); -} - -// Create veth device -static int create_veth(int sock_fd, char *ifname, char *peername){ - /* Taken from source code of ip command - See Link 1060: https://github.com/shemminger/iproute2/blob/main/ip/iplink.c - */ - struct iplink_req req = { - /* From netlink(3) - NLMSG_LENGTH() - Given the payload length, len, this macro returns the aligned length to store - in the nlmsg_len field of the nlmsghdr. - */ - - .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), - /* From netlink(7) - NLM_F_REQUEST: Must be set on all request messages - NLM_F_ACK: Request for an acknowledgement on success. - NLM_F_CREATE: Create new device if it doesn't already exist - NLM_F_EXCL: Don't replace if the object already exists - */ - .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL, - /* From rtnetlink(7) - RTM_NEWLINK: Create a specific network interface. - */ - .n.nlmsg_type = RTM_NEWLINK, - - // Set socket type to Netlink - .i.ifi_family = PF_NETLINK, - }; - - - struct nlmsghdr *n = &req.n; - int maxlen = sizeof(req); - - /* From libnetlink(3): - int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) - Add a variable length attribute of type type and with value data and alen length to netlink message n, - which is part of a buffer of length maxlen. data is copied. - - From https://www.infradead.org/~tgr/libnl/doc/route.html: - IFLA_IFNAME: Used to add link name attribute - */ - if (addattr_l(n, maxlen, IFLA_IFNAME, ifname, strlen(ifname)+1) <0){ - exit_on_error("Could Not Setup veth pair"); - } - - /* Create a network bridge - Add Attribute - See: https://unix.stackexchange.com/questions/441877/identify-if-a-network-interface-is-a-veth-using-sys-class-net - Also, I highly recommend refering to the Bible mentioned at the start of this code for the upcoming sections - */ - struct rtattr *linkinfo; - struct rtattr *linkdata; - struct rtattr *peerinfo; - linkinfo = addattr_nest(n, maxlen, IFLA_LINKINFO); - - // Specify a veth type device - if (addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, DEVICETYPE, strlen(DEVICETYPE)+1) < 0 ){ - addattr_nest_end(n, linkinfo); - exit_on_error("[-] Could not create veth device :("); - } - - // Add another nested attribute data - linkdata = addattr_nest(n, maxlen, IFLA_INFO_DATA); - - // Add nested attribute containing peer name - peerinfo = addattr_nest(n, maxlen, VETH_INFO_PEER); - n->nlmsg_len += sizeof(struct ifinfomsg); - - if (addattr_l(n, maxlen, IFLA_IFNAME, peername, strlen(peername) + 1)<0){ - addattr_nest_end(n, linkdata); - exit_on_error("[-] Could not add peer"); - } - - // End attributes - addattr_nest_end(n, peerinfo); - addattr_nest_end(n, linkdata); - addattr_nest_end(n, linkinfo); - - // Send message - send_nlmsg(sock_fd, n); - return 0; -} - -// Prepare Network Namespace -static int prepare_network_ns(){ - /* - PF_NETLINK: Netlink socket - SOCK_RAW: Raw Socket, requires sudo privileges - SOCK_CLOEXEC: Avoids a race condition between getting a new socket from accept and setting the FD_CLOEXEC flag afterwards. - NETLINK_ROUTE: Communication channel between user-space routing dæmon and kernel packet forwarding module. - - PS: PF_NETLINK and AF_NETLINK point to the same value as can be seen in socket.h: - #define PF_NETLINK AF_NETLINK - */ - int s = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); - if(s < 0){ - exit_on_error("Failed to create Netlink socket"); - } - - if (create_veth(s, VETH0, VETH1)!= 0){ - exit_on_error("Could not create interface pair"); - } - - return 0; -} +#define VETH0 "veth0" // The interface facing the root namespace +#define VETH1 "veth1" // The interface facing the network namespace +#define IP0 "10.1.1.1" // IP address associated with VETH0 +#define IP1 "10.1.1.2" // IP address associated with VETH1 +#define NETMASK "255.255.255.0" // Netmask of our virtual network +#define DEVICETYPE "veth" + +int check_response(int sock_fd); +int send_nlmsg(int sock_fd, struct nlmsghdr *n); +int create_veth(int sock_fd, char *ifname, char *peername); +int interface_up(char *ifname, char *ip, char *netmask); +int ns_fd(int pid); +int move_interface_to_ns(int sock_fd, char *ifname, int netns); +int prepare_networkns(int child_pid); +#endif \ No newline at end of file diff --git a/include/userns.h b/include/userns.h index dc1aa1d..cf5b8e4 100644 --- a/include/userns.h +++ b/include/userns.h @@ -1,5 +1,6 @@ #pragma once -#ifndef __PREPARE_USER_NS +#ifndef __USER_NS +#define __USER_NS #include #include #include @@ -7,6 +8,6 @@ #include "utils.h" -int prepare_user_ns(int pid); +int prepare_userns(int pid); #endif \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index c7683d2..77e8c15 100644 --- a/include/utils.h +++ b/include/utils.h @@ -14,14 +14,6 @@ #define MAGENTA(string) "\x1b[35m" string "\x1b[0m" #define CYAN(string) "\x1b[36m" string "\x1b[0m" -#define UID 1000 -#define VETH0 "veth0" // The interface facing the root namespace -#define VETH1 "veth1" // The interface facing the network namespace -#define IP_0 "10.1.1.1" // IP address associated with VETH0 -#define IP_1 "10.1.1.2" // IP address associated with VETH1 -#define NETMASK "255.255.255.0" // Netmask of our virtual network -#define DEVICETYPE "veth" - void exit_on_error(const char *format, ...); #endif \ No newline at end of file diff --git a/src/isolate.c b/src/isolate.c index 9d84077..bd6dcdd 100644 --- a/src/isolate.c +++ b/src/isolate.c @@ -14,7 +14,7 @@ #include "utils.h" #include "mountns.h" #include "userns.h" -//#include "networkns.h" +#include "networkns.h" // Flags used in name space creation @@ -67,6 +67,7 @@ int cmd_exec(void *arg){ return -1; } + // Prepare MOUNT namespace if (prepare_mountns() != 0){ fprintf(stderr,"[" RED("!") "] Failed to create "RED("Mount") "namespace\n"); return -1; @@ -159,15 +160,20 @@ int main(int argc, char* argv[]){ free(stack); exit_on_error("[" RED("!") "] The function " RED("clone()") " failed\n"); } - fprintf(stdout,"[" GREEN("i") "] Successfully created " GREEN("Hostname") " namespace\n"); + fprintf(stdout,"[" GREEN("i") "] Successfully created " GREEN("UTS") " namespace\n"); - // Prepare User Namespace - if (prepare_user_ns(cmd_pid) != 0){ + // Prepare USER Namespace + if (prepare_userns(cmd_pid) != 0){ exit_on_error("[" RED("!") "] Failed to create " RED("User") " namespace\n"); } fprintf(stdout,"[" GREEN("i") "] Successfully created " GREEN("User") " namespace\n"); + // Prepare Network Namespace + if (prepare_networkns(cmd_pid) != 0){ + exit_on_error("[" RED("!") "] Failed to create " RED("Network") " namespace\n"); + } + fprintf(stdout,"[" GREEN("i") "] Successfully created " GREEN("Network") " namespace\n"); // Send 'setup done' signal to Child process if (write(cli_params.fd[1],"OK",2)!=2){ diff --git a/src/networkns.c b/src/networkns.c new file mode 100644 index 0000000..921d5db --- /dev/null +++ b/src/networkns.c @@ -0,0 +1,407 @@ +/* The Holy Bible which helped me through this: +https://maz-programmersdiary.blogspot.com/2011/09/netlink-sockets.html + +God protect the precious soul who wrote this +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "networkns.h" + + +/* +Struct representing the Netlink message taken from: +Line 111: https://github.com/shemminger/iproute2/blob/main/ip/ip_common.h (Commit: 7ca868a) + +Link Message Format: https://www.infradead.org/~tgr/libnl/doc/route.html#_netlink_protocol +Netlink Message Header Format: https://datatracker.ietf.org/doc/html/rfc3549#section-2.3.2 +Struct ifinfomsg definition: https://elixir.bootlin.com/linux/v4.9/source/include/uapi/linux/rtnetlink.h#L481 +*/ +struct iplink_req{ + struct nlmsghdr n; // Netlink message header + struct ifinfomsg i; // Request family specific Link header + char buf[MAX_PAYLOAD]; +}; + + +// Check netlink message response from kernel +int check_response(int sock_fd){ + struct iovec iov; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = &iov, + .msg_iovlen = 1 + }; + + char *resp; + resp = (char *)malloc(MAX_PAYLOAD); + if (resp == NULL){ + fprintf(stderr, "[" RED("!") "] Out of memory\n"); + return -1; + } + + // Check response + struct iovec *resp_iov = msg->msg_iov; + resp_iov->iov_base = &resp; + resp_iov->iov_len = MAX_PAYLOAD; + + recv_reply: + ssize_t resp_len = recvmsg(fd, msg, 0); + if (resp_len == 0 || resp_len < 0 ){ + if(errno==EINTR){ + goto recv_reply; + } + else{ + fprintf(stderr, "[" RED("!") "] Error occured while receiving "RED("Netlink")" message\n"); + return -1; + } + } + + + // Cast pointer to nlmsghdr type + struct nlmsghdr *hdr = (struct nlmsghdr *)resp; + int nlmsglen = hdr->nlmsg_len; + int datalen = nlmsglen - sizeof(struct nlmsghdr); // Get data length + + if(datalen < 0 || nlmsglen > resp_len){ + if(msg.msg_flags == MSG_TRUNC ){ + fprintf(stderr, "[" RED("!") "] Received truncated "RED("Netlink")" message\n"); + return -1; + } + fprintf(stderr, "[" RED("!") "] Received malformed "RED("Netlink")" message\n"); + } + + + // Check for error message + if (hdr->nlmsg_flags == NLMSG_ERROR){ + // See netlink (7) + struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(hdr); + if(datalen < sizeof(struct nlmsgerr)){ + fprintf(stderr, "[" RED("!") "] Received malformed "RED("Netlink")" message\n"); + return -1; + } + if (err->error){ + fprintf(stderr, "[" RED("!") "] Received error code: %d\n", err->error); + return -1; + } + } + free(resp); + return 0; +} + + +// Send Netlink message +int send_nlmsg(int sock_fd, struct nlmsghdr *n){ + // See EXAMPLES from man netlink(7) + // See: https://bit.ly/3oBuYAM + struct iovec iov = { + .iov_base = n, /* Starting address */ + .iov_len = n->nlmsg_len /* Starting address */ + }; + + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = &iov, + .msg_iovlen = 1 + }; + + n->nlmsg_pid = 0; + n->nlmsg_seq++; + + if (sendmsg(sock_fd, &msg, 0) < 0){ + fprintf(stderr,"[" RED("!") "] Failed to send "RED("Netlink") "message\n"); + return -1; + } + + return 0; +} + + +// Create veth pair +int create_veth(int sock_fd, char *ifname, char *peername){ + // For reference, see: https://github.com/shemminger/iproute2/blob/main/ip/iplink.c + struct iplink_req req = { + /* From netlink(3) + NLMSG_LENGTH() + Given the payload length, len, this macro returns the aligned length to store + in the nlmsg_len field of the nlmsghdr. + */ + + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), + /* From netlink(7) + NLM_F_REQUEST: Must be set on all request messages + NLM_F_ACK: Request for an acknowledgement on success. + NLM_F_CREATE: Create new device if it doesn't already exist + NLM_F_EXCL: Don't replace if the object already exists + */ + .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL, + /* From rtnetlink(7) + RTM_NEWLINK: Create a specific network interface. + */ + .n.nlmsg_type = RTM_NEWLINK, + + // Set socket type to Netlink + .i.ifi_family = PF_NETLINK, + }; + + + // Adding Attributes to our Netlink message + struct nlmsghdr *n = &req.n; + int maxlen = sizeof(req); + + /* From libnetlink(3): + int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) + Add a variable length attribute of type type and with value data and alen length to netlink message n, + which is part of a buffer of length maxlen. data is copied. + + From https://www.infradead.org/~tgr/libnl/doc/route.html: + IFLA_IFNAME: Used to add link name attribute + */ + if (addattr_l(n, maxlen, IFLA_IFNAME, ifname, strlen(ifname)+1) <0){ + fprintf(stderr,"[" RED("!") "] Failed to set interface name attribut\n"); + return -1; + } + + /* Create a network bridge + Add Attribute + See: https://unix.stackexchange.com/questions/441877/identify-if-a-network-interface-is-a-veth-using-sys-class-net + Also, I highly recommend refering to the Bible mentioned at the start of this code for the upcoming sections + */ + struct rtattr *linkinfo; + struct rtattr *linkdata; + struct rtattr *peerinfo; + + if(memset(&linkinfo,0,sizeof(rtattr)) == NULL || memset(&linkdata,0,sizeof(rtattr)) == NULL || memset(&peerinfo,0,sizeof(rtattr)) == NULL ){ + fprintf(stderr,"[" RED("-") "] The function " RED("memset()") " failed\n"); + return -1; + } + + linkinfo = addattr_nest(n, maxlen, IFLA_LINKINFO); // Nested attribute to contain veth info + + // Specify a 'veth' type interface + if (addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, DEVICETYPE, strlen(DEVICETYPE)) < 0 ){ + addattr_nest_end(n, linkinfo); + fprintf(stderr,"[" RED("-") "] Could not create "RED("'veth'")" device\n"); + return -1; + } + + // Add another nested attribute data + linkdata = addattr_nest(n, maxlen, IFLA_INFO_DATA); + + // Add nested attribute containing peer name + peerinfo = addattr_nest(n, maxlen, VETH_INFO_PEER); + n->nlmsg_len += sizeof(struct ifinfomsg); + + if (addattr_l(n, maxlen, IFLA_IFNAME, peername, strlen(peername) + 1)<0){ + addattr_nest_end(n, linkinfo); + addattr_nest_end(n, linkdata); + fprintf(stderr,"[" RED("-") "] Could not add peername attribute\n"); + return -1; + } + + // End attributes + addattr_nest_end(n, peerinfo); + addattr_nest_end(n, linkdata); + addattr_nest_end(n, linkinfo); + + // Send message + if (send_nlmsg(sock_fd, n) != 0){ + fprintf(stderr,"[" RED("-") "] Failed to send "RED("Netlink Message")"\n"); + return -1; + } + + // Check Response + if (check_response(sock_fd) != 0){ + fprintf(stderr, "[" RED("!") "] Error occured while fetching netlink response"); + return -1; + } + + return 0; +} + + +// Bring up interface +int interface_up(char *ifname, char *ip, char *netmask){ + // See: https://stackoverflow.com/questions/5858655/linux-programmatically-up-down-an-interface-kernel/5859449 + int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP ); + if(s < 0){ + fprintf(stderr, "["RED("!")"] Failed to create SOCK_DGRAM socket\n"); + return -1; + } + + // man netdevice(7) + struct ifreq ifr; + if( memset(&ifr, 0, sizeof(struct ifreq)) == NULL){ + fprintf(stderr,"[" RED("-") "] The function " RED("memset()") " failed\n"); + return -1; + } + + // Copy interface name + strncpy(ifr.ifr_name, ifname, strlen(ifname)); + + struct sockaddr_in saddr; + if(memset(&saddr, 0, sizeof(struct sockaddr_in)) == NULL){ + fprintf(stderr,"[" RED("-") "] The function " RED("memset()") " failed\n"); + return -1; + } + saddr.sin_family = AF_INET; + saddr.sin_port = 0; + char *p = (char *)&saddr; + + // From man netdevice(7) + // Set IP address of the interface + saddr.sin_addr.s_addr = inet_addr(ip); + memcpy((char *)&(ifr.ifr_addr), p, sizeof(struct sockaddr)); + if(ioctl(s, SIOCSIFADDR, &ifr) < 0){ + fprintf(stderr, "["RED("!")"] Failed to set up Interface: %s with IP: %s "RED("ioctl()")" call\n", ifname, ip); + return -1; + } + + // Set Netmask of the interface + saddr.sin_addr.s_addr = inet_addr(netmask); + memcpy((char *)&(ifr.ifr_addr), p, sizeof(struct sockaddr)); + if(ioctl(s, SIOCSIFNETMASK, &ifr) < 0){ + fprintf(stderr, "["RED("!")"] Failed to set up Interface: %s with Netmask: %s "RED("ioctl()")" call\n", ifname, netmask); + return -1; + } + + // Set interface flags + ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST; + if(ioctl(s, SIOCSIFFLAGS, &ifr) <0 ){ + fprintf(stderr, "["RED("!")"] Failed to set interface flags for %s with "RED("ioctl()")" call\n", ifname); + return -1; + } + + if(close(s) < 0){ + fprintf(stderr, "["RED("!")" Failed to close socket\n"); + return -1; + } + + return 0; +} + + +// Get a file descriptor inside a namespace +int ns_fd(int pid){ + char *path; + if(asprintf(&path, "/proc/%d/ns/net", pid) < 0){ + fprintf(stderr, "["RED("!") "] Out of memory\n"); + return -1; + } + + int fd = open(path, O_RDONLY); + if(fd < 0){ + fprintf(stderr, "["RED("!") "] Could not open "RED("/proc/%d/ns/net")" for reading\n", pid); + return -1; + } + + free(path); + return fd; +} + + +// Move interface to namespace +int move_interface_to_ns(int sock_fd, char *ifname, int netns){ + // send interface to namespace + struct iplink_req req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), + .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .n.nlmsg_type = RTM_NEWLINK, + .i.ifi_family = PF_NETLINK, + }; + + // See: https://pyroute2.org/pyroute2-0.3.9alpha1/netns.html + addattr_l(&req.n, sizeof(req), IFLA_NET_NS_FD, &netns, 4); + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, ifname, strlen(ifname)); + + // Send message + if (send_nlmsg(sock_fd, n) != 0){ + fprintf(stderr,"[" RED("-") "] Failed to send "RED("Netlink Message")"\n"); + return -1; + } + + // Check Response + if (check_response(sock_fd) != 0){ + fprintf(stderr, "[" RED("!") "] Error occured while fetching netlink response"); + return -1; + } + + return 0; +} + +// Prepare Network Namespace +int prepare_networkns(int child_pid){ + /* + PF_NETLINK: Netlink socket + SOCK_RAW: Raw Socket, requires sudo privileges + SOCK_CLOEXEC: Avoids a race condition between getting a new socket from accept and setting the FD_CLOEXEC flag afterwards. + NETLINK_ROUTE: Communication channel between user-space routing dæmon and kernel packet forwarding module. + + PS: PF_NETLINK and AF_NETLINK point to the same value as can be seen in socket.h: + #define PF_NETLINK AF_NETLINK + */ + int s = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); + if(s < 0){ + fprintf(stderr, "["RED("!")"] Failed to create" RED("Netlink") " socket\n"); + return -1; + } + + // Create veth pair using netlink messages to the kernel + if (create_veth(s, VETH0, VETH1)!= 0){ + fprintf(stderr, "[" RED("!")"] Could not create "RED("veth")" pair"); + return -1; + } + + // Set veth0 up with given ip and netmask + if(interface_up(VETH0, IP0, NETMASK) < 0){ + fprintf(stderr, "["RED("!")"] Could not setup %s interface\n", VETH0); + return -1; + } + + int host_fd = ns_fd(getpid()); + int child_fd = ns_fd(child_pid); + + // Move VETH1 to child namespace + if(move_interface_to_ns(sock_fd, VETH1, child_fd) < 0){ + fprintf(stderr,"["RED("!")"] Failed to move %s to child namespace\n", VETH1); + return -1; + } + + // See man setns(2) + if (setns(child_fd, CLONE_NEWNET) < 0){ + fprintf(stderr,"["RED("!")"] Failed to move thread to child namespace\n", VETH1); + return -1; + } + + // Set veth1 up with given ip and netmask + if(interface_up(VETH1, IP1, NETMASK) < 0){ + fprintf(stderr, "["RED("!")"] Could not setup %s interface\n", VETH1); + return -1; + } + + // See man setns(2) + if (setns(host_fd, CLONE_NEWNET) < 0){ + fprintf(stderr,"["RED("!")"] Failed to move thread back to host namespace\n", VETH1); + return -1; + } + + close(s); + close(child_fd); + close(host_fd); + return 0; +} diff --git a/src/userns.c b/src/userns.c index 62579e1..16c7855 100644 --- a/src/userns.c +++ b/src/userns.c @@ -4,6 +4,9 @@ #include #include "userns.h" +#define UID 1000 + +// Write to a file int write_to_file(char* path_to_file, char *line_to_write){ FILE *f = fopen(path_to_file,"w"); if (f == NULL){ @@ -21,7 +24,9 @@ int write_to_file(char* path_to_file, char *line_to_write){ return 0; } -int prepare_user_ns(int pid){ + +// Prepare User Namespace +int prepare_userns(int pid){ char* path; char* line;