static inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct group_info *group_info; int g; struct fdtable *fdt = NULL; const struct cred *cred; pid_t ppid, tpid; rcu_read_lock(); ppid = pid_alive(p) ? task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; tpid = 0; if (pid_alive(p)) { struct task_struct *tracer = tracehook_tracer_task(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); } cred = get_task_cred(p); seq_printf(m, "State:\t%s\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), task_tgid_nr_ns(p, ns), pid_nr_ns(pid, ns), ppid, tpid, cred->uid, cred->euid, cred->suid, cred->fsuid, cred->gid, cred->egid, cred->sgid, cred->fsgid); task_lock(p); if (p->files) fdt = files_fdtable(p->files); seq_printf(m, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); rcu_read_unlock(); group_info = cred->group_info; task_unlock(p); for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) seq_printf(m, "%d ", GROUP_AT(group_info, g)); put_cred(cred); seq_printf(m, "\n"); }
static ssize_t __cgroup1_procs_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off, bool threadgroup) { struct cgroup *cgrp; struct task_struct *task; const struct cred *cred, *tcred; ssize_t ret; cgrp = cgroup_kn_lock_live(of->kn, false); if (!cgrp) return -ENODEV; task = cgroup_procs_write_start(buf, threadgroup); ret = PTR_ERR_OR_ZERO(task); if (ret) goto out_unlock; /* * Even if we're attaching all tasks in the thread group, we only * need to check permissions on one of them. */ cred = current_cred(); tcred = get_task_cred(task); if (!uid_eq(cred->euid, GLOBAL_ROOT_UID) && !uid_eq(cred->euid, tcred->uid) && !uid_eq(cred->euid, tcred->suid)) ret = -EACCES; put_cred(tcred); if (ret) goto out_finish; ret = cgroup_attach_task(cgrp, task, threadgroup); out_finish: cgroup_procs_write_finish(task); out_unlock: cgroup_kn_unlock(of->kn); return ret ?: nbytes; }
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 inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct user_namespace *user_ns = seq_user_ns(m); struct group_info *group_info; int g; struct task_struct *tracer; const struct cred *cred; pid_t ppid, tpid = 0, tgid, ngid; unsigned int max_fds = 0; rcu_read_lock(); ppid = pid_alive(p) ? task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; tracer = ptrace_parent(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); tgid = task_tgid_nr_ns(p, ns); ngid = task_numa_group_id(p); cred = get_task_cred(p); task_lock(p); if (p->files) max_fds = files_fdtable(p->files)->max_fds; task_unlock(p); rcu_read_unlock(); seq_printf(m, "State:\t%s\n" "Tgid:\t%d\n" "Ngid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n" "FDSize:\t%d\nGroups:\t", get_task_state(p), tgid, ngid, pid_nr_ns(pid, ns), ppid, tpid, from_kuid_munged(user_ns, cred->uid), from_kuid_munged(user_ns, cred->euid), from_kuid_munged(user_ns, cred->suid), from_kuid_munged(user_ns, cred->fsuid), from_kgid_munged(user_ns, cred->gid), from_kgid_munged(user_ns, cred->egid), from_kgid_munged(user_ns, cred->sgid), from_kgid_munged(user_ns, cred->fsgid), max_fds); group_info = cred->group_info; for (g = 0; g < group_info->ngroups; g++) seq_printf(m, "%d ", from_kgid_munged(user_ns, GROUP_AT(group_info, g))); put_cred(cred); #ifdef CONFIG_PID_NS seq_puts(m, "\nNStgid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_tgid_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSpid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_pid_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSpgid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_pgrp_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSsid:"); for (g = ns->level; g <= pid->level; g++) seq_printf(m, "\t%d", task_session_nr_ns(p, pid->numbers[g].ns)); #endif seq_putc(m, '\n'); }
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; }
static inline void task_state(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p) { struct user_namespace *user_ns = seq_user_ns(m); struct group_info *group_info; int g, umask = -1; struct task_struct *tracer; const struct cred *cred; pid_t ppid, tpid = 0, tgid, ngid; unsigned int max_fds = 0; rcu_read_lock(); ppid = pid_alive(p) ? task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; tracer = ptrace_parent(p); if (tracer) tpid = task_pid_nr_ns(tracer, ns); tgid = task_tgid_nr_ns(p, ns); ngid = task_numa_group_id(p); cred = get_task_cred(p); task_lock(p); if (p->fs) umask = p->fs->umask; if (p->files) max_fds = files_fdtable(p->files)->max_fds; task_unlock(p); rcu_read_unlock(); if (umask >= 0) seq_printf(m, "Umask:\t%#04o\n", umask); seq_puts(m, "State:\t"); seq_puts(m, get_task_state(p)); seq_put_decimal_ull(m, "\nTgid:\t", tgid); seq_put_decimal_ull(m, "\nNgid:\t", ngid); seq_put_decimal_ull(m, "\nPid:\t", pid_nr_ns(pid, ns)); seq_put_decimal_ull(m, "\nPPid:\t", ppid); seq_put_decimal_ull(m, "\nTracerPid:\t", tpid); seq_put_decimal_ull(m, "\nUid:\t", from_kuid_munged(user_ns, cred->uid)); seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->euid)); seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->suid)); seq_put_decimal_ull(m, "\t", from_kuid_munged(user_ns, cred->fsuid)); seq_put_decimal_ull(m, "\nGid:\t", from_kgid_munged(user_ns, cred->gid)); seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->egid)); seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->sgid)); seq_put_decimal_ull(m, "\t", from_kgid_munged(user_ns, cred->fsgid)); seq_put_decimal_ull(m, "\nFDSize:\t", max_fds); seq_puts(m, "\nGroups:\t"); group_info = cred->group_info; for (g = 0; g < group_info->ngroups; g++) seq_put_decimal_ull(m, g ? " " : "", from_kgid_munged(user_ns, group_info->gid[g])); put_cred(cred); /* Trailing space shouldn't have been added in the first place. */ seq_putc(m, ' '); #ifdef CONFIG_PID_NS seq_puts(m, "\nNStgid:"); for (g = ns->level; g <= pid->level; g++) seq_put_decimal_ull(m, "\t", task_tgid_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSpid:"); for (g = ns->level; g <= pid->level; g++) seq_put_decimal_ull(m, "\t", task_pid_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSpgid:"); for (g = ns->level; g <= pid->level; g++) seq_put_decimal_ull(m, "\t", task_pgrp_nr_ns(p, pid->numbers[g].ns)); seq_puts(m, "\nNSsid:"); for (g = ns->level; g <= pid->level; g++) seq_put_decimal_ull(m, "\t", task_session_nr_ns(p, pid->numbers[g].ns)); #endif seq_putc(m, '\n'); }