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 #define _GNU_SOURCE /* for unshare() */
20 #include <sys/types.h>
21 #include <sys/socket.h>
24 #include <sys/select.h>
34 #include <sys/mount.h>
37 #include <sys/types.h>
42 #ifdef SUPERUSER_EMBEDDED
43 #include <cutils/multiuser.h>
50 int daemon_from_uid = 0;
51 int daemon_from_pid = 0;
53 static int read_int(int fd) {
55 int len = read(fd, &val, sizeof(int));
56 if (len != sizeof(int)) {
57 LOGE("unable to read int");
63 static void write_int(int fd, int val) {
64 int written = write(fd, &val, sizeof(int));
65 if (written != sizeof(int)) {
66 PLOGE("unable to write int");
71 static char* read_string(int fd) {
72 int len = read_int(fd);
73 if (len > PATH_MAX || len < 0) {
74 LOGE("invalid string length %d", len);
77 char* val = malloc(sizeof(char) * (len + 1));
79 LOGE("unable to malloc string");
83 int amount = read(fd, val, len);
85 LOGE("unable to read string");
91 static void write_string(int fd, char* val) {
92 int len = strlen(val);
94 int written = write(fd, val, len);
96 PLOGE("unable to write string");
101 #ifdef SUPERUSER_EMBEDDED
102 static void mount_emulated_storage(int user_id) {
103 const char *emulated_source = getenv("EMULATED_STORAGE_SOURCE");
104 const char *emulated_target = getenv("EMULATED_STORAGE_TARGET");
105 const char* legacy = getenv("EXTERNAL_STORAGE");
107 if (!emulated_source || !emulated_target) {
108 // No emulated storage is present
112 // Create a second private mount namespace for our process
113 if (unshare(CLONE_NEWNS) < 0) {
118 if (mount("rootfs", "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
119 PLOGE("mount rootfs as slave");
123 // /mnt/shell/emulated -> /storage/emulated
124 if (mount(emulated_source, emulated_target, NULL, MS_BIND, NULL) < 0) {
125 PLOGE("mount emulated storage");
128 char target_user[PATH_MAX];
129 snprintf(target_user, PATH_MAX, "%s/%d", emulated_target, user_id);
131 // /mnt/shell/emulated/<user> -> /storage/emulated/legacy
132 if (mount(target_user, legacy, NULL, MS_BIND | MS_REC, NULL) < 0) {
133 PLOGE("mount legacy path");
138 static int run_daemon_child(int infd, int outfd, int errfd, int argc, char** argv) {
139 if (-1 == dup2(outfd, STDOUT_FILENO)) {
140 PLOGE("dup2 child outfd");
144 if (-1 == dup2(errfd, STDERR_FILENO)) {
145 PLOGE("dup2 child errfd");
149 if (-1 == dup2(infd, STDIN_FILENO)) {
150 PLOGE("dup2 child infd");
158 return su_main(argc, argv, 0);
161 static void pump(int input, int output) {
164 while ((len = read(input, buf, 4096)) > 0) {
165 write(output, buf, len);
171 static void* pump_thread(void* data) {
172 int* files = (int*)data;
173 int input = files[0];
174 int output = files[1];
180 static void pump_async(int input, int output) {
182 int* files = (int*)malloc(sizeof(int) * 2);
184 LOGE("unable to pump_async");
189 pthread_create(&writer, NULL, pump_thread, files);
192 static int daemon_accept(int fd) {
194 int pid = read_int(fd);
195 LOGV("remote pid: %d", pid);
196 int atty = read_int(fd);
197 LOGV("remote atty: %d", atty);
198 daemon_from_uid = read_int(fd);
199 LOGV("remote uid: %d", daemon_from_uid);
200 daemon_from_pid = read_int(fd);
201 LOGV("remote req pid: %d", daemon_from_pid);
203 struct ucred credentials;
204 int ucred_length = sizeof(struct ucred);
205 /* fill in the user data structure */
206 if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &credentials, &ucred_length)) {
207 LOGE("could obtain credentials from unix domain socket");
210 // if the credentials on the other side of the wire are NOT root,
211 // we can't trust anything being sent.
212 if (credentials.uid != 0) {
213 daemon_from_uid = credentials.uid;
214 pid = credentials.pid;
215 daemon_from_pid = credentials.pid;
218 int mount_storage = read_int(fd);
219 int argc = read_int(fd);
220 if (argc < 0 || argc > 512) {
221 LOGE("unable to allocate args: %d", argc);
224 LOGV("remote args: %d", argc);
225 char** argv = (char**)malloc(sizeof(char*) * (argc + 1));
228 for (i = 0; i < argc; i++) {
229 argv[i] = read_string(fd);
232 char errfile[PATH_MAX];
233 char outfile[PATH_MAX];
234 char infile[PATH_MAX];
235 sprintf(outfile, "%s/%d.stdout", REQUESTOR_DAEMON_PATH, pid);
236 sprintf(errfile, "%s/%d.stderr", REQUESTOR_DAEMON_PATH, pid);
237 sprintf(infile, "%s/%d.stdin", REQUESTOR_DAEMON_PATH, pid);
239 if (mkfifo(outfile, 0660) != 0) {
240 PLOGE("mkfifo %s", outfile);
243 if (mkfifo(errfile, 0660) != 0) {
244 PLOGE("mkfifo %s", errfile);
247 if (mkfifo(infile, 0660) != 0) {
248 PLOGE("mkfifo %s", infile);
252 chown(outfile, daemon_from_uid, 0);
253 chown(infile, daemon_from_uid, 0);
254 chown(errfile, daemon_from_uid, 0);
255 chmod(outfile, 0660);
257 chmod(errfile, 0660);
263 char* devname = NULL;
265 ptm = open("/dev/ptmx", O_RDWR);
270 if(grantpt(ptm) || unlockpt(ptm) || ((devname = (char*) ptsname(ptm)) == 0)) {
275 LOGV("devname: %s", devname);
278 int outfd = open(outfile, O_WRONLY);
280 PLOGE("outfd daemon %s", outfile);
283 int errfd = open(errfile, O_WRONLY);
285 PLOGE("errfd daemon %s", errfile);
288 int infd = open(infile, O_RDONLY);
290 PLOGE("infd daemon %s", infile);
295 // now fork and run main, watch for the child pid exit, and send that
296 // across the control channel as the response.
303 // if this is the child, open the fifo streams
304 // and dup2 them with stdin/stdout, and run main, which execs
309 if (devname != NULL) {
310 int pts = open(devname, O_RDWR);
316 struct termios slave_orig_term_settings; // Saved terminal settings
317 tcgetattr(pts, &slave_orig_term_settings);
319 struct termios new_term_settings;
320 new_term_settings = slave_orig_term_settings;
321 cfmakeraw(&new_term_settings);
322 // WHY DOESN'T THIS WORK, FUUUUU
323 new_term_settings.c_lflag &= ~(ECHO);
324 tcsetattr(pts, TCSANOW, &new_term_settings);
327 ioctl(pts, TIOCSCTTY, 1);
339 #ifdef SUPERUSER_EMBEDDED
341 mount_emulated_storage(multiuser_get_user_id(daemon_from_uid));
345 return run_daemon_child(infd, outfd, errfd, argc, argv);
348 if (devname != NULL) {
349 // pump ptm across the socket
350 pump_async(infd, ptm);
359 // wait for the child to exit, and send the exit code
362 LOGV("waiting for child exit");
363 if (waitpid(child, &status, 0) > 0) {
364 code = WEXITSTATUS(status);
371 write(fd, &code, sizeof(int));
373 LOGV("child exited");
378 if (getuid() != 0 || getgid() != 0) {
379 PLOGE("daemon requires root. uid/gid not root");
384 struct sockaddr_un sun;
386 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
391 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
392 PLOGE("fcntl FD_CLOEXEC");
396 memset(&sun, 0, sizeof(sun));
397 sun.sun_family = AF_LOCAL;
398 sprintf(sun.sun_path, "%s/server", REQUESTOR_DAEMON_PATH);
401 * Delete the socket to protect from situations when
402 * something bad occured previously and the kernel reused pid from that process.
403 * Small probability, isn't it.
405 unlink(sun.sun_path);
406 unlink(REQUESTOR_DAEMON_PATH);
408 int previous_umask = umask(027);
409 mkdir(REQUESTOR_DAEMON_PATH, 0777);
411 if (bind(fd, (struct sockaddr*)&sun, sizeof(sun)) < 0) {
412 PLOGE("daemon bind");
416 chmod(REQUESTOR_DAEMON_PATH, 0755);
417 chmod(sun.sun_path, 0777);
419 umask(previous_umask);
421 if (listen(fd, 10) < 0) {
422 PLOGE("daemon listen");
427 while ((client = accept(fd, NULL, NULL)) > 0) {
428 if (fork_zero_fucks() == 0) {
430 return daemon_accept(client);
437 LOGE("daemon exiting");
443 int connect_daemon(int argc, char *argv[]) {
444 char errfile[PATH_MAX];
445 char outfile[PATH_MAX];
446 char infile[PATH_MAX];
448 sprintf(outfile, "%s/%d.stdout", REQUESTOR_DAEMON_PATH, getpid());
449 sprintf(errfile, "%s/%d.stderr", REQUESTOR_DAEMON_PATH, getpid());
450 sprintf(infile, "%s/%d.stdin", REQUESTOR_DAEMON_PATH, getpid());
455 struct sockaddr_un sun;
457 int socketfd = socket(AF_LOCAL, SOCK_STREAM, 0);
462 if (fcntl(socketfd, F_SETFD, FD_CLOEXEC)) {
463 PLOGE("fcntl FD_CLOEXEC");
467 memset(&sun, 0, sizeof(sun));
468 sun.sun_family = AF_LOCAL;
469 sprintf(sun.sun_path, "%s/server", REQUESTOR_DAEMON_PATH);
471 if (0 != connect(socketfd, (struct sockaddr*)&sun, sizeof(sun))) {
476 LOGV("connecting client %d", getpid());
478 int mount_storage = getenv("MOUNT_EMULATED_STORAGE") != NULL;
480 write_int(socketfd, getpid());
481 write_int(socketfd, isatty(STDIN_FILENO));
482 write_int(socketfd, uid);
483 write_int(socketfd, getppid());
484 write_int(socketfd, mount_storage);
485 write_int(socketfd, mount_storage ? argc - 1 : argc);
488 for (i = 0; i < argc; i++) {
489 if (i == 1 && mount_storage) {
492 write_string(socketfd, argv[i]);
498 int outfd = open(outfile, O_RDONLY);
500 PLOGE("outfd %s ", outfile);
503 int errfd = open(errfile, O_RDONLY);
505 PLOGE("errfd %s", errfile);
508 int infd = open(infile, O_WRONLY);
510 PLOGE("infd %s", infile);
514 pump_async(STDIN_FILENO, infd);
515 pump_async(errfd, STDERR_FILENO);
516 pump(outfd, STDOUT_FILENO);
518 int code = read_int(socketfd);
519 LOGV("client exited %d", code);