From 5c8b3835b7aadb184a1777268a6ed3f7100ba933 Mon Sep 17 00:00:00 2001 From: Eli Zrihen Date: Wed, 16 Jun 2021 16:59:12 +0300 Subject: [PATCH] MACVLAN modes support --- cmdline.cc | 18 ++++++++++++++++++ config.cc | 1 + config.proto | 1 + net.cc | 7 ++++++- nsjail.h | 1 + 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/cmdline.cc b/cmdline.cc index fc04c11..d29a35a 100644 --- a/cmdline.cc +++ b/cmdline.cc @@ -158,6 +158,7 @@ struct custom_option custom_opts[] = { { { "macvlan_vs_nm", required_argument, NULL, 0x702 }, "Netmask of the 'vs' interface (e.g. \"255.255.255.0\")" }, { { "macvlan_vs_gw", required_argument, NULL, 0x703 }, "Default GW for the 'vs' interface (e.g. \"192.168.0.1\")" }, { { "macvlan_vs_ma", required_argument, NULL, 0x705 }, "MAC-address of the 'vs' interface (e.g. \"ba:ad:ba:be:45:00\")" }, + { { "macvlan_vs_mo", required_argument, NULL, 0x706 }, "Mode of the 'vs' interface. Can be either 'private', 'vepa', 'bridge' or 'passthru' (default: 'private')" }, }; // clang-format on @@ -391,6 +392,19 @@ void setupUsers(nsjconf_t* nsjconf) { } } +std::string parseMACVlanMode(const char* optarg) { + if (strcasecmp(optarg, "private") != 0 && + strcasecmp(optarg, "vepa") != 0 && + strcasecmp(optarg, "bridge") != 0 && + strcasecmp(optarg, "passthru") != 0) { + LOG_F( + "macvlan mode can only be one of the values: 'private'/'vepa'/'bridge'/'passthru' ('%s' " + "provided).", + optarg); + } + return std::string(optarg); +} + std::unique_ptr parseArgs(int argc, char* argv[]) { std::unique_ptr nsjconf(new nsjconf_t); @@ -451,6 +465,7 @@ std::unique_ptr parseArgs(int argc, char* argv[]) { nsjconf->iface_vs_nm = "255.255.255.0"; nsjconf->iface_vs_gw = "0.0.0.0"; nsjconf->iface_vs_ma = ""; + nsjconf->iface_vs_mo = "private"; nsjconf->orig_uid = getuid(); nsjconf->orig_euid = geteuid(); nsjconf->num_cpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -809,6 +824,9 @@ std::unique_ptr parseArgs(int argc, char* argv[]) { case 0x705: nsjconf->iface_vs_ma = optarg; break; + case 0x706: + nsjconf->iface_vs_mo = parseMACVlanMode(optarg); + break; case 0x801: nsjconf->cgroup_mem_max = (size_t)strtoull(optarg, NULL, 0); break; diff --git a/config.cc b/config.cc index 5dacef6..413f6fc 100644 --- a/config.cc +++ b/config.cc @@ -267,6 +267,7 @@ static bool configParseInternal(nsjconf_t* nsjconf, const nsjail::NsJailConfig& nsjconf->iface_vs_nm = njc.macvlan_vs_nm(); nsjconf->iface_vs_gw = njc.macvlan_vs_gw(); nsjconf->iface_vs_ma = njc.macvlan_vs_ma(); + nsjconf->iface_vs_mo = njc.macvlan_vs_mo(); if (njc.has_exec_bin()) { if (njc.exec_bin().has_path()) { diff --git a/config.proto b/config.proto index 25d6ee1..8c55991 100644 --- a/config.proto +++ b/config.proto @@ -244,6 +244,7 @@ message NsJailConfig { optional string macvlan_vs_nm = 79 [default = "255.255.255.0"]; optional string macvlan_vs_gw = 80 [default = "192.168.0.1"]; optional string macvlan_vs_ma = 81 [default = ""]; + optional string macvlan_vs_mo = 87 [default = "private"]; /* Niceness level of the jailed process */ optional int32 nice_level = 82 [default = 19]; diff --git a/net.cc b/net.cc index 5259f9c..d8d750d 100644 --- a/net.cc +++ b/net.cc @@ -84,7 +84,12 @@ static bool cloneIface( rtnl_link_set_addr(rmv, nladdr); nl_addr_put(nladdr); } - + + if ((err = rtnl_link_macvlan_set_mode(rmv, rtnl_link_macvlan_str2mode(nsjconf->iface_vs_mo.c_str()))) < 0) { + LOG_E("rtnl_link_macvlan_set_mode(mode:'%s') failed: %s", + nsjconf->iface_vs_mo.c_str(), nl_geterror(err)); + } + if ((err = rtnl_link_add(sk, rmv, NLM_F_CREATE)) < 0) { LOG_E("rtnl_link_add(name:'%s' link:'%s'): %s", IFACE_NAME, nsjconf->iface_vs.c_str(), nl_geterror(err)); diff --git a/nsjail.h b/nsjail.h index 5e686c7..7dd588e 100644 --- a/nsjail.h +++ b/nsjail.h @@ -140,6 +140,7 @@ struct nsjconf_t { std::string iface_vs_nm; std::string iface_vs_gw; std::string iface_vs_ma; + std::string iface_vs_mo; std::string cgroup_mem_mount; std::string cgroup_mem_parent; size_t cgroup_mem_max;