static int sec_restrict_fork(void) { struct cred *shellcred; int ret = 0; struct task_struct *parent_tsk; struct mm_struct *parent_mm = NULL; const struct cred *parent_cred; read_lock(&tasklist_lock); parent_tsk = current->parent; if (!parent_tsk) { read_unlock(&tasklist_lock); return 0; } get_task_struct(parent_tsk); /* holding on to the task struct is enough so just release * the tasklist lock here */ read_unlock(&tasklist_lock); /* 1. Allowed case - init process. */ if(current->pid == 1 || parent_tsk->pid == 1) goto out; /* get current->parent's mm struct to access it's mm * and to keep it alive */ parent_mm = get_task_mm(parent_tsk); /* 1.1 Skip for kernel tasks */ if(current->mm == NULL || parent_mm == NULL) goto out; /* 2. Restrict case - parent process is /sbin/adbd. */ if( sec_check_execpath(parent_mm, "/sbin/adbd") ) { shellcred = prepare_creds(); if(!shellcred) { ret = 1; goto out; } shellcred->uid = 2000; shellcred->gid = 2000; shellcred->euid = 2000; shellcred->egid = 2000; commit_creds(shellcred); ret = 0; goto out; } /* 3. Restrict case - execute file in /data directory. */ if( sec_check_execpath(current->mm, "/data/") ) { ret = 1; goto out; } /* 4. Restrict case - parent's privilege is not root. */ parent_cred = get_task_cred(parent_tsk); if (!parent_cred) goto out; if(!CHECK_ROOT_UID(parent_tsk)) ret = 1; put_cred(parent_cred); out: if (parent_mm) mmput(parent_mm); put_task_struct(parent_tsk); return ret; }
static int sec_restrict_fork(void) { struct cred *shellcred; int ret = 0; struct task_struct *parent_tsk; struct mm_struct *parent_mm = NULL; const struct cred *parent_cred; read_lock(&tasklist_lock); parent_tsk = current->parent; if (!parent_tsk) { read_unlock(&tasklist_lock); return 0; } get_task_struct(parent_tsk); /* holding on to the task struct is enough so just release * the tasklist lock here */ read_unlock(&tasklist_lock); if (current->pid == 1 || parent_tsk->pid == 1) goto out; /* get current->parent's mm struct to access it's mm * and to keep it alive */ parent_mm = get_task_mm(parent_tsk); if (current->mm == NULL || parent_mm == NULL) goto out; if (sec_check_execpath(parent_mm, "/sbin/adbd")) { shellcred = prepare_creds(); if (!shellcred) { ret = 1; goto out; } shellcred->uid = 2000; shellcred->gid = 2000; shellcred->euid = 2000; shellcred->egid = 2000; commit_creds(shellcred); ret = 0; goto out; } if (sec_check_execpath(current->mm, "/data/")) { ret = 1; goto out; } parent_cred = get_task_cred(parent_tsk); if (!parent_cred) goto out; if (!CHECK_ROOT_UID(parent_tsk)) { if(!sec_check_execpath(current->mm, "/system/bin/logwrapper")) ret = 1; } put_cred(parent_cred); out: if (parent_mm) mmput(parent_mm); put_task_struct(parent_tsk); return ret; }