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