Redirect qtaguid native call to netd fwmark client
In order to replace qtaguid module with new eBPF network monitoring module. We firstly move the current qtaguid userspace implementation into netd and hide the detail from other processes. The current API will talk to netd fwmark client to pass down the qtaguid related request from high level framework and netd will use the proper method to complete the request. Test: Current TrafficStats CTS tests should not fail. Bug: 30950746 Change-Id: Ie90c28f3594ab2877746b2372a1b6944768bfb18
This commit is contained in:
parent
5b11831aa1
commit
baede73bd9
5 changed files with 205 additions and 53 deletions
|
@ -110,7 +110,7 @@ cc_library {
|
|||
"klog.cpp",
|
||||
"partition_utils.c",
|
||||
"properties.cpp",
|
||||
"qtaguid.c",
|
||||
"qtaguid.cpp",
|
||||
"trace-dev.c",
|
||||
"uevent.c",
|
||||
],
|
||||
|
|
64
libcutils/include/cutils/qtaguid.h
Normal file
64
libcutils/include/cutils/qtaguid.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __CUTILS_QTAGUID_H
|
||||
#define __CUTILS_QTAGUID_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set tags (and owning UIDs) for network sockets.
|
||||
*/
|
||||
extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
|
||||
|
||||
/*
|
||||
* Untag a network socket before closing.
|
||||
*/
|
||||
extern int qtaguid_untagSocket(int sockfd);
|
||||
|
||||
/*
|
||||
* For the given uid, switch counter sets.
|
||||
* The kernel only keeps a limited number of sets.
|
||||
* 2 for now.
|
||||
*/
|
||||
extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
|
||||
|
||||
/*
|
||||
* Delete all tag info that relates to the given tag an uid.
|
||||
* If the tag is 0, then ALL info about the uid is freed.
|
||||
* The delete data also affects active tagged sockets, which are
|
||||
* then untagged.
|
||||
* The calling process can only operate on its own tags.
|
||||
* Unless it is part of the happy AID_NET_BW_ACCT group.
|
||||
* In which case it can clobber everything.
|
||||
*/
|
||||
extern int qtaguid_deleteTagData(int tag, uid_t uid);
|
||||
|
||||
/*
|
||||
* Enable/disable qtaguid functionnality at a lower level.
|
||||
* When pacified, the kernel will accept commands but do nothing.
|
||||
*/
|
||||
extern int qtaguid_setPacifier(int on);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CUTILS_QTAG_UID_H */
|
125
libcutils/qtaguid.cpp
Normal file
125
libcutils/qtaguid.cpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright 2017, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// #define LOG_NDEBUG 0
|
||||
|
||||
#define LOG_TAG "qtaguid"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/qtaguid.h>
|
||||
#include <log/log.h>
|
||||
|
||||
class netdHandler {
|
||||
public:
|
||||
int (*netdTagSocket)(int, uint32_t, uid_t);
|
||||
int (*netdUntagSocket)(int);
|
||||
int (*netdSetCounterSet)(uint32_t, uid_t);
|
||||
int (*netdDeleteTagData)(uint32_t, uid_t);
|
||||
};
|
||||
|
||||
int dummyTagSocket(int, uint32_t, uid_t) {
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int dummyUntagSocket(int) {
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int dummySetCounterSet(uint32_t, uid_t) {
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int dummyDeleteTagData(uint32_t, uid_t) {
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
netdHandler initHandler(void) {
|
||||
netdHandler handler = {dummyTagSocket, dummyUntagSocket, dummySetCounterSet, dummyDeleteTagData};
|
||||
|
||||
void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
|
||||
if (!netdClientHandle) {
|
||||
ALOGE("Failed to open libnetd_client.so: %s", dlerror());
|
||||
return handler;
|
||||
}
|
||||
|
||||
handler.netdTagSocket = (int (*)(int, uint32_t, uid_t))dlsym(netdClientHandle, "tagSocket");
|
||||
if (!handler.netdTagSocket) {
|
||||
ALOGE("load netdTagSocket handler failed: %s", dlerror());
|
||||
}
|
||||
|
||||
handler.netdUntagSocket = (int (*)(int))dlsym(netdClientHandle, "untagSocket");
|
||||
if (!handler.netdUntagSocket) {
|
||||
ALOGE("load netdUntagSocket handler failed: %s", dlerror());
|
||||
}
|
||||
|
||||
handler.netdSetCounterSet = (int (*)(uint32_t, uid_t))dlsym(netdClientHandle, "setCounterSet");
|
||||
if (!handler.netdSetCounterSet) {
|
||||
ALOGE("load netdSetCounterSet handler failed: %s", dlerror());
|
||||
}
|
||||
|
||||
handler.netdDeleteTagData = (int (*)(uint32_t, uid_t))dlsym(netdClientHandle, "deleteTagData");
|
||||
if (!handler.netdDeleteTagData) {
|
||||
ALOGE("load netdDeleteTagData handler failed: %s", dlerror());
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
// The language guarantees that this object will be initialized in a thread-safe way.
|
||||
static netdHandler& getHandler() {
|
||||
static netdHandler instance = initHandler();
|
||||
return instance;
|
||||
}
|
||||
|
||||
int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
|
||||
// Check the socket fd passed to us is still valid before we load the netd
|
||||
// client. Pass a already closed socket fd to netd client may let netd open
|
||||
// the unix socket with the same fd number and pass it to server for
|
||||
// tagging.
|
||||
// TODO: move the check into netdTagSocket.
|
||||
int res = fcntl(sockfd, F_GETFD);
|
||||
if (res < 0) return res;
|
||||
|
||||
ALOGV("Tagging socket %d with tag %u for uid %d", sockfd, tag, uid);
|
||||
return getHandler().netdTagSocket(sockfd, tag, uid);
|
||||
}
|
||||
|
||||
int qtaguid_untagSocket(int sockfd) {
|
||||
// Similiar to tag socket. We need a check before untag to make sure untag a closed socket fail
|
||||
// as expected.
|
||||
// TODO: move the check into netdTagSocket.
|
||||
int res = fcntl(sockfd, F_GETFD);
|
||||
if (res < 0) return res;
|
||||
|
||||
ALOGV("Untagging socket %d", sockfd);
|
||||
return getHandler().netdUntagSocket(sockfd);
|
||||
}
|
||||
|
||||
int qtaguid_setCounterSet(int counterSetNum, uid_t uid) {
|
||||
ALOGV("Setting counters to set %d for uid %d", counterSetNum, uid);
|
||||
return getHandler().netdSetCounterSet(counterSetNum, uid);
|
||||
}
|
||||
|
||||
int qtaguid_deleteTagData(int tag, uid_t uid) {
|
||||
ALOGV("Deleting tag data with tag %u for uid %d", tag, uid);
|
||||
return getHandler().netdDeleteTagData(tag, uid);
|
||||
}
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __CUTILS_QTAGUID_H
|
||||
#define __CUTILS_QTAGUID_H
|
||||
#ifndef __LEGACY_QTAGUID_H
|
||||
#define __LEGACY_QTAGUID_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -30,19 +30,19 @@ extern "C" {
|
|||
* by calling qtaguid_untagSocket() before closing it, otherwise the qtaguid
|
||||
* module will keep a reference to it even after close.
|
||||
*/
|
||||
extern int qtaguid_tagSocket(int sockfd, int tag, uid_t uid);
|
||||
extern int legacy_tagSocket(int sockfd, int tag, uid_t uid);
|
||||
|
||||
/*
|
||||
* Untag a network socket before closing.
|
||||
*/
|
||||
extern int qtaguid_untagSocket(int sockfd);
|
||||
extern int legacy_untagSocket(int sockfd);
|
||||
|
||||
/*
|
||||
* For the given uid, switch counter sets.
|
||||
* The kernel only keeps a limited number of sets.
|
||||
* 2 for now.
|
||||
*/
|
||||
extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
|
||||
extern int legacy_setCounterSet(int counterSetNum, uid_t uid);
|
||||
|
||||
/*
|
||||
* Delete all tag info that relates to the given tag an uid.
|
||||
|
@ -53,16 +53,10 @@ extern int qtaguid_setCounterSet(int counterSetNum, uid_t uid);
|
|||
* Unless it is part of the happy AID_NET_BW_ACCT group.
|
||||
* In which case it can clobber everything.
|
||||
*/
|
||||
extern int qtaguid_deleteTagData(int tag, uid_t uid);
|
||||
|
||||
/*
|
||||
* Enable/disable qtaguid functionnality at a lower level.
|
||||
* When pacified, the kernel will accept commands but do nothing.
|
||||
*/
|
||||
extern int qtaguid_setPacifier(int on);
|
||||
extern int legacy_deleteTagData(int tag, uid_t uid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CUTILS_QTAG_UID_H */
|
||||
#endif /* __LEGACY_QTAGUID_H */
|
||||
|
|
|
@ -26,13 +26,11 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/qtaguid.h>
|
||||
#include <log/log.h>
|
||||
#include <qtaguid/qtaguid.h>
|
||||
|
||||
static const char* CTRL_PROCPATH = "/proc/net/xt_qtaguid/ctrl";
|
||||
static const int CTRL_MAX_INPUT_LEN = 128;
|
||||
static const char* GLOBAL_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/passive";
|
||||
static const char* TAG_PACIFIER_PARAM = "/sys/module/xt_qtaguid/parameters/tag_tracking_passive";
|
||||
|
||||
/*
|
||||
* One per proccess.
|
||||
|
@ -46,7 +44,7 @@ static int resTrackFd = -1;
|
|||
pthread_once_t resTrackInitDone = PTHREAD_ONCE_INIT;
|
||||
|
||||
/* Only call once per process. */
|
||||
void qtaguid_resTrack(void) {
|
||||
void legacy_resTrack(void) {
|
||||
resTrackFd = TEMP_FAILURE_RETRY(open("/dev/xt_qtaguid", O_RDONLY | O_CLOEXEC));
|
||||
}
|
||||
|
||||
|
@ -79,28 +77,12 @@ static int write_ctrl(const char* cmd) {
|
|||
return -savedErrno;
|
||||
}
|
||||
|
||||
static int write_param(const char* param_path, const char* value) {
|
||||
int param_fd;
|
||||
int res;
|
||||
|
||||
param_fd = TEMP_FAILURE_RETRY(open(param_path, O_WRONLY | O_CLOEXEC));
|
||||
if (param_fd < 0) {
|
||||
return -errno;
|
||||
}
|
||||
res = TEMP_FAILURE_RETRY(write(param_fd, value, strlen(value)));
|
||||
if (res < 0) {
|
||||
return -errno;
|
||||
}
|
||||
close(param_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
|
||||
int legacy_tagSocket(int sockfd, int tag, uid_t uid) {
|
||||
char lineBuf[CTRL_MAX_INPUT_LEN];
|
||||
int res;
|
||||
uint64_t kTag = ((uint64_t)tag << 32);
|
||||
|
||||
pthread_once(&resTrackInitDone, qtaguid_resTrack);
|
||||
pthread_once(&resTrackInitDone, legacy_resTrack);
|
||||
|
||||
snprintf(lineBuf, sizeof(lineBuf), "t %d %" PRIu64 " %d", sockfd, kTag, uid);
|
||||
|
||||
|
@ -115,7 +97,7 @@ int qtaguid_tagSocket(int sockfd, int tag, uid_t uid) {
|
|||
return res;
|
||||
}
|
||||
|
||||
int qtaguid_untagSocket(int sockfd) {
|
||||
int legacy_untagSocket(int sockfd) {
|
||||
char lineBuf[CTRL_MAX_INPUT_LEN];
|
||||
int res;
|
||||
|
||||
|
@ -130,7 +112,7 @@ int qtaguid_untagSocket(int sockfd) {
|
|||
return res;
|
||||
}
|
||||
|
||||
int qtaguid_setCounterSet(int counterSetNum, uid_t uid) {
|
||||
int legacy_setCounterSet(int counterSetNum, uid_t uid) {
|
||||
char lineBuf[CTRL_MAX_INPUT_LEN];
|
||||
int res;
|
||||
|
||||
|
@ -141,14 +123,14 @@ int qtaguid_setCounterSet(int counterSetNum, uid_t uid) {
|
|||
return res;
|
||||
}
|
||||
|
||||
int qtaguid_deleteTagData(int tag, uid_t uid) {
|
||||
int legacy_deleteTagData(int tag, uid_t uid) {
|
||||
char lineBuf[CTRL_MAX_INPUT_LEN];
|
||||
int cnt = 0, res = 0;
|
||||
uint64_t kTag = (uint64_t)tag << 32;
|
||||
|
||||
ALOGV("Deleting tag data with tag %" PRIx64 "{%d,0} for uid %d", kTag, tag, uid);
|
||||
|
||||
pthread_once(&resTrackInitDone, qtaguid_resTrack);
|
||||
pthread_once(&resTrackInitDone, legacy_resTrack);
|
||||
|
||||
snprintf(lineBuf, sizeof(lineBuf), "d %" PRIu64 " %d", kTag, uid);
|
||||
res = write_ctrl(lineBuf);
|
||||
|
@ -159,16 +141,3 @@ int qtaguid_deleteTagData(int tag, uid_t uid) {
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
int qtaguid_setPacifier(int on) {
|
||||
const char* value;
|
||||
|
||||
value = on ? "Y" : "N";
|
||||
if (write_param(GLOBAL_PACIFIER_PARAM, value) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
if (write_param(TAG_PACIFIER_PARAM, value) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue