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

📄 hooks.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  NSA Security-Enhanced Linux (SELinux) security module * *  This file contains the SELinux hook function implementations. * *  Authors:  Stephen Smalley, <sds@epoch.ncsc.mil> *            Chris Vance, <cvance@nai.com> *            Wayne Salamon, <wsalamon@nai.com> *            James Morris <jmorris@redhat.com> * *  Copyright (C) 2001,2002 Networks Associates Technology, Inc. *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. *                          <dgoeddel@trustedcs.com> *  Copyright (C) 2006 Hewlett-Packard Development Company, L.P. *                     Paul Moore, <paul.moore@hp.com> *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. *                     Yuichi Nakamura <ynakam@hitachisoft.jp> * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License version 2, *      as published by the Free Software Foundation. */#include <linux/init.h>#include <linux/kernel.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/security.h>#include <linux/xattr.h>#include <linux/capability.h>#include <linux/unistd.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/slab.h>#include <linux/pagemap.h>#include <linux/swap.h>#include <linux/spinlock.h>#include <linux/syscalls.h>#include <linux/file.h>#include <linux/namei.h>#include <linux/mount.h>#include <linux/ext2_fs.h>#include <linux/proc_fs.h>#include <linux/kd.h>#include <linux/netfilter_ipv4.h>#include <linux/netfilter_ipv6.h>#include <linux/tty.h>#include <net/icmp.h>#include <net/ip.h>		/* for local_port_range[] */#include <net/tcp.h>		/* struct or_callable used in sock_rcv_skb */#include <asm/uaccess.h>#include <asm/ioctls.h>#include <linux/bitops.h>#include <linux/interrupt.h>#include <linux/netdevice.h>	/* for network interface checks */#include <linux/netlink.h>#include <linux/tcp.h>#include <linux/udp.h>#include <linux/dccp.h>#include <linux/quota.h>#include <linux/un.h>		/* for Unix socket types */#include <net/af_unix.h>	/* for Unix socket types */#include <linux/parser.h>#include <linux/nfs_mount.h>#include <net/ipv6.h>#include <linux/hugetlb.h>#include <linux/personality.h>#include <linux/sysctl.h>#include <linux/audit.h>#include <linux/string.h>#include <linux/selinux.h>#include <linux/mutex.h>#include "avc.h"#include "objsec.h"#include "netif.h"#include "xfrm.h"#include "netlabel.h"#define XATTR_SELINUX_SUFFIX "selinux"#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIXextern unsigned int policydb_loaded_version;extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);extern int selinux_compat_net;extern struct security_operations *security_ops;#ifdef CONFIG_SECURITY_SELINUX_DEVELOPint selinux_enforcing = 0;static int __init enforcing_setup(char *str){	selinux_enforcing = simple_strtol(str,NULL,0);	return 1;}__setup("enforcing=", enforcing_setup);#endif#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAMint selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;static int __init selinux_enabled_setup(char *str){	selinux_enabled = simple_strtol(str, NULL, 0);	return 1;}__setup("selinux=", selinux_enabled_setup);#elseint selinux_enabled = 1;#endif/* Original (dummy) security module. */static struct security_operations *original_ops = NULL;/* Minimal support for a secondary security module,   just to allow the use of the dummy or capability modules.   The owlsm module can alternatively be used as a secondary   module as long as CONFIG_OWLSM_FD is not enabled. */static struct security_operations *secondary_ops = NULL;/* Lists of inode and superblock security structures initialized   before the policy was loaded. */static LIST_HEAD(superblock_security_head);static DEFINE_SPINLOCK(sb_security_lock);static struct kmem_cache *sel_inode_cache;/* Return security context for a given sid or just the context    length if the buffer is null or length is 0 */static int selinux_getsecurity(u32 sid, void *buffer, size_t size){	char *context;	unsigned len;	int rc;	rc = security_sid_to_context(sid, &context, &len);	if (rc)		return rc;	if (!buffer || !size)		goto getsecurity_exit;	if (size < len) {		len = -ERANGE;		goto getsecurity_exit;	}	memcpy(buffer, context, len);getsecurity_exit:	kfree(context);	return len;}/* Allocate and free functions for each kind of security blob. */static int task_alloc_security(struct task_struct *task){	struct task_security_struct *tsec;	tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);	if (!tsec)		return -ENOMEM;	tsec->task = task;	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;	task->security = tsec;	return 0;}static void task_free_security(struct task_struct *task){	struct task_security_struct *tsec = task->security;	task->security = NULL;	kfree(tsec);}static int inode_alloc_security(struct inode *inode){	struct task_security_struct *tsec = current->security;	struct inode_security_struct *isec;	isec = kmem_cache_zalloc(sel_inode_cache, GFP_KERNEL);	if (!isec)		return -ENOMEM;	mutex_init(&isec->lock);	INIT_LIST_HEAD(&isec->list);	isec->inode = inode;	isec->sid = SECINITSID_UNLABELED;	isec->sclass = SECCLASS_FILE;	isec->task_sid = tsec->sid;	inode->i_security = isec;	return 0;}static void inode_free_security(struct inode *inode){	struct inode_security_struct *isec = inode->i_security;	struct superblock_security_struct *sbsec = inode->i_sb->s_security;	spin_lock(&sbsec->isec_lock);	if (!list_empty(&isec->list))		list_del_init(&isec->list);	spin_unlock(&sbsec->isec_lock);	inode->i_security = NULL;	kmem_cache_free(sel_inode_cache, isec);}static int file_alloc_security(struct file *file){	struct task_security_struct *tsec = current->security;	struct file_security_struct *fsec;	fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);	if (!fsec)		return -ENOMEM;	fsec->file = file;	fsec->sid = tsec->sid;	fsec->fown_sid = tsec->sid;	file->f_security = fsec;	return 0;}static void file_free_security(struct file *file){	struct file_security_struct *fsec = file->f_security;	file->f_security = NULL;	kfree(fsec);}static int superblock_alloc_security(struct super_block *sb){	struct superblock_security_struct *sbsec;	sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);	if (!sbsec)		return -ENOMEM;	mutex_init(&sbsec->lock);	INIT_LIST_HEAD(&sbsec->list);	INIT_LIST_HEAD(&sbsec->isec_head);	spin_lock_init(&sbsec->isec_lock);	sbsec->sb = sb;	sbsec->sid = SECINITSID_UNLABELED;	sbsec->def_sid = SECINITSID_FILE;	sbsec->mntpoint_sid = SECINITSID_UNLABELED;	sb->s_security = sbsec;	return 0;}static void superblock_free_security(struct super_block *sb){	struct superblock_security_struct *sbsec = sb->s_security;	spin_lock(&sb_security_lock);	if (!list_empty(&sbsec->list))		list_del_init(&sbsec->list);	spin_unlock(&sb_security_lock);	sb->s_security = NULL;	kfree(sbsec);}static int sk_alloc_security(struct sock *sk, int family, gfp_t priority){	struct sk_security_struct *ssec;	ssec = kzalloc(sizeof(*ssec), priority);	if (!ssec)		return -ENOMEM;	ssec->sk = sk;	ssec->peer_sid = SECINITSID_UNLABELED;	ssec->sid = SECINITSID_UNLABELED;	sk->sk_security = ssec;	selinux_netlbl_sk_security_init(ssec, family);	return 0;}static void sk_free_security(struct sock *sk){	struct sk_security_struct *ssec = sk->sk_security;	sk->sk_security = NULL;	kfree(ssec);}/* The security server must be initialized before   any labeling or access decisions can be provided. */extern int ss_initialized;/* The file system's label must be initialized prior to use. */static char *labeling_behaviors[6] = {	"uses xattr",	"uses transition SIDs",	"uses task SIDs",	"uses genfs_contexts",	"not configured for labeling",	"uses mountpoint labeling",};static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);static inline int inode_doinit(struct inode *inode){	return inode_doinit_with_dentry(inode, NULL);}enum {	Opt_error = -1,	Opt_context = 1,	Opt_fscontext = 2,	Opt_defcontext = 4,	Opt_rootcontext = 8,};static match_table_t tokens = {	{Opt_context, "context=%s"},	{Opt_fscontext, "fscontext=%s"},	{Opt_defcontext, "defcontext=%s"},	{Opt_rootcontext, "rootcontext=%s"},	{Opt_error, NULL},};#define SEL_MOUNT_FAIL_MSG "SELinux:  duplicate or incompatible mount options\n"static int may_context_mount_sb_relabel(u32 sid,			struct superblock_security_struct *sbsec,			struct task_security_struct *tsec){	int rc;	rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,			  FILESYSTEM__RELABELFROM, NULL);	if (rc)		return rc;	rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,			  FILESYSTEM__RELABELTO, NULL);	return rc;}static int may_context_mount_inode_relabel(u32 sid,			struct superblock_security_struct *sbsec,			struct task_security_struct *tsec){	int rc;	rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,			  FILESYSTEM__RELABELFROM, NULL);	if (rc)		return rc;	rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,			  FILESYSTEM__ASSOCIATE, NULL);	return rc;}static int try_context_mount(struct super_block *sb, void *data){	char *context = NULL, *defcontext = NULL;	char *fscontext = NULL, *rootcontext = NULL;	const char *name;	u32 sid;	int alloc = 0, rc = 0, seen = 0;	struct task_security_struct *tsec = current->security;	struct superblock_security_struct *sbsec = sb->s_security;	if (!data)		goto out;	name = sb->s_type->name;	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {		/* NFS we understand. */		if (!strcmp(name, "nfs")) {			struct nfs_mount_data *d = data;			if (d->version <  NFS_MOUNT_VERSION)				goto out;			if (d->context[0]) {				context = d->context;				seen |= Opt_context;			}		} else			goto out;	} else {		/* Standard string-based options. */		char *p, *options = data;		while ((p = strsep(&options, "|")) != NULL) {			int token;			substring_t args[MAX_OPT_ARGS];			if (!*p)				continue;			token = match_token(p, tokens, args);			switch (token) {			case Opt_context:				if (seen & (Opt_context|Opt_defcontext)) {					rc = -EINVAL;					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);					goto out_free;				}				context = match_strdup(&args[0]);				if (!context) {					rc = -ENOMEM;					goto out_free;				}				if (!alloc)					alloc = 1;				seen |= Opt_context;				break;			case Opt_fscontext:				if (seen & Opt_fscontext) {					rc = -EINVAL;					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);					goto out_free;				}				fscontext = match_strdup(&args[0]);				if (!fscontext) {					rc = -ENOMEM;					goto out_free;				}				if (!alloc)					alloc = 1;				seen |= Opt_fscontext;				break;			case Opt_rootcontext:				if (seen & Opt_rootcontext) {					rc = -EINVAL;					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);					goto out_free;				}				rootcontext = match_strdup(&args[0]);				if (!rootcontext) {					rc = -ENOMEM;					goto out_free;				}				if (!alloc)					alloc = 1;				seen |= Opt_rootcontext;				break;			case Opt_defcontext:				if (sbsec->behavior != SECURITY_FS_USE_XATTR) {					rc = -EINVAL;					printk(KERN_WARNING "SELinux:  "					       "defcontext option is invalid "					       "for this filesystem type\n");					goto out_free;				}				if (seen & (Opt_context|Opt_defcontext)) {					rc = -EINVAL;					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);					goto out_free;				}				defcontext = match_strdup(&args[0]);				if (!defcontext) {					rc = -ENOMEM;					goto out_free;				}				if (!alloc)					alloc = 1;				seen |= Opt_defcontext;				break;			default:				rc = -EINVAL;				printk(KERN_WARNING "SELinux:  unknown mount "				       "option\n");				goto out_free;			}		}	}	if (!seen)		goto out;	/* sets the context of the superblock for the fs being mounted. */	if (fscontext) {		rc = security_context_to_sid(fscontext, strlen(fscontext), &sid);		if (rc) {			printk(KERN_WARNING "SELinux: security_context_to_sid"			       "(%s) failed for (dev %s, type %s) errno=%d\n",			       fscontext, sb->s_id, name, rc);			goto out_free;		}		rc = may_context_mount_sb_relabel(sid, sbsec, tsec);		if (rc)			goto out_free;		sbsec->sid = sid;	}	/*	 * Switch to using mount point labeling behavior.	 * sets the label used on all file below the mountpoint, and will set	 * the superblock context if not already set.	 */	if (context) {		rc = security_context_to_sid(context, strlen(context), &sid);		if (rc) {			printk(KERN_WARNING "SELinux: security_context_to_sid"			       "(%s) failed for (dev %s, type %s) errno=%d\n",			       context, sb->s_id, name, rc);			goto out_free;		}		if (!fscontext) {			rc = may_context_mount_sb_relabel(sid, sbsec, tsec);			if (rc)				goto out_free;			sbsec->sid = sid;		} else {			rc = may_context_mount_inode_relabel(sid, sbsec, tsec);			if (rc)

⌨️ 快捷键说明

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