Christian Brauner (Amutable)exec_state: relocate dumpable information6b1c66c5 months agoHistory
3074 lines · 72.8 KB · C
RawDownload
		return 1 | PR_THP_DISABLE_EXCEPT_ADVISED;	return 0;} static int prctl_set_thp_disable(bool thp_disable, unsigned long flags,				 unsigned long arg4, unsigned long arg5){	struct mm_struct *mm = current->mm; 	if (arg4 || arg5)		return -EINVAL; 	/* Flags are only allowed when disabling. */	if ((!thp_disable && flags) || (flags & ~PR_THP_DISABLE_EXCEPT_ADVISED))		return -EINVAL;	if (mmap_write_lock_killable(current->mm))		return -EINTR;	if (thp_disable) {		if (flags & PR_THP_DISABLE_EXCEPT_ADVISED) {			mm_flags_clear(MMF_DISABLE_THP_COMPLETELY, mm);			mm_flags_set(MMF_DISABLE_THP_EXCEPT_ADVISED, mm);		} else {			mm_flags_set(MMF_DISABLE_THP_COMPLETELY, mm);			mm_flags_clear(MMF_DISABLE_THP_EXCEPT_ADVISED, mm);		}	} else {		mm_flags_clear(MMF_DISABLE_THP_COMPLETELY, mm);		mm_flags_clear(MMF_DISABLE_THP_EXCEPT_ADVISED, mm);	}	mmap_write_unlock(current->mm);	return 0;} SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,		unsigned long, arg4, unsigned long, arg5){	struct task_struct *me = current;	unsigned char comm[sizeof(me->comm)];	long error; 	error = security_task_prctl(option, arg2, arg3, arg4, arg5);	if (error != -ENOSYS)		return error; 	error = 0;	switch (option) {	case PR_SET_PDEATHSIG:		if (!valid_signal(arg2)) {			error = -EINVAL;			break;		}		/*		 * Ensure that either:		 *		 * 1. Subsequent getppid() calls reflect the parent process having died.		 * 2. forget_original_parent() will send the new me->pdeath_signal.		 *		 * Also prevent the read of me->pdeath_signal from being a data race.		 */		read_lock(&tasklist_lock);		me->pdeath_signal = arg2;		read_unlock(&tasklist_lock);		break;	case PR_GET_PDEATHSIG:		error = put_user(me->pdeath_signal, (int __user *)arg2);		break;	case PR_GET_DUMPABLE:		error = task_exec_state_get_dumpable(me);		break;	case PR_SET_DUMPABLE:		if (arg2 != TASK_DUMPABLE_OFF && arg2 != TASK_DUMPABLE_OWNER) {			error = -EINVAL;			break;		}		task_exec_state_set_dumpable(arg2);		break; 	case PR_SET_UNALIGN:		error = SET_UNALIGN_CTL(me, arg2);		break;	case PR_GET_UNALIGN:		error = GET_UNALIGN_CTL(me, arg2);		break;	case PR_SET_FPEMU:		error = SET_FPEMU_CTL(me, arg2);		break;	case PR_GET_FPEMU:		error = GET_FPEMU_CTL(me, arg2);		break;	case PR_SET_FPEXC:		error = SET_FPEXC_CTL(me, arg2);		break;	case PR_GET_FPEXC:		error = GET_FPEXC_CTL(me, arg2);		break;	case PR_GET_TIMING:		error = PR_TIMING_STATISTICAL;		break;	case PR_SET_TIMING:		if (arg2 != PR_TIMING_STATISTICAL)			error = -EINVAL;		break;	case PR_SET_NAME:		comm[sizeof(me->comm) - 1] = 0;		if (strncpy_from_user(comm, (char __user *)arg2,				      sizeof(me->comm) - 1) < 0)			return -EFAULT;		set_task_comm(me, comm);		proc_comm_connector(me);		break;	case PR_GET_NAME:		get_task_comm(comm, me);		if (copy_to_user((char __user *)arg2, comm, sizeof(comm)))			return -EFAULT;		break;	case PR_GET_ENDIAN:		error = GET_ENDIAN(me, arg2);		break;	case PR_SET_ENDIAN:		error = SET_ENDIAN(me, arg2);		break;	case PR_GET_SECCOMP:		error = prctl_get_seccomp();		break;	case PR_SET_SECCOMP:		error = prctl_set_seccomp(arg2, (char __user *)arg3);		break;	case PR_GET_TSC:		error = GET_TSC_CTL(arg2);		break;	case PR_SET_TSC:		error = SET_TSC_CTL(arg2);		break;	case PR_TASK_PERF_EVENTS_DISABLE:		error = perf_event_task_disable();		break;	case PR_TASK_PERF_EVENTS_ENABLE:		error = perf_event_task_enable();		break;	case PR_GET_TIMERSLACK:		if (current->timer_slack_ns > ULONG_MAX)			error = ULONG_MAX;		else			error = current->timer_slack_ns;		break;	case PR_SET_TIMERSLACK:		if (rt_or_dl_task_policy(current))			break;		if (arg2 <= 0)			current->timer_slack_ns =					current->default_timer_slack_ns;		else			current->timer_slack_ns = arg2;		break;	case PR_MCE_KILL:		if (arg4 | arg5)			return -EINVAL;		switch (arg2) {		case PR_MCE_KILL_CLEAR:			if (arg3 != 0)				return -EINVAL;			current->flags &= ~PF_MCE_PROCESS;			break;		case PR_MCE_KILL_SET:			current->flags |= PF_MCE_PROCESS;			if (arg3 == PR_MCE_KILL_EARLY)				current->flags |= PF_MCE_EARLY;			else if (arg3 == PR_MCE_KILL_LATE)				current->flags &= ~PF_MCE_EARLY;			else if (arg3 == PR_MCE_KILL_DEFAULT)				current->flags &=						~(PF_MCE_EARLY|PF_MCE_PROCESS);			else				return -EINVAL;			break;		default:			return -EINVAL;		}		break;	case PR_MCE_KILL_GET:		if (arg2 | arg3 | arg4 | arg5)			return -EINVAL;		if (current->flags & PF_MCE_PROCESS)			error = (current->flags & PF_MCE_EARLY) ?				PR_MCE_KILL_EARLY : PR_MCE_KILL_LATE;		else			error = PR_MCE_KILL_DEFAULT;		break;	case PR_SET_MM:		error = prctl_set_mm(arg2, arg3, arg4, arg5);		break;	case PR_GET_TID_ADDRESS:		error = prctl_get_tid_address(me, (int __user * __user *)arg2);		break;	case PR_SET_CHILD_SUBREAPER:		me->signal->is_child_subreaper = !!arg2;		if (!arg2)			break; 		walk_process_tree(me, propagate_has_child_subreaper, NULL);		break;	case PR_GET_CHILD_SUBREAPER:		error = put_user(me->signal->is_child_subreaper,				 (int __user *)arg2);		break;	case PR_SET_NO_NEW_PRIVS:		if (arg2 != 1 || arg3 || arg4 || arg5)			return -EINVAL; 		task_set_no_new_privs(current);		break;	case PR_GET_NO_NEW_PRIVS:		if (arg2 || arg3 || arg4 || arg5)			return -EINVAL;		return task_no_new_privs(current) ? 1 : 0;	case PR_GET_THP_DISABLE:		error = prctl_get_thp_disable(arg2, arg3, arg4, arg5);		break;	case PR_SET_THP_DISABLE:		error = prctl_set_thp_disable(arg2, arg3, arg4, arg5);		break;	case PR_MPX_ENABLE_MANAGEMENT:	case PR_MPX_DISABLE_MANAGEMENT:		/* No longer implemented: */		return -EINVAL;	case PR_SET_FP_MODE:		error = SET_FP_MODE(me, arg2);		break;	case PR_GET_FP_MODE:		error = GET_FP_MODE(me);		break;	case PR_SVE_SET_VL:		error = SVE_SET_VL(arg2);		break;	case PR_SVE_GET_VL:		error = SVE_GET_VL();		break;	case PR_SME_SET_VL:		error = SME_SET_VL(arg2);		break;	case PR_SME_GET_VL:		error = SME_GET_VL();		break;	case PR_GET_SPECULATION_CTRL:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = arch_prctl_spec_ctrl_get(me, arg2);		break;	case PR_SET_SPECULATION_CTRL:		if (arg4 || arg5)			return -EINVAL;		error = arch_prctl_spec_ctrl_set(me, arg2, arg3);		break;	case PR_PAC_RESET_KEYS:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = PAC_RESET_KEYS(me, arg2);		break;	case PR_PAC_SET_ENABLED_KEYS:		if (arg4 || arg5)			return -EINVAL;		error = PAC_SET_ENABLED_KEYS(me, arg2, arg3);		break;	case PR_PAC_GET_ENABLED_KEYS:		if (arg2 || arg3 || arg4 || arg5)			return -EINVAL;		error = PAC_GET_ENABLED_KEYS(me);		break;	case PR_SET_TAGGED_ADDR_CTRL:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = SET_TAGGED_ADDR_CTRL(arg2);		break;	case PR_GET_TAGGED_ADDR_CTRL:		if (arg2 || arg3 || arg4 || arg5)			return -EINVAL;		error = GET_TAGGED_ADDR_CTRL();		break;	case PR_SET_IO_FLUSHER:		if (!capable(CAP_SYS_RESOURCE))			return -EPERM; 		if (arg3 || arg4 || arg5)			return -EINVAL; 		if (arg2 == 1)			current->flags |= PR_IO_FLUSHER;		else if (!arg2)			current->flags &= ~PR_IO_FLUSHER;		else			return -EINVAL;		break;	case PR_GET_IO_FLUSHER:		if (!capable(CAP_SYS_RESOURCE))			return -EPERM; 		if (arg2 || arg3 || arg4 || arg5)			return -EINVAL; 		error = (current->flags & PR_IO_FLUSHER) == PR_IO_FLUSHER;		break;	case PR_SET_SYSCALL_USER_DISPATCH:		error = set_syscall_user_dispatch(arg2, arg3, arg4,						  (char __user *) arg5);		break;#ifdef CONFIG_SCHED_CORE	case PR_SCHED_CORE:		error = sched_core_share_pid(arg2, arg3, arg4, arg5);		break;#endif	case PR_SET_MDWE:		error = prctl_set_mdwe(arg2, arg3, arg4, arg5);		break;	case PR_GET_MDWE:		error = prctl_get_mdwe(arg2, arg3, arg4, arg5);		break;	case PR_PPC_GET_DEXCR:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = PPC_GET_DEXCR_ASPECT(me, arg2);		break;	case PR_PPC_SET_DEXCR:		if (arg4 || arg5)			return -EINVAL;		error = PPC_SET_DEXCR_ASPECT(me, arg2, arg3);		break;	case PR_SET_VMA:		error = prctl_set_vma(arg2, arg3, arg4, arg5);		break;	case PR_GET_AUXV:		if (arg4 || arg5)			return -EINVAL;		error = prctl_get_auxv((void __user *)arg2, arg3);		break;#ifdef CONFIG_KSM	case PR_SET_MEMORY_MERGE:		if (arg3 || arg4 || arg5)			return -EINVAL;		if (mmap_write_lock_killable(me->mm))			return -EINTR; 		if (arg2)			error = ksm_enable_merge_any(me->mm);		else			error = ksm_disable_merge_any(me->mm);		mmap_write_unlock(me->mm);		break;	case PR_GET_MEMORY_MERGE:		if (arg2 || arg3 || arg4 || arg5)			return -EINVAL; 		error = !!mm_flags_test(MMF_VM_MERGE_ANY, me->mm);		break;#endif	case PR_RISCV_V_SET_CONTROL:		error = RISCV_V_SET_CONTROL(arg2);		break;	case PR_RISCV_V_GET_CONTROL:		error = RISCV_V_GET_CONTROL();		break;	case PR_RISCV_SET_ICACHE_FLUSH_CTX:		error = RISCV_SET_ICACHE_FLUSH_CTX(arg2, arg3);		break;	case PR_GET_SHADOW_STACK_STATUS:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = arch_get_shadow_stack_status(me, (unsigned long __user *) arg2);		break;	case PR_SET_SHADOW_STACK_STATUS:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = arch_set_shadow_stack_status(me, arg2);		break;	case PR_LOCK_SHADOW_STACK_STATUS:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = arch_lock_shadow_stack_status(me, arg2);		break;	case PR_TIMER_CREATE_RESTORE_IDS:		if (arg3 || arg4 || arg5)			return -EINVAL;		error = posixtimer_create_prctl(arg2);		break;	case PR_FUTEX_HASH:		error = futex_hash_prctl(arg2, arg3, arg4);		break;	case PR_RSEQ_SLICE_EXTENSION:		if (arg4 || arg5)			return -EINVAL;		error = rseq_slice_extension_prctl(arg2, arg3);		break;	case PR_GET_CFI:		if (arg2 != PR_CFI_BRANCH_LANDING_PADS)			return -EINVAL;		if (arg4 || arg5)			return -EINVAL;		error = arch_prctl_get_branch_landing_pad_state(me, (unsigned long __user *)arg3);		break;	case PR_SET_CFI:		if (arg2 != PR_CFI_BRANCH_LANDING_PADS)			return -EINVAL;		if (arg4 || arg5)			return -EINVAL;		error = arch_prctl_set_branch_landing_pad_state(me, arg3);		if (error)			break;		if (arg3 & PR_CFI_LOCK && !(arg3 & PR_CFI_DISABLE))			error = arch_prctl_lock_branch_landing_pad_state(me);		break;	default:		trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5);		error = -EINVAL;		break;	}	return error;} SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, void __user *, unused){	int err = 0;	int cpu = raw_smp_processor_id(); 	if (cpup)		err |= put_user(cpu, cpup);	if (nodep)		err |= put_user(cpu_to_node(cpu), nodep);	return err ? -EFAULT : 0;} /** * do_sysinfo - fill in sysinfo struct * @info: pointer to buffer to fill */static int do_sysinfo(struct sysinfo *info){	unsigned long mem_total, sav_total;	unsigned int mem_unit, bitcount;	struct timespec64 tp; 	memset(info, 0, sizeof(struct sysinfo)); 	ktime_get_boottime_ts64(&tp);	timens_add_boottime(&tp);	info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); 	get_avenrun(info->loads, 0, SI_LOAD_SHIFT - FSHIFT); 	info->procs = nr_threads; 	si_meminfo(info);	si_swapinfo(info); 	/*	 * If the sum of all the available memory (i.e. ram + swap)	 * is less than can be stored in a 32 bit unsigned long then	 * we can be binary compatible with 2.2.x kernels.  If not,	 * well, in that case 2.2.x was broken anyways...	 *	 *  -Erik Andersen <andersee@debian.org>	 */ 	mem_total = info->totalram + info->totalswap;	if (mem_total < info->totalram || mem_total < info->totalswap)		goto out;	bitcount = 0;	mem_unit = info->mem_unit;	while (mem_unit > 1) {		bitcount++;		mem_unit >>= 1;		sav_total = mem_total;		mem_total <<= 1;		if (mem_total < sav_total)			goto out;	} 	/*	 * If mem_total did not overflow, multiply all memory values by	 * info->mem_unit and set it to 1.  This leaves things compatible	 * with 2.2.x, and also retains compatibility with earlier 2.4.x	 * kernels...	 */ 	info->mem_unit = 1;	info->totalram <<= bitcount;	info->freeram <<= bitcount;	info->sharedram <<= bitcount;	info->bufferram <<= bitcount;	info->totalswap <<= bitcount;	info->freeswap <<= bitcount;	info->totalhigh <<= bitcount;	info->freehigh <<= bitcount; out:	return 0;} SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info){	struct sysinfo val; 

Lines 2501–3000 of 3074. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t