1*dd0948b3SAndroid Build Coastguard Worker /*
2*dd0948b3SAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*dd0948b3SAndroid Build Coastguard Worker *
4*dd0948b3SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*dd0948b3SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*dd0948b3SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*dd0948b3SAndroid Build Coastguard Worker *
8*dd0948b3SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*dd0948b3SAndroid Build Coastguard Worker *
10*dd0948b3SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*dd0948b3SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*dd0948b3SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*dd0948b3SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*dd0948b3SAndroid Build Coastguard Worker * limitations under the License.
15*dd0948b3SAndroid Build Coastguard Worker */
16*dd0948b3SAndroid Build Coastguard Worker
17*dd0948b3SAndroid Build Coastguard Worker #include "./context.h"
18*dd0948b3SAndroid Build Coastguard Worker
19*dd0948b3SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h> // For AID_APP_START.
20*dd0948b3SAndroid Build Coastguard Worker #include <stdio.h>
21*dd0948b3SAndroid Build Coastguard Worker #include <stdlib.h>
22*dd0948b3SAndroid Build Coastguard Worker
23*dd0948b3SAndroid Build Coastguard Worker #include <iostream>
24*dd0948b3SAndroid Build Coastguard Worker #include <string>
25*dd0948b3SAndroid Build Coastguard Worker
26*dd0948b3SAndroid Build Coastguard Worker #include "./string-utils.h"
27*dd0948b3SAndroid Build Coastguard Worker #include "./test-app.h"
28*dd0948b3SAndroid Build Coastguard Worker
29*dd0948b3SAndroid Build Coastguard Worker namespace shell_as {
30*dd0948b3SAndroid Build Coastguard Worker
31*dd0948b3SAndroid Build Coastguard Worker namespace {
32*dd0948b3SAndroid Build Coastguard Worker
ParseIdFromProcStatusLine(char * line,uid_t * id)33*dd0948b3SAndroid Build Coastguard Worker bool ParseIdFromProcStatusLine(char* line, uid_t* id) {
34*dd0948b3SAndroid Build Coastguard Worker // The user and group ID lines of the status file look like:
35*dd0948b3SAndroid Build Coastguard Worker //
36*dd0948b3SAndroid Build Coastguard Worker // Uid: <real> <effective> <saved> <filesystem>
37*dd0948b3SAndroid Build Coastguard Worker // Gid: <real> <effective> <saved> <filesystem>
38*dd0948b3SAndroid Build Coastguard Worker std::vector<uid_t> ids;
39*dd0948b3SAndroid Build Coastguard Worker if (!SplitIdsAndSkip(line, "\t\n ", /*num_to_skip=*/1, &ids) ||
40*dd0948b3SAndroid Build Coastguard Worker ids.size() < 1) {
41*dd0948b3SAndroid Build Coastguard Worker return false;
42*dd0948b3SAndroid Build Coastguard Worker }
43*dd0948b3SAndroid Build Coastguard Worker *id = ids[0];
44*dd0948b3SAndroid Build Coastguard Worker return true;
45*dd0948b3SAndroid Build Coastguard Worker }
46*dd0948b3SAndroid Build Coastguard Worker
ParseGroupsFromProcStatusLine(char * line,std::vector<gid_t> * ids)47*dd0948b3SAndroid Build Coastguard Worker bool ParseGroupsFromProcStatusLine(char* line, std::vector<gid_t>* ids) {
48*dd0948b3SAndroid Build Coastguard Worker // The supplementary groups line of the status file looks like:
49*dd0948b3SAndroid Build Coastguard Worker //
50*dd0948b3SAndroid Build Coastguard Worker // Groups: <group1> <group2> <group3> ...
51*dd0948b3SAndroid Build Coastguard Worker return SplitIdsAndSkip(line, "\t\n ", /*num_to_skip=*/1, ids);
52*dd0948b3SAndroid Build Coastguard Worker }
53*dd0948b3SAndroid Build Coastguard Worker
ParseProcStatusFile(const pid_t process_id,uid_t * real_user_id,gid_t * real_group_id,std::vector<gid_t> * supplementary_group_ids)54*dd0948b3SAndroid Build Coastguard Worker bool ParseProcStatusFile(const pid_t process_id, uid_t* real_user_id,
55*dd0948b3SAndroid Build Coastguard Worker gid_t* real_group_id,
56*dd0948b3SAndroid Build Coastguard Worker std::vector<gid_t>* supplementary_group_ids) {
57*dd0948b3SAndroid Build Coastguard Worker std::string proc_status_path =
58*dd0948b3SAndroid Build Coastguard Worker std::string("/proc/") + std::to_string(process_id) + "/status";
59*dd0948b3SAndroid Build Coastguard Worker FILE* status_file = fopen(proc_status_path.c_str(), "r");
60*dd0948b3SAndroid Build Coastguard Worker if (status_file == nullptr) {
61*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Unable to open '" << proc_status_path << "'" << std::endl;
62*dd0948b3SAndroid Build Coastguard Worker }
63*dd0948b3SAndroid Build Coastguard Worker bool parsed_user = false;
64*dd0948b3SAndroid Build Coastguard Worker bool parsed_group = false;
65*dd0948b3SAndroid Build Coastguard Worker bool parsed_supplementary_groups = false;
66*dd0948b3SAndroid Build Coastguard Worker while (true) {
67*dd0948b3SAndroid Build Coastguard Worker size_t line_length = 0;
68*dd0948b3SAndroid Build Coastguard Worker char* line = nullptr;
69*dd0948b3SAndroid Build Coastguard Worker if (getline(&line, &line_length, status_file) < 0) {
70*dd0948b3SAndroid Build Coastguard Worker free(line);
71*dd0948b3SAndroid Build Coastguard Worker break;
72*dd0948b3SAndroid Build Coastguard Worker }
73*dd0948b3SAndroid Build Coastguard Worker if (strncmp("Uid:", line, 4) == 0) {
74*dd0948b3SAndroid Build Coastguard Worker parsed_user = ParseIdFromProcStatusLine(line, real_user_id);
75*dd0948b3SAndroid Build Coastguard Worker } else if (strncmp("Gid:", line, 4) == 0) {
76*dd0948b3SAndroid Build Coastguard Worker parsed_group = ParseIdFromProcStatusLine(line, real_group_id);
77*dd0948b3SAndroid Build Coastguard Worker } else if (strncmp("Groups:", line, 7) == 0) {
78*dd0948b3SAndroid Build Coastguard Worker parsed_supplementary_groups =
79*dd0948b3SAndroid Build Coastguard Worker ParseGroupsFromProcStatusLine(line, supplementary_group_ids);
80*dd0948b3SAndroid Build Coastguard Worker }
81*dd0948b3SAndroid Build Coastguard Worker free(line);
82*dd0948b3SAndroid Build Coastguard Worker }
83*dd0948b3SAndroid Build Coastguard Worker fclose(status_file);
84*dd0948b3SAndroid Build Coastguard Worker return parsed_user && parsed_group && parsed_supplementary_groups;
85*dd0948b3SAndroid Build Coastguard Worker }
86*dd0948b3SAndroid Build Coastguard Worker
87*dd0948b3SAndroid Build Coastguard Worker } // namespace
88*dd0948b3SAndroid Build Coastguard Worker
SecurityContextFromProcess(const pid_t process_id,SecurityContext * context)89*dd0948b3SAndroid Build Coastguard Worker bool SecurityContextFromProcess(const pid_t process_id,
90*dd0948b3SAndroid Build Coastguard Worker SecurityContext* context) {
91*dd0948b3SAndroid Build Coastguard Worker char* selinux_context;
92*dd0948b3SAndroid Build Coastguard Worker if (getpidcon(process_id, &selinux_context) != 0) {
93*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Unable to obtain SELinux context from process " << process_id
94*dd0948b3SAndroid Build Coastguard Worker << std::endl;
95*dd0948b3SAndroid Build Coastguard Worker return false;
96*dd0948b3SAndroid Build Coastguard Worker }
97*dd0948b3SAndroid Build Coastguard Worker
98*dd0948b3SAndroid Build Coastguard Worker cap_t capabilities = cap_get_pid(process_id);
99*dd0948b3SAndroid Build Coastguard Worker if (capabilities == nullptr) {
100*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Unable to obtain capability set from process " << process_id
101*dd0948b3SAndroid Build Coastguard Worker << std::endl;
102*dd0948b3SAndroid Build Coastguard Worker return false;
103*dd0948b3SAndroid Build Coastguard Worker }
104*dd0948b3SAndroid Build Coastguard Worker
105*dd0948b3SAndroid Build Coastguard Worker uid_t user_id = 0;
106*dd0948b3SAndroid Build Coastguard Worker gid_t group_id = 0;
107*dd0948b3SAndroid Build Coastguard Worker std::vector<gid_t> supplementary_group_ids;
108*dd0948b3SAndroid Build Coastguard Worker if (!ParseProcStatusFile(process_id, &user_id, &group_id,
109*dd0948b3SAndroid Build Coastguard Worker &supplementary_group_ids)) {
110*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Unable to obtain user and group IDs from process "
111*dd0948b3SAndroid Build Coastguard Worker << process_id << std::endl;
112*dd0948b3SAndroid Build Coastguard Worker return false;
113*dd0948b3SAndroid Build Coastguard Worker }
114*dd0948b3SAndroid Build Coastguard Worker
115*dd0948b3SAndroid Build Coastguard Worker context->selinux_context = selinux_context;
116*dd0948b3SAndroid Build Coastguard Worker context->user_id = user_id;
117*dd0948b3SAndroid Build Coastguard Worker context->group_id = group_id;
118*dd0948b3SAndroid Build Coastguard Worker context->supplementary_group_ids = supplementary_group_ids;
119*dd0948b3SAndroid Build Coastguard Worker context->capabilities = capabilities;
120*dd0948b3SAndroid Build Coastguard Worker return true;
121*dd0948b3SAndroid Build Coastguard Worker }
122*dd0948b3SAndroid Build Coastguard Worker
SecurityContextFromTestApp(SecurityContext * context)123*dd0948b3SAndroid Build Coastguard Worker bool SecurityContextFromTestApp(SecurityContext* context) {
124*dd0948b3SAndroid Build Coastguard Worker pid_t test_app_pid = 0;
125*dd0948b3SAndroid Build Coastguard Worker if (!SetupAndStartTestApp(&test_app_pid)) {
126*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Unable to install test app." << std::endl;
127*dd0948b3SAndroid Build Coastguard Worker return false;
128*dd0948b3SAndroid Build Coastguard Worker }
129*dd0948b3SAndroid Build Coastguard Worker return SecurityContextFromProcess(test_app_pid, context);
130*dd0948b3SAndroid Build Coastguard Worker }
131*dd0948b3SAndroid Build Coastguard Worker
SeccompFilterFromUserId(uid_t user_id)132*dd0948b3SAndroid Build Coastguard Worker SeccompFilter SeccompFilterFromUserId(uid_t user_id) {
133*dd0948b3SAndroid Build Coastguard Worker // Copied from:
134*dd0948b3SAndroid Build Coastguard Worker // frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
135*dd0948b3SAndroid Build Coastguard Worker return user_id >= AID_APP_START ? kAppFilter : kSystemFilter;
136*dd0948b3SAndroid Build Coastguard Worker }
137*dd0948b3SAndroid Build Coastguard Worker
138*dd0948b3SAndroid Build Coastguard Worker } // namespace shell_as
139