1 /* 2 * 3 * honggfuzz - namespace-related utilities 4 * ----------------------------------------- 5 * 6 * Author: Robert Swiecki <swiecki (at) google.com> 7 * 8 * Copyright 2017 by Google Inc. All Rights Reserved. 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may 11 * not use this file except in compliance with the License. You may obtain 12 * a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 19 * implied. See the License for the specific language governing 20 * permissions and limitations under the License. 21 * 22 */ 23 24 #include "libhfcommon/ns.h" 25 26 #include "libhfcommon/common.h" 27 #include "libhfcommon/files.h" 28 #include "libhfcommon/log.h" 29 30 #if defined(_HF_ARCH_LINUX) 31 32 #include <arpa/inet.h> 33 #include <fcntl.h> 34 #include <net/if.h> 35 #include <sched.h> 36 #include <stdbool.h> 37 #include <stdint.h> 38 #include <stdio.h> 39 #include <string.h> 40 #include <sys/ioctl.h> 41 #include <sys/mount.h> 42 #include <sys/socket.h> 43 #include <sys/stat.h> 44 #include <sys/types.h> 45 46 bool nsEnter(uintptr_t cloneFlags) { 47 pid_t current_uid = getuid(); 48 gid_t current_gid = getgid(); 49 50 if (unshare(cloneFlags) == -1) { 51 PLOG_E("unshare(0x%tx)", cloneFlags); 52 if (cloneFlags | CLONE_NEWUSER) { 53 LOG_W("Executing 'sysctl -w kernel.unprivileged_userns_clone=1' might help with this"); 54 } 55 return false; 56 } 57 58 const char* deny_str = "deny"; 59 if (files_writeBufToFile("/proc/self/setgroups", (const uint8_t*)deny_str, strlen(deny_str), 60 O_WRONLY) == false) { 61 PLOG_E("Couldn't write to /proc/self/setgroups"); 62 return false; 63 } 64 65 char gid_map[4096]; 66 snprintf(gid_map, sizeof(gid_map), "%d %d 1", (int)current_gid, (int)current_gid); 67 if (files_writeBufToFile( 68 "/proc/self/gid_map", (const uint8_t*)gid_map, strlen(gid_map), O_WRONLY) == false) { 69 PLOG_E("Couldn't write to /proc/self/gid_map"); 70 return false; 71 } 72 73 char uid_map[4096]; 74 snprintf(uid_map, sizeof(uid_map), "%d %d 1", (int)current_uid, (int)current_uid); 75 if (files_writeBufToFile( 76 "/proc/self/uid_map", (const uint8_t*)uid_map, strlen(uid_map), O_WRONLY) == false) { 77 PLOG_E("Couldn't write to /proc/self/uid_map"); 78 return false; 79 } 80 81 if (setresgid(current_gid, current_gid, current_gid) == -1) { 82 PLOG_E("setresgid(%d)", (int)current_gid); 83 return false; 84 } 85 if (setresuid(current_uid, current_uid, current_uid) == -1) { 86 PLOG_E("setresuid(%d)", (int)current_uid); 87 return false; 88 } 89 90 return true; 91 } 92 93 bool nsIfaceUp(const char* ifacename) { 94 int sock = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); 95 if (sock == -1) { 96 if ((sock = socket(PF_INET6, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP)) == -1) { 97 PLOG_E("socket(PF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_TCP)"); 98 return false; 99 } 100 } 101 102 struct ifreq ifr; 103 memset(&ifr, '\0', sizeof(ifr)); 104 snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename); 105 106 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { 107 PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename); 108 close(sock); 109 return false; 110 } 111 112 ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); 113 114 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { 115 PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename); 116 close(sock); 117 return false; 118 } 119 120 close(sock); 121 return true; 122 } 123 124 bool nsMountTmpfs(const char* dst) { 125 if (mount(NULL, dst, "tmpfs", 0, NULL) == -1) { 126 PLOG_E("mount(dst='%s', tmpfs)", dst); 127 return false; 128 } 129 return true; 130 } 131 132 #endif /* defined(_HF_ARCH_LINUX) */ 133