OSDN Git Service

9bda4f9838995def443173f39b8abf957de40e48
[android-x86/external-koush-Superuser.git] / Superuser / jni / su / activity.c
1 /*
2 ** Copyright 2010, Adam Shanks (@ChainsDD)
3 ** Copyright 2008, Zinx Verituse (@zinxv)
4 **
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
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
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.
16 */
17
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <fcntl.h>
23 #include <paths.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #include "su.h"
28
29 // TODO: leverage this with exec_log?
30 int silent_run(char* command) {
31     char *args[] = { "sh", "-c", command, NULL, };
32     set_identity(0);
33     pid_t pid;
34     pid = fork();
35     /* Parent */
36     if (pid < 0) {
37         PLOGE("fork");
38         return -1;
39     }
40     else if (pid > 0) {
41         return 0;
42     }
43     int zero = open("/dev/zero", O_RDONLY | O_CLOEXEC);
44     dup2(zero, 0);
45     int null = open("/dev/null", O_WRONLY | O_CLOEXEC);
46     dup2(null, 1);
47     dup2(null, 2);
48     execv(_PATH_BSHELL, args);
49     PLOGE("exec am");
50     _exit(EXIT_FAILURE);
51     return -1;
52 }
53
54 int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
55     int needs_owner_login_prompt = 0;
56     
57     if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
58         if (0 != ctx->user.android_user_id) {
59             needs_owner_login_prompt = 1;
60         }
61         snprintf(user, user_len, "--user 0");
62     }
63     else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
64         snprintf(user, user_len, "--user %d", ctx->user.android_user_id);
65     }
66     else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
67         user[0] = '\0';
68     }
69     else {
70         snprintf(user, user_len, "--user 0");
71     }
72     
73     return needs_owner_login_prompt;
74 }
75
76 int send_result(struct su_context *ctx, policy_t policy) {
77     char user[64];
78     get_owner_login_user_args(ctx, user, sizeof(user));
79     
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",
83             VERSION_CODE,
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);
87     }
88
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",
91         VERSION_CODE,
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);
95 }
96
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.
102     char user[64];
103     int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
104
105     int ret;
106     if (needs_owner_login_prompt) {
107         // in multiuser mode, the owner gets the su prompt
108         char notify_command[ARG_MAX];
109
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);
114
115         int ret = silent_run(notify_command);
116         if (ret) {
117             return ret;
118         }
119     }
120
121     char request_command[ARG_MAX];
122
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);
127
128     return silent_run(request_command);
129 }