📄 flask_op.c
字号:
/* * This file contains the flask_op hypercall and associated functions. * * Author: George Coker, <gscoker@alpha.ncsc.mil> * * 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 <xen/errno.h>#include <xsm/xsm.h>#include <xen/guest_access.h>#include <public/xsm/flask_op.h>#include <avc.h>#include <avc_ss.h>#include <objsec.h>#include <conditional.h>#ifdef FLASK_DEVELOPint flask_enforcing = 0;integer_param("flask_enforcing", flask_enforcing);#endif#ifdef FLASK_BOOTPARAMint flask_enabled = 1;integer_param("flask_enabled", flask_enabled);#endif#define MAX_POLICY_SIZE 0x4000000#define FLASK_COPY_IN \ ( \ 1UL<<FLASK_LOAD | \ 1UL<<FLASK_SETENFORCE | \ 1UL<<FLASK_CONTEXT_TO_SID | \ 1UL<<FLASK_SID_TO_CONTEXT | \ 1UL<<FLASK_ACCESS | \ 1UL<<FLASK_CREATE | \ 1UL<<FLASK_RELABEL | \ 1UL<<FLASK_USER | \ 1UL<<FLASK_GETBOOL | \ 1UL<<FLASK_SETBOOL | \ 1UL<<FLASK_COMMITBOOLS | \ 1UL<<FLASK_DISABLE | \ 1UL<<FLASK_SETAVC_THRESHOLD | \ 1UL<<FLASK_MEMBER \ )#define FLASK_COPY_OUT \ ( \ 1UL<<FLASK_GETENFORCE | \ 1UL<<FLASK_CONTEXT_TO_SID | \ 1UL<<FLASK_SID_TO_CONTEXT | \ 1UL<<FLASK_ACCESS | \ 1UL<<FLASK_CREATE | \ 1UL<<FLASK_RELABEL | \ 1UL<<FLASK_USER | \ 1UL<<FLASK_POLICYVERS | \ 1UL<<FLASK_GETBOOL | \ 1UL<<FLASK_MLS | \ 1UL<<FLASK_GETAVC_THRESHOLD | \ 1UL<<FLASK_AVC_HASHSTATS | \ 1UL<<FLASK_AVC_CACHESTATS | \ 1UL<<FLASK_MEMBER \ )static DEFINE_SPINLOCK(sel_sem);/* global data for booleans */static int bool_num = 0;static int *bool_pending_values = NULL;extern int ss_initialized;extern struct xsm_operations *original_ops;static int domain_has_security(struct domain *d, u32 perms){ struct domain_security_struct *dsec; dsec = d->ssid; if ( !dsec ) return -EACCES; return avc_has_perm(dsec->sid, SECINITSID_SECURITY, SECCLASS_SECURITY, perms, NULL);}static int flask_security_user(char *buf, uint32_t size){ char *page = NULL; char *con, *user, *ptr; u32 sid, *sids; int length; char *newcon; int i, rc; u32 len, nsids; length = domain_has_security(current->domain, SECURITY__COMPUTE_USER); if ( length ) return length; length = -ENOMEM; con = xmalloc_array(char, size+1); if ( !con ) return length; memset(con, 0, size+1); user = xmalloc_array(char, size+1); if ( !user ) goto out; memset(user, 0, size+1); length = -ENOMEM; page = xmalloc_bytes(PAGE_SIZE); if ( !page ) goto out2; memset(page, 0, PAGE_SIZE); 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 = snprintf(page, PAGE_SIZE, "%u", nsids) + 1; ptr = page + 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) >= PAGE_SIZE ) { xfree(newcon); length = -ERANGE; goto out3; } memcpy(ptr, newcon, len); xfree(newcon); ptr += len; length += len; } if ( length > size ) { printk( "%s: context size (%u) exceeds payload " "max\n", __FUNCTION__, length); length = -ERANGE; goto out3; } memset(buf, 0, size); memcpy(buf, page, length); out3: xfree(sids);out2: if ( page ) xfree(page); xfree(user);out: xfree(con); return length;}static int flask_security_relabel(char *buf, uint32_t size){ char *scon, *tcon; u32 ssid, tsid, newsid; u16 tclass; int length; char *newcon; u32 len; length = domain_has_security(current->domain, SECURITY__COMPUTE_RELABEL); if ( length ) return length; length = -ENOMEM; scon = xmalloc_array(char, size+1); if ( !scon ) return length; memset(scon, 0, size+1); tcon = xmalloc_array(char, size+1); if ( !tcon ) goto out; memset(tcon, 0, size+1); 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 > size ) { printk( "%s: context size (%u) exceeds payload " "max\n", __FUNCTION__, len); length = -ERANGE; goto out3; } memset(buf, 0, size); memcpy(buf, newcon, len); length = len;out3: xfree(newcon);out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_create(char *buf, uint32_t size){ char *scon, *tcon; u32 ssid, tsid, newsid; u16 tclass; int length; char *newcon; u32 len; length = domain_has_security(current->domain, SECURITY__COMPUTE_CREATE); if ( length ) return length; length = -ENOMEM; scon = xmalloc_array(char, size+1); if ( !scon ) return length; memset(scon, 0, size+1); tcon = xmalloc_array(char, size+1); if ( !tcon ) goto out; memset(tcon, 0, size+1); 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 > size ) { printk( "%s: context size (%u) exceeds payload " "max\n", __FUNCTION__, len); length = -ERANGE; goto out3; } memset(buf, 0, size); memcpy(buf, newcon, len); length = len; out3: xfree(newcon);out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_access(char *buf, uint32_t size){ char *scon, *tcon; u32 ssid, tsid; u16 tclass; u32 req; struct av_decision avd; int length; length = domain_has_security(current->domain, SECURITY__COMPUTE_AV); if ( length ) return length; length = -ENOMEM; scon = xmalloc_array(char, size+1); if (!scon) return length; memset(scon, 0, size+1); tcon = xmalloc_array(char, size+1); if ( !tcon ) goto out; memset( tcon, 0, size+1 ); length = -EINVAL; if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4) 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_compute_av(ssid, tsid, tclass, req, &avd); if ( length < 0 ) goto out2; memset(buf, 0, size); length = snprintf(buf, size, "%x %x %x %x %u", avd.allowed, avd.decided, avd.auditallow, avd.auditdeny, avd.seqno); out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_member(char *buf, uint32_t size){ char *scon, *tcon; u32 ssid, tsid, newsid; u16 tclass; int length; char *newcon; u32 len; length = domain_has_security(current->domain, SECURITY__COMPUTE_MEMBER); if ( length ) return length; length = -ENOMEM; scon = xmalloc_array(char, size+1); if ( !scon ) return length; memset(scon, 0, size+1); tcon = xmalloc_array(char, size+1); if ( !tcon ) goto out; memset(tcon, 0, size+1); 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 > size ) { printk("%s: context size (%u) exceeds payload " "max\n", __FUNCTION__, len); length = -ERANGE; goto out3; } memset(buf, 0, size); memcpy(buf, newcon, len); length = len;out3: xfree(newcon);out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_setenforce(char *buf, uint32_t count){ int length; int new_value; if ( sscanf(buf, "%d", &new_value) != 1 ) return -EINVAL; if ( new_value != flask_enforcing ) { length = domain_has_security(current->domain, SECURITY__SETENFORCE); if ( length ) goto out; flask_enforcing = new_value; if ( flask_enforcing ) avc_ss_reset(0); } length = count;out: return length;}static int flask_security_context(char *buf, uint32_t count){ u32 sid; int length; length = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT); if ( length ) goto out; length = security_context_to_sid(buf, count, &sid); if ( length < 0 ) goto out; memset(buf, 0, count); length = snprintf(buf, count, "%u", sid);out: return length;}static int flask_security_sid(char *buf, uint32_t count){ char *context;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -