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
46bool 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
90bool 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
119bool 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