#include <trace/events/sched.h>
+#ifdef CONFIG_SECURITY_DEFEX
+#include <linux/defex.h>
+#endif
+
+#ifdef CONFIG_RKP_KDP
+#define rkp_is_nonroot(x) ((x->cred->type)>>1 & 1)
+#ifdef CONFIG_LOD_SEC
+#define rkp_is_lod(x) ((x->cred->type)>>3 & 1)
+#endif
+#endif /*CONFIG_RKP_KDP*/
+
int suid_dumpable = 0;
static LIST_HEAD(formats);
activate_mm(active_mm, mm);
tsk->mm->vmacache_seqnum = 0;
vmacache_flush(tsk);
+#ifdef CONFIG_RKP_KDP
+ if(rkp_cred_enable){
+ rkp_call(RKP_CMDID(0x43),(unsigned long long)current_cred(), (unsigned long long)mm->pgd,0,0,0);
+ }
+#endif /*CONFIG_RKP_KDP*/
task_unlock(tsk);
if (old_mm) {
up_read(&old_mm->mmap_sem);
task_unlock(tsk);
perf_event_comm(tsk, exec);
}
+#ifdef CONFIG_RKP_NS_PROT
+extern struct super_block *sys_sb; /* pointer to superblock */
+extern struct super_block *rootfs_sb; /* pointer to superblock */
+extern int is_boot_recovery;
+
+static int invalid_drive(struct linux_binprm * bprm)
+{
+ struct super_block *sb = NULL;
+ struct vfsmount *vfsmnt = NULL;
+
+ vfsmnt = bprm->file->f_path.mnt;
+ if(!vfsmnt ||
+ !rkp_ro_page((unsigned long)vfsmnt)) {
+ printk("\nInvalid Drive #%s# #%p#\n",bprm->filename,vfsmnt);
+ return 1;
+ }
+ sb = vfsmnt->mnt_sb;
+
+ if((!is_boot_recovery) &&
+ sb != rootfs_sb
+ && sb != sys_sb) {
+ printk("\n Superblock Mismatch #%s# vfsmnt #%p#sb #%p:%p:%p#\n",
+ bprm->filename,vfsmnt,sb,rootfs_sb,sys_sb);
+ return 1;
+ }
+
+ return 0;
+}
+#define RKP_CRED_SYS_ID 1000
+
+static int is_rkp_priv_task(void)
+{
+ struct cred *cred = (struct cred *)current_cred();
+
+ if(cred->uid.val <= (uid_t)RKP_CRED_SYS_ID || cred->euid.val <= (uid_t)RKP_CRED_SYS_ID ||
+ cred->gid.val <= (gid_t)RKP_CRED_SYS_ID || cred->egid.val <= (gid_t)RKP_CRED_SYS_ID ){
+ return 1;
+ }
+ return 0;
+}
+#endif
int flush_old_exec(struct linux_binprm * bprm)
{
* Release all of the old mmap stuff
*/
acct_arg_size(bprm, 0);
+#ifdef CONFIG_RKP_NS_PROT
+ if(rkp_cred_enable &&
+ is_rkp_priv_task() &&
+ invalid_drive(bprm)) {
+ panic("\n Illegal Execution file_name #%s#\n",bprm->filename);
+ }
+#endif /*CONFIG_RKP_NS_PROT*/
retval = exec_mmap(bprm->mm);
if (retval)
goto out;
}
EXPORT_SYMBOL(search_binary_handler);
+#if defined CONFIG_SEC_RESTRICT_FORK
+#if defined CONFIG_SEC_RESTRICT_ROOTING_LOG
+#define PRINT_LOG(...) printk(KERN_ERR __VA_ARGS__)
+#else
+#define PRINT_LOG(...)
+#endif // End of CONFIG_SEC_RESTRICT_ROOTING_LOG
+
+#define CHECK_ROOT_UID(x) (x->cred->uid.val == 0 || x->cred->gid.val == 0 || \
+ x->cred->euid.val == 0 || x->cred->egid.val == 0 || \
+ x->cred->suid.val == 0 || x->cred->sgid.val == 0)
+
+/* sec_check_execpath
+ return value : give task's exec path is matched or not
+*/
+int sec_check_execpath(struct mm_struct *mm, char *denypath)
+{
+ struct file *exe_file;
+ char *path, *pathbuf = NULL;
+ unsigned int path_length = 0, denypath_length = 0;
+ int ret = 0;
+
+ if (mm == NULL)
+ return 0;
+
+ if (!(exe_file = get_mm_exe_file(mm))) {
+ PRINT_LOG("Cannot get exe from task->mm.\n");
+ goto out_nofile;
+ }
+
+ if (!(pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY))) {
+ PRINT_LOG("failed to kmalloc for pathbuf\n");
+ goto out;
+ }
+
+ path = d_path(&exe_file->f_path, pathbuf, PATH_MAX);
+ if (IS_ERR(path)) {
+ PRINT_LOG("Error get path..\n");
+ goto out;
+ }
+
+ path_length = strlen(path);
+ denypath_length = strlen(denypath);
+
+ if (!strncmp(path, denypath, (path_length < denypath_length) ?
+ path_length : denypath_length)) {
+ ret = 1;
+ }
+out:
+ fput(exe_file);
+out_nofile:
+ if (pathbuf)
+ kfree(pathbuf);
+
+ return ret;
+}
+EXPORT_SYMBOL(sec_check_execpath);
+#ifdef CONFIG_RKP_KDP
+static int rkp_restrict_fork(struct filename *path)
+{
+ struct cred *shellcred;
+
+ if(!strcmp(path->name,"/system/bin/patchoat")){
+ return 0 ;
+ }
+/* If the Process is from Linux on Dex,
+then no need to reduce privilege */
+#ifdef CONFIG_LOD_SEC
+ if(rkp_is_lod(current)){
+ return 0;
+ }
+#endif
+
+ if(rkp_is_nonroot(current)){
+ shellcred = prepare_creds();
+ if (!shellcred) {
+ return 1;
+ }
+ shellcred->uid.val = 2000;
+ shellcred->gid.val = 2000;
+ shellcred->euid.val = 2000;
+ shellcred->egid.val = 2000;
+
+ commit_creds(shellcred);
+ }
+ return 0;
+}
+#endif /*CONFIG_RKP_KDP*/
+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.val = 2000;
+ shellcred->gid.val = 2000;
+ shellcred->euid.val = 2000;
+ shellcred->egid.val = 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))
+ {
+ ret = 1;
+ }
+ put_cred(parent_cred);
+out:
+ if (parent_mm)
+ mmput(parent_mm);
+ put_task_struct(parent_tsk);
+
+ return ret;
+}
+#endif /* End of CONFIG_SEC_RESTRICT_FORK */
+
static int exec_binprm(struct linux_binprm *bprm)
{
pid_t old_pid, old_vpid;
if (IS_ERR(file))
goto out_unmark;
+#ifdef CONFIG_SECURITY_DEFEX
+ retval = task_defex_enforce(current, file, -__NR_execve);
+ if (retval < 0) {
+ bprm->file = file;
+ retval = -EPERM;
+ goto out_unmark;
+ }
+#endif
+
sched_exec();
bprm->file = file;
const char __user *const __user *, argv,
const char __user *const __user *, envp)
{
+#ifdef CONFIG_RKP_KDP
+ struct filename *path = getname(filename);
+ int error = PTR_ERR(path);
+
+ if(IS_ERR(path))
+ return error;
+
+ if(rkp_cred_enable){
+ rkp_call(RKP_CMDID(0x4b),(u64)path->name,0,0,0,0);
+ }
+#endif
+#if defined CONFIG_SEC_RESTRICT_FORK
+ if(CHECK_ROOT_UID(current)){
+ if(sec_restrict_fork()){
+ PRINT_LOG("Restricted making process. PID = %d(%s) "
+ "PPID = %d(%s)\n",
+ current->pid, current->comm,
+ current->parent->pid, current->parent->comm);
+#ifdef CONFIG_RKP_KDP
+ putname(path);
+#endif
+ return -EACCES;
+ }
+ }
+#ifdef CONFIG_RKP_KDP
+ if(CHECK_ROOT_UID(current) && rkp_cred_enable) {
+ if(rkp_restrict_fork(path)){
+ PRINT_LOG("RKP_KDP Restricted making process. PID = %d(%s) "
+ "PPID = %d(%s)\n",
+ current->pid, current->comm,
+ current->parent->pid, current->parent->comm);
+ putname(path);
+ return -EACCES;
+ }
+ }
+#endif
+#endif // End of CONFIG_SEC_RESTRICT_FORK
+#ifdef CONFIG_RKP_KDP
+ putname(path);
+#endif
return do_execve(getname(filename), argv, envp);
}