OSDN Git Service

multiuser all working
[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 static void kill_child(pid_t pid) {
30     LOGD("killing child %d", pid);
31     if (pid) {
32         sigset_t set, old;
33
34         sigemptyset(&set);
35         sigaddset(&set, SIGCHLD);
36         if (sigprocmask(SIG_BLOCK, &set, &old)) {
37             PLOGE("sigprocmask(SIG_BLOCK)");
38             return;
39         }
40         if (kill(pid, SIGKILL))
41             PLOGE("kill (%d)", pid);
42         else if (sigsuspend(&old) && errno != EINTR)
43             PLOGE("sigsuspend");
44         if (sigprocmask(SIG_SETMASK, &old, NULL))
45             PLOGE("sigprocmask(SIG_BLOCK)");
46     }
47 }
48
49 // TODO: leverage this with exec_log?
50 static int silent_run(char* command) {
51     char *args[] = { "sh", "-c", command, NULL, };
52     set_identity(0);
53     pid_t pid;
54     pid = fork();
55     /* Parent */
56     if (pid < 0) {
57         PLOGE("fork");
58         return -1;
59     }
60     else if (pid > 0) {
61         return 0;
62     }
63     int zero = open("/dev/zero", O_RDONLY | O_CLOEXEC);
64     dup2(zero, 0);
65     int null = open("/dev/null", O_WRONLY | O_CLOEXEC);
66     dup2(null, 1);
67     dup2(null, 2);
68     execv(_PATH_BSHELL, args);
69     PLOGE("exec am");
70     _exit(EXIT_FAILURE);
71     return -1;
72 }
73
74 int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
75     int needs_owner_login_prompt = 0;
76     
77     if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
78         if (0 != ctx->user.android_user_id) {
79             needs_owner_login_prompt = 1;
80         }
81         snprintf(user, user_len, "--user 0");
82     }
83     else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
84         snprintf(user, user_len, "--user %d", ctx->user.android_user_id);
85     }
86     else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
87         snprintf(user, user_len, "");
88     }
89     else {
90         snprintf(user, user_len, "--user 0");
91     }
92     
93     return needs_owner_login_prompt;
94 }
95
96 int send_result(struct su_context *ctx, policy_t policy) {
97     char user[64];
98     get_owner_login_user_args(ctx, user, sizeof(user));
99     
100     if (0 != ctx->user.android_user_id) {
101         char user_result_command[ARG_MAX];
102         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",
103             VERSION_CODE,
104             ctx->from.name, ctx->to.name,
105             ctx->from.uid, ctx->to.uid, get_command(&ctx->to), policy == ALLOW ? "allow" : "deny", ctx->user.android_user_id);
106         silent_run(user_result_command);
107         LOGD(user_result_command);
108     }
109
110     char result_command[ARG_MAX];
111     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",
112         VERSION_CODE,
113         ctx->from.name, ctx->to.name,
114         ctx->from.uid, ctx->to.uid, get_command(&ctx->to), policy == ALLOW ? "allow" : "deny", user);
115     return silent_run(result_command);
116 }
117
118 int send_request(struct su_context *ctx) {
119     // if su is operating in MULTIUSER_MODEL_OWNER,
120     // and the user requestor is not the owner,
121     // the owner needs to be notified of the request.
122     // so there will be two activities shown.
123     char user[64];
124     int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
125
126     int ret;
127     if (needs_owner_login_prompt) {
128         // in multiuser mode, the owner gets the su prompt
129         char notify_command[ARG_MAX];
130
131         // start the activity that confirms the request
132         snprintf(notify_command, sizeof(notify_command),
133             "exec /system/bin/am " ACTION_NOTIFY " --ei caller_uid %d --user %d",
134             ctx->from.uid, ctx->user.android_user_id);
135
136         int ret = silent_run(notify_command);
137         if (ret) {
138             return ret;
139         }
140     }
141
142     char request_command[ARG_MAX];
143
144     // start the activity that confirms the request
145     snprintf(request_command, sizeof(request_command),
146         "exec /system/bin/am " ACTION_REQUEST " --es socket '%s' %s",
147         ctx->sock_path, user);
148
149     return silent_run(request_command);
150 }