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 "ns.h"
25 #include "common.h"
26 
27 #include "files.h"
28 #include "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(%tx)", cloneFlags);
52         return false;
53     }
54 
55     const char* deny_str = "deny";
56     if (files_writeBufToFile("/proc/self/setgroups", (const uint8_t*)deny_str, strlen(deny_str),
57             O_WRONLY) == false) {
58         PLOG_E("Couldn't write to /proc/self/setgroups");
59         return false;
60     }
61 
62     char gid_map[4096];
63     snprintf(gid_map, sizeof(gid_map), "%d %d 1", (int)current_gid, (int)current_gid);
64     if (files_writeBufToFile(
65             "/proc/self/gid_map", (const uint8_t*)gid_map, strlen(gid_map), O_WRONLY) == false) {
66         PLOG_E("Couldn't write to /proc/self/gid_map");
67         return false;
68     }
69 
70     char uid_map[4096];
71     snprintf(uid_map, sizeof(uid_map), "%d %d 1", (int)current_uid, (int)current_uid);
72     if (files_writeBufToFile(
73             "/proc/self/uid_map", (const uint8_t*)uid_map, strlen(uid_map), O_WRONLY) == false) {
74         PLOG_E("Couldn't write to /proc/self/uid_map");
75         return false;
76     }
77 
78     if (setresgid(current_gid, current_gid, current_gid) == -1) {
79         PLOG_E("setresgid(%d)", (int)current_gid);
80         return false;
81     }
82     if (setresuid(current_uid, current_uid, current_uid) == -1) {
83         PLOG_E("setresuid(%d)", (int)current_uid);
84         return false;
85     }
86 
87     return true;
88 }
89 
90 bool nsIfaceUp(const char* ifacename) {
91     int sock = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP);
92     if (sock == -1) {
93         PLOG_E("socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)");
94         return false;
95     }
96 
97     struct ifreq ifr;
98     memset(&ifr, '\0', sizeof(ifr));
99     snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename);
100 
101     if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
102         PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename);
103         close(sock);
104         return false;
105     }
106 
107     ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
108 
109     if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
110         PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename);
111         close(sock);
112         return false;
113     }
114 
115     close(sock);
116     return true;
117 }
118 
119 bool nsMountTmpfs(const char* dst) {
120     if (mount(NULL, dst, "tmpfs", 0, NULL) == -1) {
121         PLOG_E("mount(dst='%s', tmpfs)", dst);
122         return false;
123     }
124     return true;
125 }
126 
127 #endif /* defined(_HF_ARCH_LINUX) */
128