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

📄 sys.c

📁 .添加系统调用.采用编译内核的方法
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/kernel/sys.c * *  Copyright (C) 1991, 1992  Linus Torvalds */#include <linux/config.h>#include <linux/module.h>#include <linux/mm.h>#include <linux/utsname.h>#include <linux/mman.h>#include <linux/smp_lock.h>#include <linux/notifier.h>#include <linux/reboot.h>#include <linux/prctl.h>#include <linux/init.h>#include <linux/highuid.h>#include <linux/dcookies.h>#include <linux/fs.h>#include <linux/times.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/unistd.h>#ifndef SET_UNALIGN_CTL# define SET_UNALIGN_CTL(a,b)	(-EINVAL)#endif#ifndef GET_UNALIGN_CTL# define GET_UNALIGN_CTL(a,b)	(-EINVAL)#endif#ifndef SET_FPEMU_CTL# define SET_FPEMU_CTL(a,b)	(-EINVAL)#endif#ifndef GET_FPEMU_CTL# define GET_FPEMU_CTL(a,b)	(-EINVAL)#endif#ifndef SET_FPEXC_CTL# define SET_FPEXC_CTL(a,b)	(-EINVAL)#endif#ifndef GET_FPEXC_CTL# define GET_FPEXC_CTL(a,b)	(-EINVAL)#endif/* * this is where the system-wide overflow UID and GID are defined, for * architectures that now have 32-bit UID/GID but didn't in the past */int overflowuid = DEFAULT_OVERFLOWUID;int overflowgid = DEFAULT_OVERFLOWGID;/* * the same as above, but for filesystems which can only store a 16-bit * UID and GID. as such, this is needed on all architectures */int fs_overflowuid = DEFAULT_FS_OVERFLOWUID;int fs_overflowgid = DEFAULT_FS_OVERFLOWUID;/* * this indicates whether you can reboot with ctrl-alt-del: the default is yes */int C_A_D = 1;int cad_pid = 1;extern int system_running;/* *	Notifier list for kernel code which wants to be called *	at shutdown. This is used to stop any idling DMA operations *	and the like.  */static struct notifier_block *reboot_notifier_list;rwlock_t notifier_lock = RW_LOCK_UNLOCKED;/** *	notifier_chain_register	- Add notifier to a notifier chain *	@list: Pointer to root list pointer *	@n: New entry in notifier chain * *	Adds a notifier to a notifier chain. * *	Currently always returns zero. */ int notifier_chain_register(struct notifier_block **list, struct notifier_block *n){	write_lock(&notifier_lock);	while(*list)	{		if(n->priority > (*list)->priority)			break;		list= &((*list)->next);	}	n->next = *list;	*list=n;	write_unlock(&notifier_lock);	return 0;}/** *	notifier_chain_unregister - Remove notifier from a notifier chain *	@nl: Pointer to root list pointer *	@n: New entry in notifier chain * *	Removes a notifier from a notifier chain. * *	Returns zero on success, or %-ENOENT on failure. */ int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n){	write_lock(&notifier_lock);	while((*nl)!=NULL)	{		if((*nl)==n)		{			*nl=n->next;			write_unlock(&notifier_lock);			return 0;		}		nl=&((*nl)->next);	}	write_unlock(&notifier_lock);	return -ENOENT;}/** *	notifier_call_chain - Call functions in a notifier chain *	@n: Pointer to root pointer of notifier chain *	@val: Value passed unmodified to notifier function *	@v: Pointer passed unmodified to notifier function * *	Calls each function in a notifier chain in turn. * *	If the return value of the notifier can be and'd *	with %NOTIFY_STOP_MASK, then notifier_call_chain *	will return immediately, with the return value of *	the notifier function which halted execution. *	Otherwise, the return value is the return value *	of the last notifier function called. */ int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v){	int ret=NOTIFY_DONE;	struct notifier_block *nb = *n;	while(nb)	{		ret=nb->notifier_call(nb,val,v);		if(ret&NOTIFY_STOP_MASK)		{			return ret;		}		nb=nb->next;	}	return ret;}/** *	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 notifier_chain_register *	always returns zero. */ int register_reboot_notifier(struct notifier_block * nb){	return notifier_chain_register(&reboot_notifier_list, nb);}#if !defined(CONFIG_PROFILING)long asmlinkage sys_lookup_dcookie(void){	return -ENOSYS;}#endif/** *	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 notifier_chain_unregister(&reboot_notifier_list, nb);}asmlinkage long sys_ni_syscall(void){	return -ENOSYS;}static int set_one_prio(struct task_struct *p, int niceval, int error){	if (p->uid != current->euid &&		p->uid != current->uid && !capable(CAP_SYS_NICE)) {		error = -EPERM;		goto out;	}	if (error == -ESRCH)		error = 0;	if (niceval < task_nice(p) && !capable(CAP_SYS_NICE))		error = -EACCES;	else		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;	struct pid *pid;	struct list_head *l;	int error = -EINVAL;	if (which > 2 || which < 0)		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)				who = current->pid;			p = find_task_by_pid(who);			if (p)				error = set_one_prio(p, niceval, error);			break;		case PRIO_PGRP:			if (!who)				who = current->pgrp;			for_each_task_pid(who, PIDTYPE_PGID, p, l, pid)				error = set_one_prio(p, niceval, error);			break;		case PRIO_USER:			if (!who)				user = current->user;			else				user = find_user(who);			if (!user)				goto out_unlock;			do_each_thread(g, p)				if (p->uid == who)					error = set_one_prio(p, niceval, error);			while_each_thread(g, p);			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 list_head *l;	struct pid *pid;	struct user_struct *user;	long niceval, retval = -ESRCH;	if (which > 2 || which < 0)		return -EINVAL;	read_lock(&tasklist_lock);	switch (which) {		case PRIO_PROCESS:			if (!who)				who = current->pid;			p = find_task_by_pid(who);			if (p) {				niceval = 20 - task_nice(p);				if (niceval > retval)					retval = niceval;			}			break;		case PRIO_PGRP:			if (!who)				who = current->pgrp;			for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) {				niceval = 20 - task_nice(p);				if (niceval > retval)					retval = niceval;			}			break;		case PRIO_USER:			if (!who)				user = current->user;			else				user = find_user(who);			if (!user)				goto out_unlock;			do_each_thread(g, p)				if (p->uid == who) {					niceval = 20 - task_nice(p);					if (niceval > retval)						retval = niceval;				}			while_each_thread(g, p);			break;	}out_unlock:	read_unlock(&tasklist_lock);	return retval;}/* * 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 * 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))		return -EINVAL;	lock_kernel();	switch (cmd) {	case LINUX_REBOOT_CMD_RESTART:		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);		printk(KERN_EMERG "Restarting system.\n");		machine_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:		notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);		printk(KERN_EMERG "System halted.\n");		machine_halt();		do_exit(0);		break;	case LINUX_REBOOT_CMD_POWER_OFF:		notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);		printk(KERN_EMERG "Power down.\n");		machine_power_off();		do_exit(0);		break;	case LINUX_REBOOT_CMD_RESTART2:		if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {			unlock_kernel();			return -EFAULT;		}		buffer[sizeof(buffer) - 1] = '\0';		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);		printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);		machine_restart(buffer);		break;	default:		unlock_kernel();		return -EINVAL;	}	unlock_kernel();	return 0;}static void deferred_cad(void *dummy){	notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);	machine_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 struct tq_struct cad_tq = {		routine: deferred_cad,	};	if (C_A_D)		schedule_task(&cad_tq);	else		kill_proc(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;	if (rgid != (gid_t) -1) {		if ((old_rgid == rgid) ||		    (current->egid==rgid) ||		    capable(CAP_SETGID))			new_rgid = rgid;		else

⌨️ 快捷键说明

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