int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
int needs_owner_login_prompt = 0;
- if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) {
- snprintf(user, user_len, "");
- }
- else if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER) {
+
+ if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
if (0 != ctx->user.android_user_id) {
needs_owner_login_prompt = 1;
}
else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
snprintf(user, user_len, "--user %d", ctx->user.android_user_id);
}
+ else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
+ snprintf(user, user_len, "");
+ }
else {
- // unknown mode?
- return -1;
+ snprintf(user, user_len, "--user 0");
}
return needs_owner_login_prompt;
int send_result(struct su_context *ctx, policy_t policy) {
char user[64];
int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
- if (needs_owner_login_prompt == -1)
- return -1;
char result_command[ARG_MAX];
- snprintf(result_command, sizeof(result_command), "exec /system/bin/am " ACTION_RESULT " --es from_name '%s' --es desired_name '%s' --ei uid %d --ei desired_uid %d --es command '%s' --es action %s %s",
+ 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",
+ VERSION_CODE,
ctx->from.name, ctx->to.name,
ctx->from.uid, ctx->to.uid, get_command(&ctx->to), policy == ALLOW ? "allow" : "deny", user);
- LOGD(result_command);
+ // LOGD(result_command);
return silent_run(result_command);
}
// so there will be two activities shown.
char user[64];
int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));
- if (needs_owner_login_prompt == -1)
- return -1;
-
int ret;
if (needs_owner_login_prompt) {
return 0;
}
-static void read_options(struct su_context *ctx) {
+static int get_multiuser_mode() {
+ char *data;
+ char sdk_ver[PROPERTY_VALUE_MAX];
+
+ data = read_file("/system/build.prop");
+ get_property(data, sdk_ver, "ro.build.version.sdk", "0");
+ free(data);
+
+ int sdk = atoi(sdk_ver);
+ if (sdk < 16)
+ return MULTIUSER_MODE_NONE;
+
+ int ret = MULTIUSER_MODE_OWNER_ONLY;
char mode[12];
FILE *fp;
if ((fp = fopen(REQUESTOR_MULTIUSER_MODE, "r"))) {
+ int last = strlen(mode) - 1;
+ if (mode[last] == '\n')
+ mode[last] = '\0';
fgets(mode, sizeof(mode), fp);
LOGD("multiuser mode: %s", mode);
- if (strcmp(mode, "user\n") == 0) {
- ctx->user.multiuser_mode = MULTIUSER_MODE_USER;
- } else if (strcmp(mode, "owner\n") == 0) {
- ctx->user.multiuser_mode = MULTIUSER_MODE_OWNER;
+ if (strcmp(mode, MULTIUSER_VALUE_USER) == 0) {
+ ret = MULTIUSER_MODE_USER;
+ } else if (strcmp(mode, MULTIUSER_VALUE_OWNER_MANAGED) == 0) {
+ ret = MULTIUSER_MODE_OWNER_MANAGED;
+ }
+ else {
+ ret = MULTIUSER_MODE_OWNER_ONLY;
}
fclose(fp);
}
+ return ret;
+}
+
+static void read_options(struct su_context *ctx) {
+ ctx->user.multiuser_mode = get_multiuser_mode();
}
static void user_init(struct su_context *ctx) {
" -m, -p,\n"
" --preserve-environment do not change environment variables\n"
" -s, --shell SHELL use SHELL instead of the default " DEFAULT_SHELL "\n"
+ " -u display the multiuser mode and exit\n"
" -v, --version display version number and exit\n"
" -V display version code and exit,\n"
" this is used almost exclusively by Superuser.apk\n");
{ NULL, 0, NULL, 0 },
};
- while ((c = getopt_long(argc, argv, "+c:hlmps:Vv", long_opts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "+c:hlmps:Vvu", long_opts, NULL)) != -1) {
switch(c) {
case 'c':
ctx.to.command = optarg;
case 'v':
printf("%s\n", VERSION);
exit(EXIT_SUCCESS);
+ case 'u':
+ switch (get_multiuser_mode()) {
+ case MULTIUSER_MODE_USER:
+ printf("%s\n", MULTIUSER_VALUE_USER);
+ break;
+ case MULTIUSER_MODE_OWNER_MANAGED:
+ printf("%s\n", MULTIUSER_VALUE_OWNER_MANAGED);
+ break;
+ case MULTIUSER_MODE_OWNER_ONLY:
+ printf("%s\n", MULTIUSER_VALUE_OWNER_ONLY);
+ break;
+ case MULTIUSER_MODE_NONE:
+ printf("%s\n", MULTIUSER_VALUE_NONE);
+ break;
+ }
+ exit(EXIT_SUCCESS);
default:
/* Bionic getopt_long doesn't terminate its error output by newline */
fprintf(stderr, "\n");
// only owner can su
MULTIUSER_MODE_OWNER_ONLY = 0,
// owner gets a su prompt
- MULTIUSER_MODE_OWNER = 1,
+ MULTIUSER_MODE_OWNER_MANAGED = 1,
// user gets a su prompt
MULTIUSER_MODE_USER = 2,
+ MULTIUSER_MODE_NONE = 3,
} multiuser_mode_t;
+#define MULTIUSER_VALUE_OWNER_ONLY "owner"
+#define MULTIUSER_VALUE_OWNER_MANAGED "managed"
+#define MULTIUSER_VALUE_USER "user"
+#define MULTIUSER_VALUE_NONE "none"
+
typedef enum {
INTERACTIVE = 0,
DENY = 1,