⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 4 页
字号:
EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);/** *	srcu_init_notifier_head - Initialize an SRCU notifier head *	@nh: Pointer to head of the srcu notifier chain * *	Unlike other sorts of notifier heads, SRCU notifier heads require *	dynamic initialization.  Be sure to call this routine before *	calling any of the other SRCU notifier routines for this head. * *	If an SRCU notifier head is deallocated, it must first be cleaned *	up by calling srcu_cleanup_notifier_head().  Otherwise the head's *	per-cpu data (used by the SRCU mechanism) will leak. */void srcu_init_notifier_head(struct srcu_notifier_head *nh){	mutex_init(&nh->mutex);	if (init_srcu_struct(&nh->srcu) < 0)		BUG();	nh->head = NULL;}EXPORT_SYMBOL_GPL(srcu_init_notifier_head);/** *	register_reboot_notifier - Register function to be called at reboot time *	@nb: Info about notifier function to be called * *	Registers a function with the list of functions *	to be called at reboot time. * *	Currently always returns zero, as blocking_notifier_chain_register() *	always returns zero. */ int register_reboot_notifier(struct notifier_block * nb){	return blocking_notifier_chain_register(&reboot_notifier_list, nb);}EXPORT_SYMBOL(register_reboot_notifier);/** *	unregister_reboot_notifier - Unregister previously registered reboot notifier *	@nb: Hook to be unregistered * *	Unregisters a previously registered reboot *	notifier function. * *	Returns zero on success, or %-ENOENT on failure. */ int unregister_reboot_notifier(struct notifier_block * nb){	return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);}EXPORT_SYMBOL(unregister_reboot_notifier);static int set_one_prio(struct task_struct *p, int niceval, int error){	int no_nice;	if (p->uid != current->euid &&		p->euid != current->euid && !capable(CAP_SYS_NICE)) {		error = -EPERM;		goto out;	}	if (niceval < task_nice(p) && !can_nice(p, niceval)) {		error = -EACCES;		goto out;	}	no_nice = security_task_setnice(p, niceval);	if (no_nice) {		error = no_nice;		goto out;	}	if (error == -ESRCH)		error = 0;	set_user_nice(p, niceval);out:	return error;}asmlinkage long sys_setpriority(int which, int who, int niceval){	struct task_struct *g, *p;	struct user_struct *user;	int error = -EINVAL;	struct pid *pgrp;	if (which > PRIO_USER || which < PRIO_PROCESS)		goto out;	/* normalize: avoid signed division (rounding problems) */	error = -ESRCH;	if (niceval < -20)		niceval = -20;	if (niceval > 19)		niceval = 19;	read_lock(&tasklist_lock);	switch (which) {		case PRIO_PROCESS:			if (who)				p = find_task_by_pid(who);			else				p = current;			if (p)				error = set_one_prio(p, niceval, error);			break;		case PRIO_PGRP:			if (who)				pgrp = find_pid(who);			else				pgrp = task_pgrp(current);			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {				error = set_one_prio(p, niceval, error);			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);			break;		case PRIO_USER:			user = current->user;			if (!who)				who = current->uid;			else				if ((who != current->uid) && !(user = find_user(who)))					goto out_unlock;	/* No processes for this user */			do_each_thread(g, p)				if (p->uid == who)					error = set_one_prio(p, niceval, error);			while_each_thread(g, p);			if (who != current->uid)				free_uid(user);		/* For find_user() */			break;	}out_unlock:	read_unlock(&tasklist_lock);out:	return error;}/* * Ugh. To avoid negative return values, "getpriority()" will * not return the normal nice-value, but a negated value that * has been offset by 20 (ie it returns 40..1 instead of -20..19) * to stay compatible. */asmlinkage long sys_getpriority(int which, int who){	struct task_struct *g, *p;	struct user_struct *user;	long niceval, retval = -ESRCH;	struct pid *pgrp;	if (which > PRIO_USER || which < PRIO_PROCESS)		return -EINVAL;	read_lock(&tasklist_lock);	switch (which) {		case PRIO_PROCESS:			if (who)				p = find_task_by_pid(who);			else				p = current;			if (p) {				niceval = 20 - task_nice(p);				if (niceval > retval)					retval = niceval;			}			break;		case PRIO_PGRP:			if (who)				pgrp = find_pid(who);			else				pgrp = task_pgrp(current);			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {				niceval = 20 - task_nice(p);				if (niceval > retval)					retval = niceval;			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);			break;		case PRIO_USER:			user = current->user;			if (!who)				who = current->uid;			else				if ((who != current->uid) && !(user = find_user(who)))					goto out_unlock;	/* No processes for this user */			do_each_thread(g, p)				if (p->uid == who) {					niceval = 20 - task_nice(p);					if (niceval > retval)						retval = niceval;				}			while_each_thread(g, p);			if (who != current->uid)				free_uid(user);		/* for find_user() */			break;	}out_unlock:	read_unlock(&tasklist_lock);	return retval;}/** *	emergency_restart - reboot the system * *	Without shutting down any hardware or taking any locks *	reboot the system.  This is called when we know we are in *	trouble so this is our best effort to reboot.  This is *	safe to call in interrupt context. */void emergency_restart(void){	machine_emergency_restart();}EXPORT_SYMBOL_GPL(emergency_restart);static void kernel_restart_prepare(char *cmd){	blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);	system_state = SYSTEM_RESTART;	device_shutdown();}/** *	kernel_restart - reboot the system *	@cmd: pointer to buffer containing command to execute for restart *		or %NULL * *	Shutdown everything and perform a clean reboot. *	This is not safe to call in interrupt context. */void kernel_restart(char *cmd){	kernel_restart_prepare(cmd);	if (!cmd)		printk(KERN_EMERG "Restarting system.\n");	else		printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);	machine_restart(cmd);}EXPORT_SYMBOL_GPL(kernel_restart);/** *	kernel_kexec - reboot the system * *	Move into place and start executing a preloaded standalone *	executable.  If nothing was preloaded return an error. */static void kernel_kexec(void){#ifdef CONFIG_KEXEC	struct kimage *image;	image = xchg(&kexec_image, NULL);	if (!image)		return;	kernel_restart_prepare(NULL);	printk(KERN_EMERG "Starting new kernel\n");	machine_shutdown();	machine_kexec(image);#endif}void kernel_shutdown_prepare(enum system_states state){	blocking_notifier_call_chain(&reboot_notifier_list,		(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);	system_state = state;	device_shutdown();}/** *	kernel_halt - halt the system * *	Shutdown everything and perform a clean system halt. */void kernel_halt(void){	kernel_shutdown_prepare(SYSTEM_HALT);	printk(KERN_EMERG "System halted.\n");	machine_halt();}EXPORT_SYMBOL_GPL(kernel_halt);/** *	kernel_power_off - power_off the system * *	Shutdown everything and perform a clean system power_off. */void kernel_power_off(void){	kernel_shutdown_prepare(SYSTEM_POWER_OFF);	printk(KERN_EMERG "Power down.\n");	machine_power_off();}EXPORT_SYMBOL_GPL(kernel_power_off);/* * Reboot system call: for obvious reasons only root may call it, * and even root needs to set up some magic numbers in the registers * so that some mistake won't make this reboot the whole machine. * You can also set the meaning of the ctrl-alt-del-key here. * * reboot doesn't sync: do that yourself before calling this. */asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user * arg){	char buffer[256];	/* We only trust the superuser with rebooting the system. */	if (!capable(CAP_SYS_BOOT))		return -EPERM;	/* For safety, we require "magic" arguments. */	if (magic1 != LINUX_REBOOT_MAGIC1 ||	    (magic2 != LINUX_REBOOT_MAGIC2 &&	                magic2 != LINUX_REBOOT_MAGIC2A &&			magic2 != LINUX_REBOOT_MAGIC2B &&	                magic2 != LINUX_REBOOT_MAGIC2C))		return -EINVAL;	/* Instead of trying to make the power_off code look like	 * halt when pm_power_off is not set do it the easy way.	 */	if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)		cmd = LINUX_REBOOT_CMD_HALT;	lock_kernel();	switch (cmd) {	case LINUX_REBOOT_CMD_RESTART:		kernel_restart(NULL);		break;	case LINUX_REBOOT_CMD_CAD_ON:		C_A_D = 1;		break;	case LINUX_REBOOT_CMD_CAD_OFF:		C_A_D = 0;		break;	case LINUX_REBOOT_CMD_HALT:		kernel_halt();		unlock_kernel();		do_exit(0);		break;	case LINUX_REBOOT_CMD_POWER_OFF:		kernel_power_off();		unlock_kernel();		do_exit(0);		break;	case LINUX_REBOOT_CMD_RESTART2:		if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {			unlock_kernel();			return -EFAULT;		}		buffer[sizeof(buffer) - 1] = '\0';		kernel_restart(buffer);		break;	case LINUX_REBOOT_CMD_KEXEC:		kernel_kexec();		unlock_kernel();		return -EINVAL;#ifdef CONFIG_SOFTWARE_SUSPEND	case LINUX_REBOOT_CMD_SW_SUSPEND:		{			int ret = hibernate();			unlock_kernel();			return ret;		}#endif	default:		unlock_kernel();		return -EINVAL;	}	unlock_kernel();	return 0;}static void deferred_cad(struct work_struct *dummy){	kernel_restart(NULL);}/* * This function gets called by ctrl-alt-del - ie the keyboard interrupt. * As it's called within an interrupt, it may NOT sync: the only choice * is whether to reboot at once, or just ignore the ctrl-alt-del. */void ctrl_alt_del(void){	static DECLARE_WORK(cad_work, deferred_cad);	if (C_A_D)		schedule_work(&cad_work);	else		kill_cad_pid(SIGINT, 1);}	/* * Unprivileged users may change the real gid to the effective gid * or vice versa.  (BSD-style) * * If you set the real gid at all, or set the effective gid to a value not * equal to the real gid, then the saved gid is set to the new effective gid. * * This makes it possible for a setgid program to completely drop its * privileges, which is often a useful assertion to make when you are doing * a security audit over a program. * * The general idea is that a program which uses just setregid() will be * 100% compatible with BSD.  A program which uses just setgid() will be * 100% compatible with POSIX with saved IDs.  * * SMP: There are not races, the GIDs are checked only by filesystem *      operations (as far as semantic preservation is concerned). */asmlinkage long sys_setregid(gid_t rgid, gid_t egid){	int old_rgid = current->gid;	int old_egid = current->egid;	int new_rgid = old_rgid;	int new_egid = old_egid;	int retval;	retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);	if (retval)		return retval;	if (rgid != (gid_t) -1) {		if ((old_rgid == rgid) ||		    (current->egid==rgid) ||		    capable(CAP_SETGID))			new_rgid = rgid;		else			return -EPERM;	}	if (egid != (gid_t) -1) {		if ((old_rgid == egid) ||		    (current->egid == egid) ||		    (current->sgid == egid) ||		    capable(CAP_SETGID))			new_egid = egid;		else			return -EPERM;	}	if (new_egid != old_egid) {		current->mm->dumpable = suid_dumpable;		smp_wmb();	}	if (rgid != (gid_t) -1 ||	    (egid != (gid_t) -1 && egid != old_rgid))		current->sgid = new_egid;	current->fsgid = new_egid;	current->egid = new_egid;	current->gid = new_rgid;	key_fsgid_changed(current);	proc_id_connector(current, PROC_EVENT_GID);	return 0;}/* * setgid() is implemented like SysV w/ SAVED_IDS  * * SMP: Same implicit races as above. */asmlinkage long sys_setgid(gid_t gid){	int old_egid = current->egid;	int retval;	retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);	if (retval)		return retval;	if (capable(CAP_SETGID)) {		if (old_egid != gid) {			current->mm->dumpable = suid_dumpable;			smp_wmb();		}		current->gid = current->egid = current->sgid = current->fsgid = gid;	} else if ((gid == current->gid) || (gid == current->sgid)) {		if (old_egid != gid) {			current->mm->dumpable = suid_dumpable;			smp_wmb();		}		current->egid = current->fsgid = gid;	}	else		return -EPERM;	key_fsgid_changed(current);	proc_id_connector(current, PROC_EVENT_GID);	return 0;}  static int set_user(uid_t new_ruid, int dumpclear){	struct user_struct *new_user;	new_user = alloc_uid(new_ruid);	if (!new_user)		return -EAGAIN;	if (atomic_read(&new_user->processes) >=				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&			new_user != &root_user) {		free_uid(new_user);		return -EAGAIN;	}	switch_uid(new_user);	if (dumpclear) {		current->mm->dumpable = suid_dumpable;		smp_wmb();	}	current->uid = new_ruid;	return 0;}/* * Unprivileged users may change the real uid to the effective uid * or vice versa.  (BSD-style) * * If you set the real uid at all, or set the effective uid to a value not * equal to the real uid, then the saved uid is set to the new effective uid. * * This makes it possible for a setuid program to completely drop its * privileges, which is often a useful assertion to make when you are doing * a security audit over a program. * * The general idea is that a program which uses just setreuid() will be * 100% compatible with BSD.  A program which uses just setuid() will be * 100% compatible with POSIX with saved IDs.  */asmlinkage long sys_setreuid(uid_t ruid, uid_t euid){	int old_ruid, old_euid, old_suid, new_ruid, new_euid;	int retval;	retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);	if (retval)		return retval;	new_ruid = old_ruid = current->uid;	new_euid = old_euid = current->euid;	old_suid = current->suid;	if (ruid != (uid_t) -1) {		new_ruid = ruid;		if ((old_ruid != ruid) &&		    (current->euid != ruid) &&		    !capable(CAP_SETUID))			return -EPERM;	}	if (euid != (uid_t) -1) {		new_euid = euid;		if ((old_ruid != euid) &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -