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

📄 sidtab.c

📁 linux-2.6.15.6
💻 C
字号:
/* * Implementation of the SID table type. * * Author : Stephen Smalley, <sds@epoch.ncsc.mil> */#include <linux/kernel.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <linux/errno.h>#include <linux/sched.h>#include "flask.h"#include "security.h"#include "sidtab.h"#define SIDTAB_HASH(sid) \(sid & SIDTAB_HASH_MASK)#define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)#define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)#define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)int sidtab_init(struct sidtab *s){	int i;	s->htable = kmalloc(sizeof(*(s->htable)) * SIDTAB_SIZE, GFP_ATOMIC);	if (!s->htable)		return -ENOMEM;	for (i = 0; i < SIDTAB_SIZE; i++)		s->htable[i] = NULL;	s->nel = 0;	s->next_sid = 1;	s->shutdown = 0;	INIT_SIDTAB_LOCK(s);	return 0;}int sidtab_insert(struct sidtab *s, u32 sid, struct context *context){	int hvalue, rc = 0;	struct sidtab_node *prev, *cur, *newnode;	if (!s) {		rc = -ENOMEM;		goto out;	}	hvalue = SIDTAB_HASH(sid);	prev = NULL;	cur = s->htable[hvalue];	while (cur != NULL && sid > cur->sid) {		prev = cur;		cur = cur->next;	}	if (cur && sid == cur->sid) {		rc = -EEXIST;		goto out;	}	newnode = kmalloc(sizeof(*newnode), GFP_ATOMIC);	if (newnode == NULL) {		rc = -ENOMEM;		goto out;	}	newnode->sid = sid;	if (context_cpy(&newnode->context, context)) {		kfree(newnode);		rc = -ENOMEM;		goto out;	}	if (prev) {		newnode->next = prev->next;		wmb();		prev->next = newnode;	} else {		newnode->next = s->htable[hvalue];		wmb();		s->htable[hvalue] = newnode;	}	s->nel++;	if (sid >= s->next_sid)		s->next_sid = sid + 1;out:	return rc;}struct context *sidtab_search(struct sidtab *s, u32 sid){	int hvalue;	struct sidtab_node *cur;	if (!s)		return NULL;	hvalue = SIDTAB_HASH(sid);	cur = s->htable[hvalue];	while (cur != NULL && sid > cur->sid)		cur = cur->next;	if (cur == NULL || sid != cur->sid) {		/* Remap invalid SIDs to the unlabeled SID. */		sid = SECINITSID_UNLABELED;		hvalue = SIDTAB_HASH(sid);		cur = s->htable[hvalue];		while (cur != NULL && sid > cur->sid)			cur = cur->next;		if (!cur || sid != cur->sid)			return NULL;	}	return &cur->context;}int sidtab_map(struct sidtab *s,	       int (*apply) (u32 sid,			     struct context *context,			     void *args),	       void *args){	int i, rc = 0;	struct sidtab_node *cur;	if (!s)		goto out;	for (i = 0; i < SIDTAB_SIZE; i++) {		cur = s->htable[i];		while (cur != NULL) {			rc = apply(cur->sid, &cur->context, args);			if (rc)				goto out;			cur = cur->next;		}	}out:	return rc;}void sidtab_map_remove_on_error(struct sidtab *s,				int (*apply) (u32 sid,					      struct context *context,					      void *args),				void *args){	int i, ret;	struct sidtab_node *last, *cur, *temp;	if (!s)		return;	for (i = 0; i < SIDTAB_SIZE; i++) {		last = NULL;		cur = s->htable[i];		while (cur != NULL) {			ret = apply(cur->sid, &cur->context, args);			if (ret) {				if (last) {					last->next = cur->next;				} else {					s->htable[i] = cur->next;				}				temp = cur;				cur = cur->next;				context_destroy(&temp->context);				kfree(temp);				s->nel--;			} else {				last = cur;				cur = cur->next;			}		}	}	return;}static inline u32 sidtab_search_context(struct sidtab *s,						  struct context *context){	int i;	struct sidtab_node *cur;	for (i = 0; i < SIDTAB_SIZE; i++) {		cur = s->htable[i];		while (cur != NULL) {			if (context_cmp(&cur->context, context))				return cur->sid;			cur = cur->next;		}	}	return 0;}int sidtab_context_to_sid(struct sidtab *s,			  struct context *context,			  u32 *out_sid){	u32 sid;	int ret = 0;	unsigned long flags;	*out_sid = SECSID_NULL;	sid = sidtab_search_context(s, context);	if (!sid) {		SIDTAB_LOCK(s, flags);		/* Rescan now that we hold the lock. */		sid = sidtab_search_context(s, context);		if (sid)			goto unlock_out;		/* No SID exists for the context.  Allocate a new one. */		if (s->next_sid == UINT_MAX || s->shutdown) {			ret = -ENOMEM;			goto unlock_out;		}		sid = s->next_sid++;		ret = sidtab_insert(s, sid, context);		if (ret)			s->next_sid--;unlock_out:		SIDTAB_UNLOCK(s, flags);	}	if (ret)		return ret;	*out_sid = sid;	return 0;}void sidtab_hash_eval(struct sidtab *h, char *tag){	int i, chain_len, slots_used, max_chain_len;	struct sidtab_node *cur;	slots_used = 0;	max_chain_len = 0;	for (i = 0; i < SIDTAB_SIZE; i++) {		cur = h->htable[i];		if (cur) {			slots_used++;			chain_len = 0;			while (cur) {				chain_len++;				cur = cur->next;			}			if (chain_len > max_chain_len)				max_chain_len = chain_len;		}	}	printk(KERN_INFO "%s:  %d entries and %d/%d buckets used, longest "	       "chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE,	       max_chain_len);}void sidtab_destroy(struct sidtab *s){	int i;	struct sidtab_node *cur, *temp;	if (!s)		return;	for (i = 0; i < SIDTAB_SIZE; i++) {		cur = s->htable[i];		while (cur != NULL) {			temp = cur;			cur = cur->next;			context_destroy(&temp->context);			kfree(temp);		}		s->htable[i] = NULL;	}	kfree(s->htable);	s->htable = NULL;	s->nel = 0;	s->next_sid = 1;}void sidtab_set(struct sidtab *dst, struct sidtab *src){	unsigned long flags;	SIDTAB_LOCK(src, flags);	dst->htable = src->htable;	dst->nel = src->nel;	dst->next_sid = src->next_sid;	dst->shutdown = 0;	SIDTAB_UNLOCK(src, flags);}void sidtab_shutdown(struct sidtab *s){	unsigned long flags;	SIDTAB_LOCK(s, flags);	s->shutdown = 1;	SIDTAB_UNLOCK(s, flags);}

⌨️ 快捷键说明

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