1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/*
* Utility routine to fork zygote and specialize the child process.
*/
static
pid_t forkAndSpecializeCommon(
const
u4* args, bool isSystemServer)
{
pid_t pid;
uid_t uid = (uid_t) args[
0
];
gid_t gid = (gid_t) args[
1
];
ArrayObject* gids = (ArrayObject *)args[
2
];
......
pid = fork();
if
(pid ==
0
) {
......
err = setgroupsIntarray(gids);
......
err = setgid(gid);
......
err = setuid(uid);
......
}
.....
return
pid;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
staticint ptrace_attach(struct task_struct *task,
long
request,
unsigned
long
addr,
unsigned
long
flags)
{
......
task_lock(task);
retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
task_unlock(task);
if
(retval)
goto
unlock_creds;
......
unlock_creds:
mutex_unlock(&task->signal->cred_guard_mutex);
out:
......
return
retval;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
int
__ptrace_may_access(struct task_struct *task, unsigned
int
mode)
{
conststruct cred *cred = current_cred(), *tcred;
......
if
(task == current)
return
0
;
rcu_read_lock();
tcred = __task_cred(task);
if
(cred->user->user_ns == tcred->user->user_ns &&
(cred->uid == tcred->euid &&
cred->uid == tcred->suid &&
cred->uid == tcred->uid &&
cred->gid == tcred->egid &&
cred->gid == tcred->sgid &&
cred->gid == tcred->gid))
goto
ok;
if
(ptrace_has_cap(tcred->user->user_ns, mode))
goto
ok;
rcu_read_unlock();
return
-EPERM;
ok:
......
return
security_ptrace_access_check(task, mode);
}
|
1
2
|
root@android:/ # ls -l /system/bin/run-as
-rwsr-s--- root shell 9528 2013-12-05 05:32 run-as
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int
__ptrace_may_access(struct task_struct *task, unsigned
int
mode)
{
conststruct cred *cred = current_cred(), *tcred;
......
int
dumpable =
0
;
......
ok:
rcu_read_unlock();
smp_rmb();
if
(task->mm)
dumpable = get_dumpable(task->mm);
if
(!dumpable && !ptrace_has_cap(task_user_ns(task), mode))
return
-EPERM;
return
security_ptrace_access_check(task, mode);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
static
pid_t forkAndSpecializeCommon(
const
u4* args, bool isSystemServer)
{
pid_t pid;
......
u4 debugFlags = args[
3
];
......
pid = fork();
if
(pid ==
0
) {
......
/* configure additional debug options */
enableDebugFeatures(debugFlags);
......
}
......
return
pid;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
void
enableDebugFeatures(u4 debugFlags)
{
......
if
((debugFlags & DEBUG_ENABLE_DEBUGGER) !=
0
) {
/* To let a non-privileged gdbserver attach to this
* process, we must set its dumpable bit flag. However
* we are not interested in generating a coredump in
* case of a crash, so also set the coredump size to 0
* to disable that
*/
if
(prctl(PR_SET_DUMPABLE,
1
,
0
,
0
,
0
) <
0
) {
ALOGE(\"could not set dumpable bit flag
for
pid %d: %s\",
getpid(), strerror(errno));
}
else
{
struct rlimit rl;
rl.rlim_cur =
0
;
rl.rlim_max = RLIM_INFINITY;
if
(setrlimit(RLIMIT_CORE, &rl) <
0
) {
ALOGE(\"could not disable core file generation
for
pid %d: %s\",
getpid(), strerror(errno));
}
}
}
......
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
int
main(
int
argc,
char
**argv)
{
constchar* pkgname;
int
myuid, uid, gid;
PackageInfo info;
......
/* check userid of caller - must be \'shell\' or \'root\' */
myuid = getuid();
if (myuid != AID_SHELL && myuid != AID_ROOT) {
panic(\"only \'shell\' or \'root\' users can run this program\\n\");
}
/* retrieve package information from system */
pkgname = argv[1];
if (get_package_info(pkgname, &info) < 0) {
panic(\"Package \'%s\' is unknown\\n\", pkgname);
return 1;
}
/* reject system packages */
if (info.uid < AID_APP) {
panic(\"Package \'%s\' is not an application\\n\", pkgname);
return 1;
}
/* reject any non-debuggable package */
if (!info.isDebuggable) {
panic(\"Package \'%s\' is not debuggable\\n\", pkgname);
return 1;
}
/* Ensure that we change all real/effectiveved IDs at the
* same time to avoid nasty surprises.
*/
uid = gid = info.uid;
if(setresgid(gid,gid,gid) || setresuid(uid,uid,uid)) {
panic(\"Permission denied\\n\");
return 1;
}
......
/* Default exec shell. */
execlp(\"/system/bin/sh\", \"sh\", NULL);
panic(\"exec failed\\n\");
return
1
;
}
|