diff options
Diffstat (limited to 'libhfcommon/ns.c')
-rw-r--r-- | libhfcommon/ns.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/libhfcommon/ns.c b/libhfcommon/ns.c new file mode 100644 index 00000000..25c25f90 --- /dev/null +++ b/libhfcommon/ns.c @@ -0,0 +1,127 @@ +/* + * + * honggfuzz - namespace-related utilities + * ----------------------------------------- + * + * Author: Robert Swiecki <swiecki@google.com> + * + * Copyright 2017 by Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + */ + +#include "libhfcommon/ns.h" + +#include "libhfcommon/common.h" +#include "libhfcommon/files.h" +#include "libhfcommon/log.h" + +#if defined(_HF_ARCH_LINUX) + +#include <arpa/inet.h> +#include <fcntl.h> +#include <net/if.h> +#include <sched.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/mount.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> + +bool nsEnter(uintptr_t cloneFlags) { + pid_t current_uid = getuid(); + gid_t current_gid = getgid(); + + if (unshare(cloneFlags) == -1) { + PLOG_E("unshare(0x%tx)", cloneFlags); + return false; + } + + const char* deny_str = "deny"; + if (files_writeBufToFile("/proc/self/setgroups", (const uint8_t*)deny_str, strlen(deny_str), + O_WRONLY) == false) { + PLOG_E("Couldn't write to /proc/self/setgroups"); + return false; + } + + char gid_map[4096]; + snprintf(gid_map, sizeof(gid_map), "%d %d 1", (int)current_gid, (int)current_gid); + if (files_writeBufToFile( + "/proc/self/gid_map", (const uint8_t*)gid_map, strlen(gid_map), O_WRONLY) == false) { + PLOG_E("Couldn't write to /proc/self/gid_map"); + return false; + } + + char uid_map[4096]; + snprintf(uid_map, sizeof(uid_map), "%d %d 1", (int)current_uid, (int)current_uid); + if (files_writeBufToFile( + "/proc/self/uid_map", (const uint8_t*)uid_map, strlen(uid_map), O_WRONLY) == false) { + PLOG_E("Couldn't write to /proc/self/uid_map"); + return false; + } + + if (setresgid(current_gid, current_gid, current_gid) == -1) { + PLOG_E("setresgid(%d)", (int)current_gid); + return false; + } + if (setresuid(current_uid, current_uid, current_uid) == -1) { + PLOG_E("setresuid(%d)", (int)current_uid); + return false; + } + + return true; +} + +bool nsIfaceUp(const char* ifacename) { + int sock = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP); + if (sock == -1) { + PLOG_E("socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)"); + return false; + } + + struct ifreq ifr; + memset(&ifr, '\0', sizeof(ifr)); + snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename); + + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { + PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename); + close(sock); + return false; + } + + ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); + + if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { + PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename); + close(sock); + return false; + } + + close(sock); + return true; +} + +bool nsMountTmpfs(const char* dst) { + if (mount(NULL, dst, "tmpfs", 0, NULL) == -1) { + PLOG_E("mount(dst='%s', tmpfs)", dst); + return false; + } + return true; +} + +#endif /* defined(_HF_ARCH_LINUX) */ |