Skip to content

Commit c35f98e

Browse files
jpa468Android (Google) Code Review
authored andcommitted
Merge "NetworkManagement SocketTagger: Migrate QTagUid support to JNI."
2 parents 6f4518f + 98a4f7e commit c35f98e

File tree

5 files changed

+131
-93
lines changed

5 files changed

+131
-93
lines changed

core/java/com/android/server/NetworkManagementSocketTagger.java

Lines changed: 31 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -75,50 +75,39 @@ public void tag(FileDescriptor fd) throws SocketException {
7575
Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
7676
+ Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
7777
}
78-
try {
79-
// TODO: skip tagging when options would be no-op
80-
tagSocketFd(fd, options.statsTag, options.statsUid);
81-
} catch (IOException e) {
82-
throw new SocketException("Problem tagging socket", e);
83-
}
78+
// TODO: skip tagging when options would be no-op
79+
tagSocketFd(fd, options.statsTag, options.statsUid);
8480
}
8581

86-
private void tagSocketFd(FileDescriptor fd, int tag, int uid) throws IOException {
87-
final int fdNum = fd.getInt$();
88-
if (fdNum == -1 || (tag == -1 && uid == -1)) return;
89-
90-
String cmd = "t " + fdNum;
91-
if (tag == -1) {
92-
// Case where just the uid needs adjusting. But probably the caller
93-
// will want to track his own name here, just in case.
94-
cmd += " 0";
95-
} else {
96-
cmd += " " + tagToKernel(tag);
97-
}
98-
if (uid != -1) {
99-
cmd += " " + uid;
82+
private void tagSocketFd(FileDescriptor fd, int tag, int uid) {
83+
int errno;
84+
if (tag == -1 && uid == -1) return;
85+
86+
errno = native_tagSocketFd(fd, tag, uid);
87+
if (errno < 0) {
88+
Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
89+
+ tag + ", " +
90+
+ uid + ") failed with errno" + errno);
10091
}
101-
internalModuleCtrl(cmd);
10292
}
10393

10494
@Override
10595
public void untag(FileDescriptor fd) throws SocketException {
10696
if (LOGD) {
10797
Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
10898
}
109-
try {
110-
unTagSocketFd(fd);
111-
} catch (IOException e) {
112-
throw new SocketException("Problem untagging socket", e);
113-
}
99+
unTagSocketFd(fd);
114100
}
115101

116-
private void unTagSocketFd(FileDescriptor fd) throws IOException {
117-
int fdNum = fd.getInt$();
102+
private void unTagSocketFd(FileDescriptor fd) {
118103
final SocketTags options = threadSocketTags.get();
119-
if (fdNum == -1 || (options.statsTag == -1 && options.statsUid == -1)) return;
120-
String cmd = "u " + fdNum;
121-
internalModuleCtrl(cmd);
104+
int errno;
105+
if (options.statsTag == -1 && options.statsUid == -1) return;
106+
107+
errno = native_untagSocketFd(fd);
108+
if (errno < 0) {
109+
Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
110+
}
122111
}
123112

124113
public static class SocketTags {
@@ -127,68 +116,19 @@ public static class SocketTags {
127116
}
128117

129118
public static void setKernelCounterSet(int uid, int counterSet) {
130-
final StringBuilder command = new StringBuilder();
131-
command.append("s ").append(counterSet).append(" ").append(uid);
132-
try {
133-
internalModuleCtrl(command.toString());
134-
} catch (IOException e) {
135-
Slog.w(TAG, "problem changing counter set for uid " + uid + " : " + e);
119+
int errno = native_setCounterSet(counterSet, uid);
120+
if (errno < 0) {
121+
Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno " + errno);
136122
}
137123
}
138124

139125
public static void resetKernelUidStats(int uid) {
140-
final StringBuilder command = new StringBuilder();
141-
command.append("d 0 ").append(uid);
142-
try {
143-
internalModuleCtrl(command.toString());
144-
} catch (IOException e) {
145-
Slog.w(TAG, "problem clearing counters for uid " + uid + " : " + e);
126+
int errno = native_deleteTagData(0, uid);
127+
if (errno < 0) {
128+
Slog.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
146129
}
147130
}
148131

149-
/**
150-
* Sends commands to the kernel netfilter module.
151-
*
152-
* @param cmd command string for the qtaguid netfilter module. May not be null.
153-
* <p>Supports:
154-
* <ul><li>tag a socket:<br>
155-
* <code>t <i>sock_fd</i> <i>acct_tag</i> [<i>uid_in_case_caller_is_acting_on_behalf_of</i>]</code><br>
156-
* <code>*_tag</code> defaults to default_policy_tag_from_uid(uid_of_caller)<br>
157-
* <code>acct_tag</code> is either 0 or greater that 2^32.<br>
158-
* <code>uid_*</code> is only settable by privileged UIDs (DownloadManager,...)
159-
* </li>
160-
* <li>untag a socket, preserving counters:<br>
161-
* <code>u <i>sock_fd</i></code>
162-
* </li></ul>
163-
* <p>Notes:<br>
164-
* <ul><li><i>sock_fd</i> is withing the callers process space.</li>
165-
* <li><i>*_tag</i> are 64bit values</li></ul>
166-
*
167-
*/
168-
private static void internalModuleCtrl(String cmd) throws IOException {
169-
if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
170-
171-
// TODO: migrate to native library for tagging commands
172-
FileOutputStream procOut = null;
173-
try {
174-
procOut = new FileOutputStream("/proc/net/xt_qtaguid/ctrl");
175-
procOut.write(cmd.getBytes(Charsets.US_ASCII));
176-
} finally {
177-
IoUtils.closeQuietly(procOut);
178-
}
179-
}
180-
181-
/**
182-
* Convert {@link Integer} tag to {@code /proc/} format. Assumes unsigned
183-
* base-10 format like {@code 2147483647}. Currently strips signed bit to
184-
* avoid using {@link BigInteger}.
185-
*/
186-
public static String tagToKernel(int tag) {
187-
// TODO: eventually write in hex, since that's what proc exports
188-
// TODO: migrate to direct integer instead of odd shifting
189-
return Long.toString((((long) tag) << 32) & 0x7FFFFFFF00000000L);
190-
}
191-
192132
/**
193133
* Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
194134
* format like {@code 0x7fffffff00000000}.
@@ -197,4 +137,9 @@ public static int kernelToTag(String string) {
197137
// TODO: migrate to direct integer instead of odd shifting
198138
return (int) (Long.decode(string) >> 32);
199139
}
140+
141+
private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
142+
private static native int native_untagSocketFd(FileDescriptor fd);
143+
private static native int native_setCounterSet(int uid, int counterSetNum);
144+
private static native int native_deleteTagData(int tag, int uid);
200145
}

core/jni/Android.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ LOCAL_SRC_FILES:= \
143143
android_server_BluetoothService.cpp \
144144
android_server_BluetoothEventLoop.cpp \
145145
android_server_BluetoothA2dpService.cpp \
146+
android_server_NetworkManagementSocketTagger.cpp \
146147
android_server_Watchdog.cpp \
147148
android_ddm_DdmHandleNativeHeap.cpp \
148149
com_android_internal_os_ZygoteInit.cpp \

core/jni/AndroidRuntime.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ extern int register_android_bluetooth_BluetoothSocket(JNIEnv *env);
155155
extern int register_android_server_BluetoothService(JNIEnv* env);
156156
extern int register_android_server_BluetoothEventLoop(JNIEnv *env);
157157
extern int register_android_server_BluetoothA2dpService(JNIEnv* env);
158+
extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
158159
extern int register_android_server_Watchdog(JNIEnv* env);
159160
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
160161
extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
@@ -1178,6 +1179,7 @@ static const RegJNIRec gRegJNI[] = {
11781179
REG_JNI(register_android_server_BluetoothService),
11791180
REG_JNI(register_android_server_BluetoothEventLoop),
11801181
REG_JNI(register_android_server_BluetoothA2dpService),
1182+
REG_JNI(register_android_server_NetworkManagementSocketTagger),
11811183
REG_JNI(register_android_server_Watchdog),
11821184
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
11831185
REG_JNI(register_android_backup_BackupDataInput),
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2011, The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#define LOG_TAG "NMST_QTagUidNative"
18+
#include <utils/Log.h>
19+
20+
#include "JNIHelp.h"
21+
22+
#include "jni.h"
23+
#include <utils/misc.h>
24+
#include <cutils/qtaguid.h>
25+
26+
#include <errno.h>
27+
#include <fcntl.h>
28+
#include <sys/types.h>
29+
#include <sys/socket.h>
30+
31+
namespace android {
32+
33+
static jint QTagUid_tagSocketFd(JNIEnv* env, jclass,
34+
jobject fileDescriptor,
35+
jint tagNum, jint uid) {
36+
int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
37+
38+
if (env->ExceptionOccurred() != NULL) {
39+
LOGE("Can't get FileDescriptor num");
40+
return (jint)-1;
41+
}
42+
43+
int res = qtaguid_tagSocket(userFd, tagNum, uid);
44+
if (res < 0) {
45+
return (jint)-errno;
46+
}
47+
return (jint)res;
48+
}
49+
50+
static int QTagUid_untagSocketFd(JNIEnv* env, jclass,
51+
jobject fileDescriptor) {
52+
int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
53+
54+
if (env->ExceptionOccurred() != NULL) {
55+
LOGE("Can't get FileDescriptor num");
56+
return (jint)-1;
57+
}
58+
59+
int res = qtaguid_untagSocket(userFd);
60+
if (res < 0) {
61+
return (jint)-errno;
62+
}
63+
return (jint)res;
64+
}
65+
66+
static jint QTagUid_setCounterSet(JNIEnv* env, jclass,
67+
jint setNum, jint uid) {
68+
69+
int res = qtaguid_setCounterSet(setNum, uid);
70+
if (res < 0) {
71+
return (jint)-errno;
72+
}
73+
return (jint)res;
74+
}
75+
76+
static jint QTagUid_deleteTagData(JNIEnv* env, jclass,
77+
jint tagNum, jint uid) {
78+
79+
int res = qtaguid_deleteTagData(tagNum, uid);
80+
if (res < 0) {
81+
return (jint)-errno;
82+
}
83+
return (jint)res;
84+
}
85+
86+
static JNINativeMethod gQTagUidMethods[] = {
87+
{ "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)QTagUid_tagSocketFd},
88+
{ "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)QTagUid_untagSocketFd},
89+
{ "native_setCounterSet", "(II)I", (void*)QTagUid_setCounterSet},
90+
{ "native_deleteTagData", "(II)I", (void*)QTagUid_deleteTagData},
91+
};
92+
93+
int register_android_server_NetworkManagementSocketTagger(JNIEnv* env) {
94+
return jniRegisterNativeMethods(env, "com/android/server/NetworkManagementSocketTagger", gQTagUidMethods, NELEM(gQTagUidMethods));
95+
}
96+
97+
};

services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import static android.net.NetworkStats.TAG_NONE;
2222
import static android.net.NetworkStats.UID_ALL;
2323
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
24-
import static com.android.server.NetworkManagementSocketTagger.tagToKernel;
2524

2625
import android.content.res.Resources;
2726
import android.net.NetworkStats;
@@ -144,12 +143,6 @@ public void testNetworkStatsCombinedInactive() throws Exception {
144143
}
145144

146145
public void testKernelTags() throws Exception {
147-
assertEquals("0", tagToKernel(0x0));
148-
assertEquals("214748364800", tagToKernel(0x32));
149-
assertEquals("9223372032559808512", tagToKernel(Integer.MAX_VALUE));
150-
assertEquals("0", tagToKernel(Integer.MIN_VALUE));
151-
assertEquals("9223369837831520256", tagToKernel(Integer.MIN_VALUE - 512));
152-
153146
assertEquals(0, kernelToTag("0x0000000000000000"));
154147
assertEquals(0x32, kernelToTag("0x0000003200000000"));
155148
assertEquals(2147483647, kernelToTag("0x7fffffff00000000"));

0 commit comments

Comments
 (0)