Home | History | Annotate | Download | only in libcommon
      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 "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