2 ** Copyright 2010, Adam Shanks (@ChainsDD)
3 ** Copyright 2008, Zinx Verituse (@zinxv)
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
9 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
18 #include <sys/types.h>
29 // TODO: leverage this with exec_log?
30 int silent_run(char* command) {
31 char *args[] = { "sh", "-c", command, NULL, };
43 int zero = open("/dev/zero", O_RDONLY | O_CLOEXEC);
45 int null = open("/dev/null", O_WRONLY | O_CLOEXEC);
48 execv(_PATH_BSHELL, args);
54 int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
55 int needs_owner_login_prompt = 0;
57 if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
58 if (0 != ctx->user.android_user_id) {
59 needs_owner_login_prompt = 1;
61 snprintf(user, user_len, "--user 0");
63 else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
64 snprintf(user, user_len, "--user %d", ctx->user.android_user_id);
66 else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
70 snprintf(user, user_len, "--user 0");
73 return needs_owner_login_prompt;
76 int send_result(struct su_context *ctx, policy_t policy) {
78 get_owner_login_user_args(ctx, user, sizeof(user));
80 if (0 != ctx->user.android_user_id) {
81 char user_result_command[ARG_MAX];
82 snprintf(user_result_command, sizeof(user_result_command), "exec /system/bin/am " ACTION_RESULT " --ei binary_version %d --es from_name '%s' --es desired_name '%s' --ei uid %d --ei desired_uid %d --es command '%s' --es action %s --user %d",
84 ctx->from.name, ctx->to.name,
85 ctx->from.uid, ctx->to.uid, get_command(&ctx->to), policy == ALLOW ? "allow" : "deny", ctx->user.android_user_id);
86 silent_run(user_result_command);
89 char result_command[ARG_MAX];
90 snprintf(result_command, sizeof(result_command), "exec /system/bin/am " ACTION_RESULT " --ei binary_version %d --es from_name '%s' --es desired_name '%s' --ei uid %d --ei desired_uid %d --es command '%s' --es action %s %s",
92 ctx->from.name, ctx->to.name,
93 ctx->from.uid, ctx->to.uid, get_command(&ctx->to), policy == ALLOW ? "allow" : "deny", user);
94 return silent_run(result_command);
97 int send_request(struct su_context *ctx) {
98 // if su is operating in MULTIUSER_MODEL_OWNER,
99 // and the user requestor is not the owner,
100 // the owner needs to be notified of the request.
101 // so there will be two activities shown.
103 int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
106 if (needs_owner_login_prompt) {
107 // in multiuser mode, the owner gets the su prompt
108 char notify_command[ARG_MAX];
110 // start the activity that confirms the request
111 snprintf(notify_command, sizeof(notify_command),
112 "exec /system/bin/am " ACTION_NOTIFY " --ei caller_uid %d --user %d",
113 ctx->from.uid, ctx->user.android_user_id);
115 int ret = silent_run(notify_command);
121 char request_command[ARG_MAX];
123 // start the activity that confirms the request
124 snprintf(request_command, sizeof(request_command),
125 "exec /system/bin/am " ACTION_REQUEST " --es socket '%s' %s",
126 ctx->sock_path, user);
128 return silent_run(request_command);