diff --git a/bpf/progs/netd.c b/bpf/progs/netd.c index 60c5a1c2ea..7525f20e92 100644 --- a/bpf/progs/netd.c +++ b/bpf/progs/netd.c @@ -433,6 +433,20 @@ static __always_inline inline BpfConfig getConfig(uint32_t configKey) { return *config; } +static __always_inline inline uint8_t get_uid_permissions(uint32_t uid) { + /* + * A given app is guaranteed to have the same app ID in all the profiles in + * which it is installed, and install permission is granted to an app for all + * users at install time so we only check the appId part of a request uid at + * run time. See UserHandle#isSameApp for detail. + */ + uint32_t appId = uid % AID_USER_OFFSET; // == PER_USER_RANGE == 100000 + + uint8_t *permissions = bpf_uid_permission_map_lookup_elem(&appId); + // if UID not in map, then default to just INTERNET permission. + return permissions ? *permissions : BPF_PERMISSION_INTERNET; +} + static __always_inline inline bool ingress_should_discard(struct __sk_buff* skb, const struct kver_uint kver) { // Require 4.19, since earlier kernels don't have bpf_skb_load_bytes_relative() which @@ -496,8 +510,9 @@ static __always_inline inline int bpf_owner_match(struct __sk_buff* skb, uint32_ } } - if (SDK_LEVEL_IS_AT_LEAST(lvl, 25Q2) && skb->ifindex == 1) { - // TODO: sdksandbox localhost restrictions + if (SDK_LEVEL_IS_AT_LEAST(lvl, 25Q2) && skb->ifindex == 1 && is_sdksandbox_uid(uid)) { + // check if the UID is allowed localhost connections + if (!(get_uid_permissions(uid) & BPF_PERMISSION_SDKSANDBOX_LOCALHOST)) return DROP; } return PASS; @@ -759,17 +774,7 @@ DEFINE_XTBPF_PROG("skfilter/denylist/xtbpf", xt_bpf_denylist_prog) } static __always_inline inline uint8_t get_app_permissions() { - uint64_t gid_uid = bpf_get_current_uid_gid(); - /* - * A given app is guaranteed to have the same app ID in all the profiles in - * which it is installed, and install permission is granted to app for all - * user at install time so we only check the appId part of a request uid at - * run time. See UserHandle#isSameApp for detail. - */ - uint32_t appId = (gid_uid & 0xffffffff) % AID_USER_OFFSET; // == PER_USER_RANGE == 100000 - uint8_t* permissions = bpf_uid_permission_map_lookup_elem(&appId); - // if UID not in map, then default to just INTERNET permission. - return permissions ? *permissions : BPF_PERMISSION_INTERNET; + return get_uid_permissions(bpf_get_current_uid_gid() & 0xffffffff); } static __always_inline inline int inet_socket_create(struct bpf_sock* sk, diff --git a/bpf/progs/netd.h b/bpf/progs/netd.h index aa5f9cc9bf..9d80c69e03 100644 --- a/bpf/progs/netd.h +++ b/bpf/progs/netd.h @@ -215,10 +215,16 @@ enum UidOwnerMatchType : uint32_t { }; // LINT.ThenChange(../framework/src/android/net/BpfNetMapsConstants.java) +// LINT.IfChange(bpf_permission) +// The BpfPermissionMatch values should match the traffic permissions defined in NetworkPermissions: +// BPF_PERMISSION_ should have the same value that TRAFFIC_PERMISSION_ enum BpfPermissionMatch : uint8_t { BPF_PERMISSION_INTERNET = 1 << 2, BPF_PERMISSION_UPDATE_DEVICE_STATS = 1 << 3, + BPF_PERMISSION_SDKSANDBOX_LOCALHOST = 1 << 4, }; +// LINT.ThenChange(packages/modules/Connectivity/service/src/com/android/server/connectivity/NetworkPermissions.java) + // In production we use two identical stats maps to record per uid stats and // do swap and clean based on the configuration specified here. The statsMapType // value in configuration map specified which map is currently in use. @@ -293,3 +299,11 @@ static inline bool is_system_uid(uint32_t uid) { // MAX_SYSTEM_UID is AID_NOBODY == 9999, while AID_APP_START == 10000 return ((uid % AID_USER_OFFSET) < AID_APP_START); } + +static inline bool is_sdksandbox_uid(uint32_t uid) { + uint32_t appid = uid % AID_USER_OFFSET; + // AID_SDK_SANDBOX_PROCESS_START = 20000 + // AID_SDK_SANDBOX_PROCESS_END = 29999 + return appid >= AID_SDK_SANDBOX_PROCESS_START && + appid <= AID_SDK_SANDBOX_PROCESS_END; +}