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

📄 selinuxfs.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	kfree(scon);	return length;}static ssize_t sel_write_create(struct file * file, char *buf, size_t size){	char *scon, *tcon;	u32 ssid, tsid, newsid;	u16 tclass;	ssize_t length;	char *newcon;	u32 len;	length = task_has_security(current, SECURITY__COMPUTE_CREATE);	if (length)		return length;	length = -ENOMEM;	scon = kzalloc(size+1, GFP_KERNEL);	if (!scon)		return length;	tcon = kzalloc(size+1, GFP_KERNEL);	if (!tcon)		goto out;	length = -EINVAL;	if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)		goto out2;	length = security_context_to_sid(scon, strlen(scon)+1, &ssid);	if (length < 0)		goto out2;	length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);	if (length < 0)		goto out2;	length = security_transition_sid(ssid, tsid, tclass, &newsid);	if (length < 0)		goto out2;	length = security_sid_to_context(newsid, &newcon, &len);	if (length < 0)		goto out2;	if (len > SIMPLE_TRANSACTION_LIMIT) {		printk(KERN_ERR "%s:  context size (%u) exceeds payload "		       "max\n", __FUNCTION__, len);		length = -ERANGE;		goto out3;	}	memcpy(buf, newcon, len);	length = len;out3:	kfree(newcon);out2:	kfree(tcon);out:	kfree(scon);	return length;}static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size){	char *scon, *tcon;	u32 ssid, tsid, newsid;	u16 tclass;	ssize_t length;	char *newcon;	u32 len;	length = task_has_security(current, SECURITY__COMPUTE_RELABEL);	if (length)		return length;	length = -ENOMEM;	scon = kzalloc(size+1, GFP_KERNEL);	if (!scon)		return length;	tcon = kzalloc(size+1, GFP_KERNEL);	if (!tcon)		goto out;	length = -EINVAL;	if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)		goto out2;	length = security_context_to_sid(scon, strlen(scon)+1, &ssid);	if (length < 0)		goto out2;	length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);	if (length < 0)		goto out2;	length = security_change_sid(ssid, tsid, tclass, &newsid);	if (length < 0)		goto out2;	length = security_sid_to_context(newsid, &newcon, &len);	if (length < 0)		goto out2;	if (len > SIMPLE_TRANSACTION_LIMIT) {		length = -ERANGE;		goto out3;	}	memcpy(buf, newcon, len);	length = len;out3:	kfree(newcon);out2:	kfree(tcon);out:	kfree(scon);	return length;}static ssize_t sel_write_user(struct file * file, char *buf, size_t size){	char *con, *user, *ptr;	u32 sid, *sids;	ssize_t length;	char *newcon;	int i, rc;	u32 len, nsids;	length = task_has_security(current, SECURITY__COMPUTE_USER);	if (length)		return length;	length = -ENOMEM;	con = kzalloc(size+1, GFP_KERNEL);	if (!con)		return length;	user = kzalloc(size+1, GFP_KERNEL);	if (!user)		goto out;	length = -EINVAL;	if (sscanf(buf, "%s %s", con, user) != 2)		goto out2;	length = security_context_to_sid(con, strlen(con)+1, &sid);	if (length < 0)		goto out2;	length = security_get_user_sids(sid, user, &sids, &nsids);	if (length < 0)		goto out2;	length = sprintf(buf, "%u", nsids) + 1;	ptr = buf + length;	for (i = 0; i < nsids; i++) {		rc = security_sid_to_context(sids[i], &newcon, &len);		if (rc) {			length = rc;			goto out3;		}		if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {			kfree(newcon);			length = -ERANGE;			goto out3;		}		memcpy(ptr, newcon, len);		kfree(newcon);		ptr += len;		length += len;	}out3:	kfree(sids);out2:	kfree(user);out:	kfree(con);	return length;}static ssize_t sel_write_member(struct file * file, char *buf, size_t size){	char *scon, *tcon;	u32 ssid, tsid, newsid;	u16 tclass;	ssize_t length;	char *newcon;	u32 len;	length = task_has_security(current, SECURITY__COMPUTE_MEMBER);	if (length)		return length;	length = -ENOMEM;	scon = kzalloc(size+1, GFP_KERNEL);	if (!scon)		return length;	tcon = kzalloc(size+1, GFP_KERNEL);	if (!tcon)		goto out;	length = -EINVAL;	if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)		goto out2;	length = security_context_to_sid(scon, strlen(scon)+1, &ssid);	if (length < 0)		goto out2;	length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);	if (length < 0)		goto out2;	length = security_member_sid(ssid, tsid, tclass, &newsid);	if (length < 0)		goto out2;	length = security_sid_to_context(newsid, &newcon, &len);	if (length < 0)		goto out2;	if (len > SIMPLE_TRANSACTION_LIMIT) {		printk(KERN_ERR "%s:  context size (%u) exceeds payload "		       "max\n", __FUNCTION__, len);		length = -ERANGE;		goto out3;	}	memcpy(buf, newcon, len);	length = len;out3:	kfree(newcon);out2:	kfree(tcon);out:	kfree(scon);	return length;}static struct inode *sel_make_inode(struct super_block *sb, int mode){	struct inode *ret = new_inode(sb);	if (ret) {		ret->i_mode = mode;		ret->i_uid = ret->i_gid = 0;		ret->i_blocks = 0;		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;	}	return ret;}static ssize_t sel_read_bool(struct file *filep, char __user *buf,			     size_t count, loff_t *ppos){	char *page = NULL;	ssize_t length;	ssize_t ret;	int cur_enforcing;	struct inode *inode = filep->f_path.dentry->d_inode;	unsigned index = inode->i_ino & SEL_INO_MASK;	const char *name = filep->f_path.dentry->d_name.name;	mutex_lock(&sel_mutex);	if (index >= bool_num || strcmp(name, bool_pending_names[index])) {		ret = -EINVAL;		goto out;	}	if (count > PAGE_SIZE) {		ret = -EINVAL;		goto out;	}	if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {		ret = -ENOMEM;		goto out;	}	cur_enforcing = security_get_bool_value(index);	if (cur_enforcing < 0) {		ret = cur_enforcing;		goto out;	}	length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,			  bool_pending_values[index]);	ret = simple_read_from_buffer(buf, count, ppos, page, length);out:	mutex_unlock(&sel_mutex);	if (page)		free_page((unsigned long)page);	return ret;}static ssize_t sel_write_bool(struct file *filep, const char __user *buf,			      size_t count, loff_t *ppos){	char *page = NULL;	ssize_t length;	int new_value;	struct inode *inode = filep->f_path.dentry->d_inode;	unsigned index = inode->i_ino & SEL_INO_MASK;	const char *name = filep->f_path.dentry->d_name.name;	mutex_lock(&sel_mutex);	length = task_has_security(current, SECURITY__SETBOOL);	if (length)		goto out;	if (index >= bool_num || strcmp(name, bool_pending_names[index])) {		length = -EINVAL;		goto out;	}	if (count >= PAGE_SIZE) {		length = -ENOMEM;		goto out;	}	if (*ppos != 0) {		/* No partial writes. */		length = -EINVAL;		goto out;	}	page = (char*)get_zeroed_page(GFP_KERNEL);	if (!page) {		length = -ENOMEM;		goto out;	}	length = -EFAULT;	if (copy_from_user(page, buf, count))		goto out;	length = -EINVAL;	if (sscanf(page, "%d", &new_value) != 1)		goto out;	if (new_value)		new_value = 1;	bool_pending_values[index] = new_value;	length = count;out:	mutex_unlock(&sel_mutex);	if (page)		free_page((unsigned long) page);	return length;}static const struct file_operations sel_bool_ops = {	.read           = sel_read_bool,	.write          = sel_write_bool,};static ssize_t sel_commit_bools_write(struct file *filep,				      const char __user *buf,				      size_t count, loff_t *ppos){	char *page = NULL;	ssize_t length;	int new_value;	mutex_lock(&sel_mutex);	length = task_has_security(current, SECURITY__SETBOOL);	if (length)		goto out;	if (count >= PAGE_SIZE) {		length = -ENOMEM;		goto out;	}	if (*ppos != 0) {		/* No partial writes. */		goto out;	}	page = (char*)get_zeroed_page(GFP_KERNEL);	if (!page) {		length = -ENOMEM;		goto out;	}	length = -EFAULT;	if (copy_from_user(page, buf, count))		goto out;	length = -EINVAL;	if (sscanf(page, "%d", &new_value) != 1)		goto out;	if (new_value && bool_pending_values) {		security_set_bools(bool_num, bool_pending_values);	}	length = count;out:	mutex_unlock(&sel_mutex);	if (page)		free_page((unsigned long) page);	return length;}static const struct file_operations sel_commit_bools_ops = {	.write          = sel_commit_bools_write,};static void sel_remove_entries(struct dentry *de){	struct list_head *node;	spin_lock(&dcache_lock);	node = de->d_subdirs.next;	while (node != &de->d_subdirs) {		struct dentry *d = list_entry(node, struct dentry, d_u.d_child);		list_del_init(node);		if (d->d_inode) {			d = dget_locked(d);			spin_unlock(&dcache_lock);			d_delete(d);			simple_unlink(de->d_inode, d);			dput(d);			spin_lock(&dcache_lock);		}		node = de->d_subdirs.next;	}	spin_unlock(&dcache_lock);}#define BOOL_DIR_NAME "booleans"static int sel_make_bools(void){	int i, ret = 0;	ssize_t len;	struct dentry *dentry = NULL;	struct dentry *dir = bool_dir;	struct inode *inode = NULL;	struct inode_security_struct *isec;	char **names = NULL, *page;	int num;	int *values = NULL;	u32 sid;	/* remove any existing files */	kfree(bool_pending_names);	kfree(bool_pending_values);	bool_pending_names = NULL;	bool_pending_values = NULL;	sel_remove_entries(dir);	if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))		return -ENOMEM;	ret = security_get_bools(&num, &names, &values);	if (ret != 0)		goto out;	for (i = 0; i < num; i++) {		dentry = d_alloc_name(dir, names[i]);		if (!dentry) {			ret = -ENOMEM;			goto err;		}		inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);		if (!inode) {			ret = -ENOMEM;			goto err;		}		len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]);		if (len < 0) {			ret = -EINVAL;			goto err;		} else if (len >= PAGE_SIZE) {			ret = -ENAMETOOLONG;			goto err;		}		isec = (struct inode_security_struct*)inode->i_security;		if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))			goto err;		isec->sid = sid;		isec->initialized = 1;		inode->i_fop = &sel_bool_ops;		inode->i_ino = i|SEL_BOOL_INO_OFFSET;		d_add(dentry, inode);	}	bool_num = num;	bool_pending_names = names;	bool_pending_values = values;out:	free_page((unsigned long)page);	return ret;err:	if (names) {		for (i = 0; i < num; i++)			kfree(names[i]);		kfree(names);	}	kfree(values);	sel_remove_entries(dir);	ret = -ENOMEM;	goto out;}#define NULL_FILE_NAME "null"struct dentry *selinux_null = NULL;static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,					    size_t count, loff_t *ppos){	char tmpbuf[TMPBUFLEN];	ssize_t length;	length = scnprintf(tmpbuf, TMPBUFLEN, "%u", avc_cache_threshold);	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);}static ssize_t sel_write_avc_cache_threshold(struct file * file,					     const char __user * buf,					     size_t count, loff_t *ppos){	char *page;	ssize_t ret;	int new_value;	if (count >= PAGE_SIZE) {		ret = -ENOMEM;		goto out;	}	if (*ppos != 0) {		/* No partial writes. */		ret = -EINVAL;		goto out;	}	page = (char*)get_zeroed_page(GFP_KERNEL);	if (!page) {		ret = -ENOMEM;		goto out;	}	if (copy_from_user(page, buf, count)) {		ret = -EFAULT;		goto out_free;	}	if (sscanf(page, "%u", &new_value) != 1) {		ret = -EINVAL;		goto out;	}	if (new_value != avc_cache_threshold) {		ret = task_has_security(current, SECURITY__SETSECPARAM);		if (ret)			goto out_free;		avc_cache_threshold = new_value;	}	ret = count;out_free:	free_page((unsigned long)page);out:	return ret;}

⌨️ 快捷键说明

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