1 /*
2 *
3 * honggfuzz - namespace-related utilities
4 * -----------------------------------------
5 *
6 * Author: Robert Swiecki <swiecki@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
nsEnter(uintptr_t cloneFlags)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
nsIfaceUp(const char * ifacename)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
nsMountTmpfs(const char * dst)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