Merge "Add NetworkStack app"

This commit is contained in:
Remi NGUYEN VAN
2018-12-26 00:48:25 +00:00
committed by Gerrit Code Review
11 changed files with 371 additions and 0 deletions

View File

@@ -679,6 +679,7 @@ java_defaults {
static_libs: [
"apex_aidl_interface-java",
"networkstack-aidl-interfaces-java",
"framework-protos",
"android.hidl.base-V1.0-java",
"android.hardware.cas-V1.0-java",
@@ -818,6 +819,16 @@ gensrcs {
output_extension: "srcjar",
}
// AIDL interfaces between the core system and the networking mainline module.
aidl_interface {
name: "networkstack-aidl-interfaces",
local_include_dir: "core/java",
srcs: [
"core/java/android/net/INetworkStackConnector.aidl",
],
api_dir: "aidl/networkstack",
}
// Build ext.jar
// ============================================================
java_library {

View File

@@ -87,6 +87,7 @@ import android.net.INetworkPolicyManager;
import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
import android.net.NetworkStack;
import android.net.NetworkWatchlistManager;
import android.net.lowpan.ILowpanManager;
import android.net.lowpan.LowpanManager;
@@ -283,6 +284,13 @@ final class SystemServiceRegistry {
return new ConnectivityManager(context, service);
}});
registerService(Context.NETWORK_STACK_SERVICE, NetworkStack.class,
new StaticServiceFetcher<NetworkStack>() {
@Override
public NetworkStack createService() {
return new NetworkStack();
}});
registerService(Context.IPSEC_SERVICE, IpSecManager.class,
new CachedServiceFetcher<IpSecManager>() {
@Override

View File

@@ -49,6 +49,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.NetworkStack;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -3502,6 +3503,15 @@ public abstract class Context {
*/
public static final String CONNECTIVITY_SERVICE = "connectivity";
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link NetworkStack} for communicating with the network stack
* @hide
* @see #getSystemService(String)
* @see NetworkStack
*/
public static final String NETWORK_STACK_SERVICE = "network_stack";
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.IpSecManager} for encrypting Sockets or Networks with

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2018, 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 perNmissions and
* limitations under the License.
*/
package android.net;
/** @hide */
oneway interface INetworkStackConnector {
// TODO: requestDhcpServer(), etc. will go here
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2018 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.
*/
package android.net;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
/**
* Service used to communicate with the network stack, which is running in a separate module.
* @hide
*/
@SystemService(Context.NETWORK_STACK_SERVICE)
public class NetworkStack {
private static final String TAG = NetworkStack.class.getSimpleName();
@NonNull
@GuardedBy("mPendingNetStackRequests")
private final ArrayList<NetworkStackRequest> mPendingNetStackRequests = new ArrayList<>();
@Nullable
@GuardedBy("mPendingNetStackRequests")
private INetworkStackConnector mConnector;
private interface NetworkStackRequest {
void onNetworkStackConnected(INetworkStackConnector connector);
}
public NetworkStack() { }
private class NetworkStackConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
registerNetworkStackService(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO: crash/reboot the system ?
Slog.wtf(TAG, "Lost network stack connector");
}
};
private void registerNetworkStackService(@NonNull IBinder service) {
final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
final ArrayList<NetworkStackRequest> requests;
synchronized (mPendingNetStackRequests) {
requests = new ArrayList<>(mPendingNetStackRequests);
mPendingNetStackRequests.clear();
mConnector = connector;
}
for (NetworkStackRequest r : requests) {
r.onNetworkStackConnected(connector);
}
}
/**
* Start the network stack. Should be called only once on device startup.
*
* <p>This method will start the network stack either in the network stack process, or inside
* the system server on devices that do not support the network stack module. The network stack
* connector will then be delivered asynchronously to clients that requested it before it was
* started.
*/
public void start(Context context) {
// Try to bind in-process if the library is available
IBinder connector = null;
try {
final Class service = Class.forName(
"com.android.server.NetworkStackService",
true /* initialize */,
context.getClassLoader());
connector = (IBinder) service.getMethod("makeConnector").invoke(null);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Slog.wtf(TAG, "Could not create network stack connector from NetworkStackService");
// TODO: crash/reboot system here ?
return;
} catch (ClassNotFoundException e) {
// Normal behavior if stack is provided by the app: fall through
}
// In-process network stack. Add the service to the service manager here.
if (connector != null) {
registerNetworkStackService(connector);
return;
}
// Start the network stack process. The service will be added to the service manager in
// NetworkStackConnection.onServiceConnected().
final Intent intent = new Intent(INetworkStackConnector.class.getName());
final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !context.bindServiceAsUser(intent, new NetworkStackConnection(),
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
Slog.wtf(TAG,
"Could not bind to network stack in-process, or in app with " + intent);
// TODO: crash/reboot system server if no network stack after a timeout ?
}
}
// TODO: use this method to obtain the connector when implementing network stack operations
private void requestConnector(@NonNull NetworkStackRequest request) {
// TODO: PID check.
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
// Don't even attempt to obtain the connector and give a nice error message
throw new SecurityException(
"Only the system server should try to bind to the network stack.");
}
final INetworkStackConnector connector;
synchronized (mPendingNetStackRequests) {
connector = mConnector;
if (connector == null) {
mPendingNetStackRequests.add(request);
return;
}
}
request.onNetworkStackConnected(connector);
}
}

View File

@@ -174,6 +174,12 @@ public class Process {
*/
public static final int SE_UID = 1068;
/**
* Defines the UID/GID for the NetworkStack app.
* @hide
*/
public static final int NETWORK_STACK_UID = 1073;
/** {@hide} */
public static final int NOBODY_UID = 9999;

View File

@@ -917,6 +917,13 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi
capabilities |= (1LL << CAP_SYS_NICE);
}
if (multiuser_get_app_id(uid) == AID_NETWORK_STACK) {
capabilities |= (1LL << CAP_NET_ADMIN);
capabilities |= (1LL << CAP_NET_BROADCAST);
capabilities |= (1LL << CAP_NET_BIND_SERVICE);
capabilities |= (1LL << CAP_NET_RAW);
}
/*
* Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
*/

View File

@@ -0,0 +1,37 @@
//
// Copyright (C) 2018 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.
//
// Library including the network stack, used to compile the network stack app, or linked into the
// system server on devices that run the stack there
java_library {
name: "NetworkStackLib",
installable: true,
srcs: [
"src/**/*.java",
],
}
// Updatable network stack packaged as an application
android_app {
name: "NetworkStack",
platform_apis: true,
certificate: "platform",
privileged: true,
static_libs: [
"NetworkStackLib"
],
manifest: "AndroidManifest.xml",
}

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2014 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.
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.networkstack"
android:sharedUserId="android.uid.networkstack">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- Launch captive portal app as specific user -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<application
android:label="NetworkStack"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
android:usesCleartextTraffic="true">
<service android:name="com.android.server.NetworkStackService">
<intent-filter>
<action android:name="android.net.INetworkStackConnector"/>
</intent-filter>
</service>
</application>
</manifest>

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2018 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.
*/
package com.android.server;
import static android.os.Binder.getCallingUid;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Service;
import android.content.Intent;
import android.net.INetworkStackConnector;
import android.os.IBinder;
import android.os.Process;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Android service used to start the network stack when bound to via an intent.
*
* <p>The service returns a binder for the system server to communicate with the network stack.
*/
public class NetworkStackService extends Service {
private static final String TAG = NetworkStackService.class.getSimpleName();
/**
* Create a binder connector for the system server to communicate with the network stack.
*
* <p>On platforms where the network stack runs in the system server process, this method may
* be called directly instead of obtaining the connector by binding to the service.
*/
public static IBinder makeConnector() {
return new NetworkStackConnector();
}
@NonNull
@Override
public IBinder onBind(Intent intent) {
return makeConnector();
}
private static class NetworkStackConnector extends INetworkStackConnector.Stub {
// TODO: makeDhcpServer(), etc. will go here.
@Override
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
@Nullable String[] args) {
checkCaller();
fout.println("NetworkStack logs:");
// TODO: dump logs here
}
}
private static void checkCaller() {
// TODO: check that the calling PID is the system server.
if (getCallingUid() != Process.SYSTEM_UID && getCallingUid() != Process.ROOT_UID) {
throw new SecurityException("Invalid caller: " + getCallingUid());
}
}
}

View File

@@ -456,6 +456,7 @@ public class PackageManagerService extends IPackageManager.Stub
private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
private static final int SHELL_UID = Process.SHELL_UID;
private static final int SE_UID = Process.SE_UID;
private static final int NETWORKSTACK_UID = Process.NETWORK_STACK_UID;
// Suffix used during package installation when copying/moving
// package apks to install directory.
@@ -2469,6 +2470,8 @@ public class PackageManagerService extends IPackageManager.Stub
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.se", SE_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {