📄 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);#endifstatic 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, int 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 = -EFAULT; if ( copy_from_user(page, buf, size) ) goto out2; length = -EINVAL; if ( sscanf(page, "%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; memset(page, 0, PAGE_SIZE); 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 ( copy_to_user(buf, page, length) ) length = -EFAULT; out3: xfree(sids);out2: if ( page ) xfree(page); xfree(user);out: xfree(con); return length;}static int flask_security_relabel(char *buf, int 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 > PAGE_SIZE ) { length = -ERANGE; goto out3; } if ( copy_to_user(buf, newcon, len) ) len = -EFAULT; length = len; out3: xfree(newcon);out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_create(char *buf, int 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 > PAGE_SIZE ) { printk( "%s: context size (%u) exceeds payload " "max\n", __FUNCTION__, len); length = -ERANGE; goto out3; } if ( copy_to_user(buf, newcon, len) ) len = -EFAULT; length = len; out3: xfree(newcon);out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_access(char *buf, int size){ char *page = NULL; 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; page = (char *)xmalloc_bytes(PAGE_SIZE); if ( !page ) { length = -ENOMEM; goto out2; } memset(page, 0, PAGE_SIZE); length = snprintf(page, PAGE_SIZE, "%x %x %x %x %u", avd.allowed, avd.decided, avd.auditallow, avd.auditdeny, avd.seqno); if ( copy_to_user(buf, page, length) ) length = -EFAULT; out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_member(char *buf, int 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 > PAGE_SIZE ) { printk("%s: context size (%u) exceeds payload " "max\n", __FUNCTION__, len); length = -ERANGE; goto out3; } if ( copy_to_user(buf, newcon, len) ) len = -EFAULT; length = len;out3: xfree(newcon);out2: xfree(tcon);out: xfree(scon); return length;}static int flask_security_setenforce(char *buf, int count){ char *page = NULL; int length; int new_value; if ( count < 0 || count >= PAGE_SIZE ) return -ENOMEM; page = (char *)xmalloc_bytes(PAGE_SIZE); if ( !page ) return -ENOMEM; memset(page, 0, PAGE_SIZE); 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 != 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: xfree(page); return length;}static int flask_security_context(char *buf, int count){ char *page = NULL; u32 sid; int length; length = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT); if ( length ) goto out; if ( count < 0 || count >= PAGE_SIZE ) return -ENOMEM; page = (char *)xmalloc_bytes(PAGE_SIZE); if ( !page ) return -ENOMEM; memset(page, 0, PAGE_SIZE); length = -EFAULT; if ( copy_from_user(page, buf, count) ) goto out; length = security_context_to_sid(page, count, &sid); if ( length < 0 ) goto out; memset(page, 0, PAGE_SIZE); length = snprintf(page, PAGE_SIZE, "%u", sid); if ( copy_to_user(buf, page, count) ) length = -EFAULT;out: xfree(page); return length;}static int flask_security_sid(char *buf, int count){ char *page = NULL; char *context; u32 sid; u32 len; int length; length = domain_has_security(current->domain, SECURITY__CHECK_CONTEXT); if ( length ) goto out; if ( count < 0 || count >= PAGE_SIZE ) return -ENOMEM; page = (char *)xmalloc_bytes(PAGE_SIZE); if ( !page ) return -ENOMEM; memset(page, 0, PAGE_SIZE); length = -EFAULT; if ( copy_from_user(page, buf, count) ) goto out; if ( sscanf(page, "%u", &sid) != 1 ) goto out; length = security_sid_to_context(sid, &context, &len); if ( length < 0 ) goto out; if ( copy_to_user(buf, context, len) ) length = -EFAULT; xfree(context);out: xfree(page); return length;}int flask_disable(void){ static int flask_disabled = 0; if ( ss_initialized ) { /* Not permitted after initial policy load. */ return -EINVAL; } if ( flask_disabled ) { /* Only do this once. */ return -EINVAL; } printk("Flask: Disabled at runtime.\n"); flask_disabled = 1; /* Reset xsm_ops to the original module. */ xsm_ops = original_ops; return 0;}static int flask_security_disable(char *buf, int count){ char *page = NULL; int length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -