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

📄 hooks.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				goto out_free;		}		sbsec->mntpoint_sid = sid;		sbsec->behavior = SECURITY_FS_USE_MNTPOINT;	}	if (rootcontext) {		struct inode *inode = sb->s_root->d_inode;		struct inode_security_struct *isec = inode->i_security;		rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid);		if (rc) {			printk(KERN_WARNING "SELinux: security_context_to_sid"			       "(%s) failed for (dev %s, type %s) errno=%d\n",			       rootcontext, sb->s_id, name, rc);			goto out_free;		}		rc = may_context_mount_inode_relabel(sid, sbsec, tsec);		if (rc)			goto out_free;		isec->sid = sid;		isec->initialized = 1;	}	if (defcontext) {		rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);		if (rc) {			printk(KERN_WARNING "SELinux: security_context_to_sid"			       "(%s) failed for (dev %s, type %s) errno=%d\n",			       defcontext, sb->s_id, name, rc);			goto out_free;		}		if (sid == sbsec->def_sid)			goto out_free;		rc = may_context_mount_inode_relabel(sid, sbsec, tsec);		if (rc)			goto out_free;		sbsec->def_sid = sid;	}out_free:	if (alloc) {		kfree(context);		kfree(defcontext);		kfree(fscontext);		kfree(rootcontext);	}out:	return rc;}static int superblock_doinit(struct super_block *sb, void *data){	struct superblock_security_struct *sbsec = sb->s_security;	struct dentry *root = sb->s_root;	struct inode *inode = root->d_inode;	int rc = 0;	mutex_lock(&sbsec->lock);	if (sbsec->initialized)		goto out;	if (!ss_initialized) {		/* Defer initialization until selinux_complete_init,		   after the initial policy is loaded and the security		   server is ready to handle calls. */		spin_lock(&sb_security_lock);		if (list_empty(&sbsec->list))			list_add(&sbsec->list, &superblock_security_head);		spin_unlock(&sb_security_lock);		goto out;	}	/* Determine the labeling behavior to use for this filesystem type. */	rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);	if (rc) {		printk(KERN_WARNING "%s:  security_fs_use(%s) returned %d\n",		       __FUNCTION__, sb->s_type->name, rc);		goto out;	}	rc = try_context_mount(sb, data);	if (rc)		goto out;	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {		/* Make sure that the xattr handler exists and that no		   error other than -ENODATA is returned by getxattr on		   the root directory.  -ENODATA is ok, as this may be		   the first boot of the SELinux kernel before we have		   assigned xattr values to the filesystem. */		if (!inode->i_op->getxattr) {			printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "			       "xattr support\n", sb->s_id, sb->s_type->name);			rc = -EOPNOTSUPP;			goto out;		}		rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);		if (rc < 0 && rc != -ENODATA) {			if (rc == -EOPNOTSUPP)				printk(KERN_WARNING "SELinux: (dev %s, type "				       "%s) has no security xattr handler\n",				       sb->s_id, sb->s_type->name);			else				printk(KERN_WARNING "SELinux: (dev %s, type "				       "%s) getxattr errno %d\n", sb->s_id,				       sb->s_type->name, -rc);			goto out;		}	}	if (strcmp(sb->s_type->name, "proc") == 0)		sbsec->proc = 1;	sbsec->initialized = 1;	if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) {		printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",		       sb->s_id, sb->s_type->name);	}	else {		printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",		       sb->s_id, sb->s_type->name,		       labeling_behaviors[sbsec->behavior-1]);	}	/* Initialize the root inode. */	rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root);	/* Initialize any other inodes associated with the superblock, e.g.	   inodes created prior to initial policy load or inodes created	   during get_sb by a pseudo filesystem that directly	   populates itself. */	spin_lock(&sbsec->isec_lock);next_inode:	if (!list_empty(&sbsec->isec_head)) {		struct inode_security_struct *isec =				list_entry(sbsec->isec_head.next,				           struct inode_security_struct, list);		struct inode *inode = isec->inode;		spin_unlock(&sbsec->isec_lock);		inode = igrab(inode);		if (inode) {			if (!IS_PRIVATE (inode))				inode_doinit(inode);			iput(inode);		}		spin_lock(&sbsec->isec_lock);		list_del_init(&isec->list);		goto next_inode;	}	spin_unlock(&sbsec->isec_lock);out:	mutex_unlock(&sbsec->lock);	return rc;}static inline u16 inode_mode_to_security_class(umode_t mode){	switch (mode & S_IFMT) {	case S_IFSOCK:		return SECCLASS_SOCK_FILE;	case S_IFLNK:		return SECCLASS_LNK_FILE;	case S_IFREG:		return SECCLASS_FILE;	case S_IFBLK:		return SECCLASS_BLK_FILE;	case S_IFDIR:		return SECCLASS_DIR;	case S_IFCHR:		return SECCLASS_CHR_FILE;	case S_IFIFO:		return SECCLASS_FIFO_FILE;	}	return SECCLASS_FILE;}static inline int default_protocol_stream(int protocol){	return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);}static inline int default_protocol_dgram(int protocol){	return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);}static inline u16 socket_type_to_security_class(int family, int type, int protocol){	switch (family) {	case PF_UNIX:		switch (type) {		case SOCK_STREAM:		case SOCK_SEQPACKET:			return SECCLASS_UNIX_STREAM_SOCKET;		case SOCK_DGRAM:			return SECCLASS_UNIX_DGRAM_SOCKET;		}		break;	case PF_INET:	case PF_INET6:		switch (type) {		case SOCK_STREAM:			if (default_protocol_stream(protocol))				return SECCLASS_TCP_SOCKET;			else				return SECCLASS_RAWIP_SOCKET;		case SOCK_DGRAM:			if (default_protocol_dgram(protocol))				return SECCLASS_UDP_SOCKET;			else				return SECCLASS_RAWIP_SOCKET;		case SOCK_DCCP:			return SECCLASS_DCCP_SOCKET;		default:			return SECCLASS_RAWIP_SOCKET;		}		break;	case PF_NETLINK:		switch (protocol) {		case NETLINK_ROUTE:			return SECCLASS_NETLINK_ROUTE_SOCKET;		case NETLINK_FIREWALL:			return SECCLASS_NETLINK_FIREWALL_SOCKET;		case NETLINK_INET_DIAG:			return SECCLASS_NETLINK_TCPDIAG_SOCKET;		case NETLINK_NFLOG:			return SECCLASS_NETLINK_NFLOG_SOCKET;		case NETLINK_XFRM:			return SECCLASS_NETLINK_XFRM_SOCKET;		case NETLINK_SELINUX:			return SECCLASS_NETLINK_SELINUX_SOCKET;		case NETLINK_AUDIT:			return SECCLASS_NETLINK_AUDIT_SOCKET;		case NETLINK_IP6_FW:			return SECCLASS_NETLINK_IP6FW_SOCKET;		case NETLINK_DNRTMSG:			return SECCLASS_NETLINK_DNRT_SOCKET;		case NETLINK_KOBJECT_UEVENT:			return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;		default:			return SECCLASS_NETLINK_SOCKET;		}	case PF_PACKET:		return SECCLASS_PACKET_SOCKET;	case PF_KEY:		return SECCLASS_KEY_SOCKET;	case PF_APPLETALK:		return SECCLASS_APPLETALK_SOCKET;	}	return SECCLASS_SOCKET;}#ifdef CONFIG_PROC_FSstatic int selinux_proc_get_sid(struct proc_dir_entry *de,				u16 tclass,				u32 *sid){	int buflen, rc;	char *buffer, *path, *end;	buffer = (char*)__get_free_page(GFP_KERNEL);	if (!buffer)		return -ENOMEM;	buflen = PAGE_SIZE;	end = buffer+buflen;	*--end = '\0';	buflen--;	path = end-1;	*path = '/';	while (de && de != de->parent) {		buflen -= de->namelen + 1;		if (buflen < 0)			break;		end -= de->namelen;		memcpy(end, de->name, de->namelen);		*--end = '/';		path = end;		de = de->parent;	}	rc = security_genfs_sid("proc", path, tclass, sid);	free_page((unsigned long)buffer);	return rc;}#elsestatic int selinux_proc_get_sid(struct proc_dir_entry *de,				u16 tclass,				u32 *sid){	return -EINVAL;}#endif/* The inode's security attributes must be initialized before first use. */static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry){	struct superblock_security_struct *sbsec = NULL;	struct inode_security_struct *isec = inode->i_security;	u32 sid;	struct dentry *dentry;#define INITCONTEXTLEN 255	char *context = NULL;	unsigned len = 0;	int rc = 0;	if (isec->initialized)		goto out;	mutex_lock(&isec->lock);	if (isec->initialized)		goto out_unlock;	sbsec = inode->i_sb->s_security;	if (!sbsec->initialized) {		/* Defer initialization until selinux_complete_init,		   after the initial policy is loaded and the security		   server is ready to handle calls. */		spin_lock(&sbsec->isec_lock);		if (list_empty(&isec->list))			list_add(&isec->list, &sbsec->isec_head);		spin_unlock(&sbsec->isec_lock);		goto out_unlock;	}	switch (sbsec->behavior) {	case SECURITY_FS_USE_XATTR:		if (!inode->i_op->getxattr) {			isec->sid = sbsec->def_sid;			break;		}		/* Need a dentry, since the xattr API requires one.		   Life would be simpler if we could just pass the inode. */		if (opt_dentry) {			/* Called from d_instantiate or d_splice_alias. */			dentry = dget(opt_dentry);		} else {			/* Called from selinux_complete_init, try to find a dentry. */			dentry = d_find_alias(inode);		}		if (!dentry) {			printk(KERN_WARNING "%s:  no dentry for dev=%s "			       "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,			       inode->i_ino);			goto out_unlock;		}		len = INITCONTEXTLEN;		context = kmalloc(len, GFP_KERNEL);		if (!context) {			rc = -ENOMEM;			dput(dentry);			goto out_unlock;		}		rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,					   context, len);		if (rc == -ERANGE) {			/* Need a larger buffer.  Query for the right size. */			rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,						   NULL, 0);			if (rc < 0) {				dput(dentry);				goto out_unlock;			}			kfree(context);			len = rc;			context = kmalloc(len, GFP_KERNEL);			if (!context) {				rc = -ENOMEM;				dput(dentry);				goto out_unlock;			}			rc = inode->i_op->getxattr(dentry,						   XATTR_NAME_SELINUX,						   context, len);		}		dput(dentry);		if (rc < 0) {			if (rc != -ENODATA) {				printk(KERN_WARNING "%s:  getxattr returned "				       "%d for dev=%s ino=%ld\n", __FUNCTION__,				       -rc, inode->i_sb->s_id, inode->i_ino);				kfree(context);				goto out_unlock;			}			/* Map ENODATA to the default file SID */			sid = sbsec->def_sid;			rc = 0;		} else {			rc = security_context_to_sid_default(context, rc, &sid,			                                     sbsec->def_sid);			if (rc) {				printk(KERN_WARNING "%s:  context_to_sid(%s) "				       "returned %d for dev=%s ino=%ld\n",				       __FUNCTION__, context, -rc,				       inode->i_sb->s_id, inode->i_ino);				kfree(context);				/* Leave with the unlabeled SID */				rc = 0;				break;			}		}		kfree(context);		isec->sid = sid;		break;	case SECURITY_FS_USE_TASK:		isec->sid = isec->task_sid;		break;	case SECURITY_FS_USE_TRANS:		/* Default to the fs SID. */		isec->sid = sbsec->sid;		/* Try to obtain a transition SID. */		isec->sclass = inode_mode_to_security_class(inode->i_mode);		rc = security_transition_sid(isec->task_sid,					     sbsec->sid,					     isec->sclass,					     &sid);		if (rc)			goto out_unlock;		isec->sid = sid;		break;	case SECURITY_FS_USE_MNTPOINT:		isec->sid = sbsec->mntpoint_sid;		break;	default:		/* Default to the fs superblock SID. */		isec->sid = sbsec->sid;		if (sbsec->proc) {			struct proc_inode *proci = PROC_I(inode);			if (proci->pde) {				isec->sclass = inode_mode_to_security_class(inode->i_mode);				rc = selinux_proc_get_sid(proci->pde,							  isec->sclass,							  &sid);				if (rc)					goto out_unlock;				isec->sid = sid;			}		}		break;	}	isec->initialized = 1;out_unlock:	mutex_unlock(&isec->lock);out:	if (isec->sclass == SECCLASS_FILE)		isec->sclass = inode_mode_to_security_class(inode->i_mode);	return rc;}/* Convert a Linux signal to an access vector. */static inline u32 signal_to_av(int sig){	u32 perm = 0;	switch (sig) {	case SIGCHLD:		/* Commonly granted from child to parent. */		perm = PROCESS__SIGCHLD;		break;	case SIGKILL:		/* Cannot be caught or ignored */		perm = PROCESS__SIGKILL;		break;	case SIGSTOP:		/* Cannot be caught or ignored */		perm = PROCESS__SIGSTOP;		break;	default:		/* All other signals. */		perm = PROCESS__SIGNAL;		break;	}	return perm;}/* Check permission betweeen a pair of tasks, e.g. signal checks,   fork check, ptrace check, etc. */static int task_has_perm(struct task_struct *tsk1,			 struct task_struct *tsk2,			 u32 perms){	struct task_security_struct *tsec1, *tsec2;	tsec1 = tsk1->security;	tsec2 = tsk2->security;	return avc_has_perm(tsec1->sid, tsec2->sid,			    SECCLASS_PROCESS, perms, NULL);}/* Check whether a task is allowed to use a capability. */static int task_has_capability(struct task_struct *tsk,			       int cap){	struct task_security_struct *tsec;	struct avc_audit_data ad;	tsec = tsk->security;	AVC_AUDIT_DATA_INIT(&ad,CAP);	ad.tsk = tsk;	ad.u.cap = cap;	return avc_has_perm(tsec->sid, tsec->sid,			    SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);}/* Check whether a task is allowed to use a system operation. */static int task_has_system(struct task_struct *tsk,			   u32 perms){	struct task_security_struct *tsec;	tsec = tsk->security;	return avc_has_perm(tsec->sid, SECINITSID_KERNEL,			    SECCLASS_SYSTEM, perms, NULL);}/* Check whether a task has a particular permission to an inode.   The 'adp' parameter is optional and allows other audit

⌨️ 快捷键说明

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