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

📄 avc.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
				struct dentry *dentry = a->u.fs.dentry;				if (a->u.fs.mnt) {					audit_log_d_path(ab, "path=", dentry,							a->u.fs.mnt);				} else {					audit_log_format(ab, " name=%s",							 dentry->d_name.name);				}				inode = dentry->d_inode;			} else if (a->u.fs.inode) {				struct dentry *dentry;				inode = a->u.fs.inode;				dentry = d_find_alias(inode);				if (dentry) {					audit_log_format(ab, " name=%s",							 dentry->d_name.name);					dput(dentry);				}			}			if (inode)				audit_log_format(ab, " dev=%s ino=%ld",						 inode->i_sb->s_id,						 inode->i_ino);			break;		case AVC_AUDIT_DATA_NET:			if (a->u.net.sk) {				struct sock *sk = a->u.net.sk;				struct unix_sock *u;				int len = 0;				char *p = NULL;				switch (sk->sk_family) {				case AF_INET: {					struct inet_opt *inet = inet_sk(sk);					avc_print_ipv4_addr(ab, inet->rcv_saddr,							    inet->sport,							    "laddr", "lport");					avc_print_ipv4_addr(ab, inet->daddr,							    inet->dport,							    "faddr", "fport");					break;				}				case AF_INET6: {					struct inet_opt *inet = inet_sk(sk);					struct ipv6_pinfo *inet6 = inet6_sk(sk);					avc_print_ipv6_addr(ab, &inet6->rcv_saddr,							    inet->sport,							    "laddr", "lport");					avc_print_ipv6_addr(ab, &inet6->daddr,							    inet->dport,							    "faddr", "fport");					break;				}				case AF_UNIX:					u = unix_sk(sk);					if (u->dentry) {						audit_log_d_path(ab, "path=",							u->dentry, u->mnt);						break;					}					if (!u->addr)						break;					len = u->addr->len-sizeof(short);					p = &u->addr->name->sun_path[0];					if (*p)						audit_log_format(ab,							"path=%*.*s", len,							len, p);					else						audit_log_format(ab,							"path=@%*.*s", len-1,							len-1, p+1);					break;				}			}						switch (a->u.net.family) {			case AF_INET:				avc_print_ipv4_addr(ab, a->u.net.v4info.saddr,						    a->u.net.sport,						    "saddr", "src");				avc_print_ipv4_addr(ab, a->u.net.v4info.daddr,						    a->u.net.dport,						    "daddr", "dest");				break;			case AF_INET6:				avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr,						    a->u.net.sport,						    "saddr", "src");				avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr,						    a->u.net.dport,						    "daddr", "dest");				break;			}			if (a->u.net.netif)				audit_log_format(ab, " netif=%s",					a->u.net.netif);			break;		}	}	audit_log_format(ab, " ");	avc_dump_query(ab, ssid, tsid, tclass);	audit_log_end(ab);}/** * avc_add_callback - Register a callback for security events. * @callback: callback function * @events: security events * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions * * Register a callback function for events in the set @events * related to the SID pair (@ssid, @tsid) and * and the permissions @perms, interpreting * @perms based on @tclass.  Returns %0 on success or * -%ENOMEM if insufficient memory exists to add the callback. */int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,                                     u16 tclass, u32 perms,                                     u32 *out_retained),                     u32 events, u32 ssid, u32 tsid,                     u16 tclass, u32 perms){	struct avc_callback_node *c;	int rc = 0;	c = kmalloc(sizeof(*c), GFP_ATOMIC);	if (!c) {		rc = -ENOMEM;		goto out;	}	c->callback = callback;	c->events = events;	c->ssid = ssid;	c->tsid = tsid;	c->perms = perms;	c->next = avc_callbacks;	avc_callbacks = c;out:	return rc;}static inline int avc_sidcmp(u32 x, u32 y){	return (x == y || x == SECSID_WILD || y == SECSID_WILD);}static inline void avc_update_node(u32 event, struct avc_node *node, u32 perms){	switch (event) {	case AVC_CALLBACK_GRANT:		node->ae.avd.allowed |= perms;		break;	case AVC_CALLBACK_TRY_REVOKE:	case AVC_CALLBACK_REVOKE:		node->ae.avd.allowed &= ~perms;		break;	case AVC_CALLBACK_AUDITALLOW_ENABLE:		node->ae.avd.auditallow |= perms;		break;	case AVC_CALLBACK_AUDITALLOW_DISABLE:		node->ae.avd.auditallow &= ~perms;		break;	case AVC_CALLBACK_AUDITDENY_ENABLE:		node->ae.avd.auditdeny |= perms;		break;	case AVC_CALLBACK_AUDITDENY_DISABLE:		node->ae.avd.auditdeny &= ~perms;		break;	}}static int avc_update_cache(u32 event, u32 ssid, u32 tsid,                            u16 tclass, u32 perms){	struct avc_node *node;	int i;	unsigned long flags;	spin_lock_irqsave(&avc_lock,flags);	if (ssid == SECSID_WILD || tsid == SECSID_WILD) {		/* apply to all matching nodes */		for (i = 0; i < AVC_CACHE_SLOTS; i++) {			for (node = avc_cache.slots[i]; node;			     node = node->next) {				if (avc_sidcmp(ssid, node->ae.ssid) &&				    avc_sidcmp(tsid, node->ae.tsid) &&				    tclass == node->ae.tclass) {					avc_update_node(event,node,perms);				}			}		}	} else {		/* apply to one node */		node = avc_search_node(ssid, tsid, tclass, NULL);		if (node) {			avc_update_node(event,node,perms);		}	}	spin_unlock_irqrestore(&avc_lock,flags);	return 0;}static int avc_control(u32 event, u32 ssid, u32 tsid,                       u16 tclass, u32 perms,                       u32 seqno, u32 *out_retained){	struct avc_callback_node *c;	u32 tretained = 0, cretained = 0;	int rc = 0;	unsigned long flags;	/*	 * try_revoke only removes permissions from the cache	 * state if they are not retained by the object manager.	 * Hence, try_revoke must wait until after the callbacks have	 * been invoked to update the cache state.	 */	if (event != AVC_CALLBACK_TRY_REVOKE)		avc_update_cache(event,ssid,tsid,tclass,perms);	for (c = avc_callbacks; c; c = c->next)	{		if ((c->events & event) &&		    avc_sidcmp(c->ssid, ssid) &&		    avc_sidcmp(c->tsid, tsid) &&		    c->tclass == tclass &&		    (c->perms & perms)) {			cretained = 0;			rc = c->callback(event, ssid, tsid, tclass,					 (c->perms & perms),					 &cretained);			if (rc)				goto out;			tretained |= cretained;		}	}	if (event == AVC_CALLBACK_TRY_REVOKE) {		/* revoke any unretained permissions */		perms &= ~tretained;		avc_update_cache(event,ssid,tsid,tclass,perms);		*out_retained = tretained;	}	spin_lock_irqsave(&avc_lock,flags);	if (seqno > avc_cache.latest_notif)		avc_cache.latest_notif = seqno;	spin_unlock_irqrestore(&avc_lock,flags);out:	return rc;}/** * avc_ss_grant - Grant previously denied permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number */int avc_ss_grant(u32 ssid, u32 tsid, u16 tclass,                 u32 perms, u32 seqno){	return avc_control(AVC_CALLBACK_GRANT,			   ssid, tsid, tclass, perms, seqno, NULL);}/** * avc_ss_try_revoke - Try to revoke previously granted permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * @out_retained: subset of @perms that are retained * * Try to revoke previously granted permissions, but * only if they are not retained as migrated permissions. * Return the subset of permissions that are retained via @out_retained. */int avc_ss_try_revoke(u32 ssid, u32 tsid, u16 tclass,                      u32 perms, u32 seqno, u32 *out_retained){	return avc_control(AVC_CALLBACK_TRY_REVOKE,			   ssid, tsid, tclass, perms, seqno, out_retained);}/** * avc_ss_revoke - Revoke previously granted permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * * Revoke previously granted permissions, even if * they are retained as migrated permissions. */int avc_ss_revoke(u32 ssid, u32 tsid, u16 tclass,                  u32 perms, u32 seqno){	return avc_control(AVC_CALLBACK_REVOKE,			   ssid, tsid, tclass, perms, seqno, NULL);}/** * avc_ss_reset - Flush the cache and revalidate migrated permissions. * @seqno: policy sequence number */int avc_ss_reset(u32 seqno){	struct avc_callback_node *c;	int i, rc = 0;	struct avc_node *node, *tmp;	unsigned long flags;	avc_hash_eval("reset");	spin_lock_irqsave(&avc_lock,flags);	for (i = 0; i < AVC_CACHE_SLOTS; i++) {		node = avc_cache.slots[i];		while (node) {			tmp = node;			node = node->next;			tmp->ae.ssid = tmp->ae.tsid = SECSID_NULL;			tmp->ae.tclass = SECCLASS_NULL;			tmp->ae.avd.allowed = tmp->ae.avd.decided = 0;			tmp->ae.avd.auditallow = tmp->ae.avd.auditdeny = 0;			tmp->ae.used = 0;			tmp->next = avc_node_freelist;			avc_node_freelist = tmp;			avc_cache.active_nodes--;		}		avc_cache.slots[i] = NULL;	}	avc_cache.lru_hint = 0;	spin_unlock_irqrestore(&avc_lock,flags);	for (i = 0; i < AVC_NSTATS; i++)		avc_cache_stats[i] = 0;	for (c = avc_callbacks; c; c = c->next) {		if (c->events & AVC_CALLBACK_RESET) {			rc = c->callback(AVC_CALLBACK_RESET,					 0, 0, 0, 0, NULL);			if (rc)				goto out;		}	}	spin_lock_irqsave(&avc_lock,flags);	if (seqno > avc_cache.latest_notif)		avc_cache.latest_notif = seqno;	spin_unlock_irqrestore(&avc_lock,flags);out:	return rc;}/** * avc_ss_set_auditallow - Enable or disable auditing of granted permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * @enable: enable flag. */int avc_ss_set_auditallow(u32 ssid, u32 tsid, u16 tclass,                          u32 perms, u32 seqno, u32 enable){	if (enable)		return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,				   ssid, tsid, tclass, perms, seqno, NULL);	else		return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,				   ssid, tsid, tclass, perms, seqno, NULL);}/** * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions. * @ssid: source security identifier or %SECSID_WILD * @tsid: target security identifier or %SECSID_WILD * @tclass: target security class * @perms: permissions to grant * @seqno: policy sequence number * @enable: enable flag. */int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass,                         u32 perms, u32 seqno, u32 enable){	if (enable)		return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,				   ssid, tsid, tclass, perms, seqno, NULL);	else		return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,				   ssid, tsid, tclass, perms, seqno, NULL);}/** * avc_has_perm_noaudit - Check permissions but perform no auditing. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @requested: requested permissions, interpreted based on @tclass * @aeref:  AVC entry reference * @avd: access vector decisions * * Check the AVC to determine whether the @requested permissions are granted * for the SID pair (@ssid, @tsid), interpreting the permissions * based on @tclass, and call the security server on a cache miss to obtain * a new decision and add it to the cache.  Update @aeref to refer to an AVC * entry with the resulting decisions, and return a copy of the decisions * in @avd.  Return %0 if all @requested permissions are granted, * -%EACCES if any permissions are denied, or another -errno upon * other errors.  This function is typically called by avc_has_perm(), * but may also be called directly to separate permission checking from * auditing, e.g. in cases where a lock must be held for the check but * should be released for the auditing. */int avc_has_perm_noaudit(u32 ssid, u32 tsid,                         u16 tclass, u32 requested,                         struct avc_entry_ref *aeref, struct av_decision *avd){	struct avc_entry *ae;	int rc = 0;	unsigned long flags;	struct avc_entry entry;	u32 denied;	struct avc_entry_ref ref;	if (!aeref) {		avc_entry_ref_init(&ref);		aeref = &ref;	}	spin_lock_irqsave(&avc_lock, flags);	avc_cache_stats_incr(AVC_ENTRY_LOOKUPS);	ae = aeref->ae;	if (ae) {		if (ae->ssid == ssid &&		    ae->tsid == tsid &&		    ae->tclass == tclass &&		    ((ae->avd.decided & requested) == requested)) {			avc_cache_stats_incr(AVC_ENTRY_HITS);			ae->used = 1;		} else {			avc_cache_stats_incr(AVC_ENTRY_DISCARDS);			ae = NULL;		}	}	if (!ae) {		avc_cache_stats_incr(AVC_ENTRY_MISSES);		rc = avc_lookup(ssid, tsid, tclass, requested, aeref);		if (rc) {			spin_unlock_irqrestore(&avc_lock,flags);			rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd);			if (rc)				goto out;			spin_lock_irqsave(&avc_lock, flags);			rc = avc_insert(ssid,tsid,tclass,&entry,aeref);			if (rc) {				spin_unlock_irqrestore(&avc_lock,flags);				goto out;			}		}		ae = aeref->ae;	}	if (avd)		memcpy(avd, &ae->avd, sizeof(*avd));	denied = requested & ~(ae->avd.allowed);	if (!requested || denied) {		if (selinux_enforcing) {			spin_unlock_irqrestore(&avc_lock,flags);			rc = -EACCES;			goto out;		} else {			ae->avd.allowed |= requested;			spin_unlock_irqrestore(&avc_lock,flags);			goto out;		}	}	spin_unlock_irqrestore(&avc_lock,flags);out:	return rc;}/** * avc_has_perm - Check permissions and perform any appropriate auditing. * @ssid: source security identifier * @tsid: target security identifier * @tclass: target security class * @requested: requested permissions, interpreted based on @tclass * @aeref:  AVC entry reference * @auditdata: auxiliary audit data * * Check the AVC to determine whether the @requested permissions are granted * for the SID pair (@ssid, @tsid), interpreting the permissions * based on @tclass, and call the security server on a cache miss to obtain * a new decision and add it to the cache.  Update @aeref to refer to an AVC * entry with the resulting decisions.  Audit the granting or denial of * permissions in accordance with the policy.  Return %0 if all @requested * permissions are granted, -%EACCES if any permissions are denied, or * another -errno upon other errors. */int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,                 u32 requested, struct avc_entry_ref *aeref,                 struct avc_audit_data *auditdata){	struct av_decision avd;	int rc;	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd);	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);	return rc;}

⌨️ 快捷键说明

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