Доступ к / proc / net / tcp в Android Q - PullRequest
       111

Доступ к / proc / net / tcp в Android Q

2 голосов
/ 22 октября 2019

В моем приложении VPN вплоть до Android-9 было возможно прочитать файлы /proc/net/tcp из приложений, ориентированных на уровень API <28. Доступ из приложений больше не работает в Android Q. Я получаю ошибку <code>/proc/net/tcp: open failed: EACCES (Permission denied) при попытке прочитать файл.

В Android-Q с изменением конфиденциальности Google обратился Ограничение доступа к / proc / net файловая система

И я думаю ConnectivityManager.getConnectionOwnerUid() можно использовать, если версия compileSDK для приложений составляет 29. Но, к сожалению, на данный момент я не могу изменить свою версию compileSDK, но я обновил версию targetSDK до последней версии IE, 29.

Есть ли другой возможный способ прочитать файл в Android-10? Размещение моего кода для справки

public static final int INDEX_UID_COL = 7;
public static final int INDEX_LOCAL_ADDRESS_COL = 1;
public static final String PROC_FILE = "/proc/net/tcp";

 public static String getPackageName(Context context, int srcPort) {
        String packageName = "";
        try {

            BufferedReader br = new BufferedReader(new FileReader(PROC_FILE));

            //Ignore first line
            String line = br.readLine();
            while ((line = br.readLine()) != null) {
                /**
                 * Proc file table column sequence
                 * sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
                 */
                String[] parts = line.trim().split("\\s+");
                if (parts.length >= 8) {
                    String localAddress = parts[INDEX_LOCAL_ADDRESS_COL];
                    if (!localAddress.isEmpty()) {
                        String[] localAddressParts = localAddress.split(":");
                        if (localAddressParts.length == 2) {
                            int port = Integer.parseInt(localAddressParts[1], 16);
                            if (port == srcPort) {
                                int uid = Integer.parseInt(parts[INDEX_UID_COL]);
                                packageName = context.getPackageManager().getNameForUid(uid);
                                break;
                            }
                        }
                    }
                }
            }
            br.close();
        } catch (Exception ex) {
            Log.e("ProcFileParser", ex.getMessage());
        }
        return packageName;
    }

1 Ответ

1 голос
/ 22 октября 2019

ConnectivityManager - API уровня платформы. Вы можете попробовать отражение Java, чтобы получить доступ к getConnectionOwnerUid в вашем контексте. Но я предлагаю вам обновить версию compileSdk до последней .

import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.IPPROTO_TCP;

InetSocketAddress remoteInetSocketAddress = new InetSocketAddress(finalHost, srcPort);
InetSocketAddress localInetSocketAddress = new InetSocketAddress(1234);

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
Method method = ConnectivityManager.class.getMethod("getConnectionOwnerUid", int.class, InetSocketAddress.class, InetSocketAddress.class);
int uid = (int) method.invoke(connectivityManager, IPPROTO_TCP, localInetSocketAddress, remoteInetSocketAddress);
if (uid != INVALID_UID) {
       // UID access here         
  }

ПРИМЕЧАНИЕ. Этот метод позволяет только VPN-приложениям искать владельца UID сетевого подключения. Это означает, что будут разрешены только подключения для UID, которые применяются к вызывающему приложению VPN.

...