diff options
author | junyulai <junyulai@google.com> | 2018-10-29 23:10:15 +0800 |
---|---|---|
committer | junyulai <junyulai@google.com> | 2018-12-20 16:25:08 +0800 |
commit | b5e8f977bb53cbec0ef311a0ad85b7d64d228bac (patch) | |
tree | f9605a56d1a7d32a4a80465b4ab00c7b07a4e92d /clatd.c | |
parent | 51c73d30d2cda21ca54dd617ad41e3805eebd4d6 (diff) | |
download | platform_external_android-clat-b5e8f977bb53cbec0ef311a0ad85b7d64d228bac.tar.gz platform_external_android-clat-b5e8f977bb53cbec0ef311a0ad85b7d64d228bac.tar.bz2 platform_external_android-clat-b5e8f977bb53cbec0ef311a0ad85b7d64d228bac.zip |
Count ipv6 tx traffic of clat into clat uid.
Currently, 464xlat counts its ipv6 tx traffic into root uid.
When user is making ipv4 upload over ipv6-only network, ipv4
tx traffic may sometimes be counted faster then ipv6 tx
traffic.
Thus, NetworkStatsService may detect non-monotonic values due
to 464xlat adjustment.
So the solution here is to make ipv6 tx traffic counts into
clat uid, and then ignore it in the framework side.
Bug: 118602783
Test: 1. manually verify clatd traffic on clat uid.
2. atest clatd_test.cpp
Change-Id: I834aef7184a06df89f0db8fee28e2174aa03d817
Diffstat (limited to 'clatd.c')
-rw-r--r-- | clatd.c | 63 |
1 files changed, 39 insertions, 24 deletions
@@ -154,40 +154,52 @@ void configure_tun_ip(const struct tun_data *tunnel) { } } -/* function: drop_root - * drops root privs but keeps the needed capability +/* function: set_capability + * set the permitted, effective and inheritable capabilities of the current + * thread */ -void drop_root() { +void set_capability(uint64_t target_cap) { + struct __user_cap_header_struct header = { + .version = _LINUX_CAPABILITY_VERSION_3, + .pid = 0 // 0 = change myself + }; + struct __user_cap_data_struct cap[_LINUX_CAPABILITY_U32S_3] = {}; + + cap[0].permitted = cap[0].effective = cap[0].inheritable = target_cap; + cap[1].permitted = cap[1].effective = cap[1].inheritable = target_cap >> 32; + + if (capset(&header, cap) < 0) { + logmsg(ANDROID_LOG_FATAL, "capset failed: %s", strerror(errno)); + exit(1); + } +} + +/* function: drop_root_but_keep_caps + * drops root privs but keeps the needed capabilities + */ +void drop_root_but_keep_caps() { gid_t groups[] = { AID_INET, AID_VPN }; if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) < 0) { - logmsg(ANDROID_LOG_FATAL, "drop_root/setgroups failed: %s", strerror(errno)); + logmsg(ANDROID_LOG_FATAL, "setgroups failed: %s", strerror(errno)); exit(1); } - prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); + prctl(PR_SET_KEEPCAPS, 1); - if (setgid(AID_CLAT) < 0) { - logmsg(ANDROID_LOG_FATAL, "drop_root/setgid failed: %s", strerror(errno)); + if (setresgid(AID_CLAT, AID_CLAT, AID_CLAT) < 0) { + logmsg(ANDROID_LOG_FATAL, "setresgid failed: %s", strerror(errno)); exit(1); } - if (setuid(AID_CLAT) < 0) { - logmsg(ANDROID_LOG_FATAL, "drop_root/setuid failed: %s", strerror(errno)); + if (setresuid(AID_CLAT, AID_CLAT, AID_CLAT) < 0) { + logmsg(ANDROID_LOG_FATAL, "setresuid failed: %s", strerror(errno)); exit(1); } - struct __user_cap_header_struct header; - struct __user_cap_data_struct cap; - memset(&header, 0, sizeof(header)); - memset(&cap, 0, sizeof(cap)); - - header.version = _LINUX_CAPABILITY_VERSION; - header.pid = 0; // 0 = change myself - cap.effective = cap.permitted = (1 << CAP_NET_ADMIN); - - if (capset(&header, &cap) < 0) { - logmsg(ANDROID_LOG_FATAL, "drop_root/capset failed: %s", strerror(errno)); - exit(1); - } + // keep CAP_NET_RAW capability to open raw socket, and CAP_IPC_LOCK for mmap + // to lock memory. + set_capability((1 << CAP_NET_ADMIN) | + (1 << CAP_NET_RAW) | + (1 << CAP_IPC_LOCK)); } /* function: open_sockets @@ -494,11 +506,14 @@ int main(int argc, char **argv) { logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s netid=%s mark=%s", CLATD_VERSION, uplink_interface, net_id_str ? net_id_str : "(none)", mark_str ? mark_str : "(none)"); + // run under a regular user but keep needed capabilities + drop_root_but_keep_caps(); + // open our raw sockets before dropping privs open_sockets(&tunnel, mark); - // run under a regular user - drop_root(); + // keeps only admin capability + set_capability(1 << CAP_NET_ADMIN); // we can create tun devices as non-root because we're in the VPN group. tunnel.fd4 = tun_open(); |