From 12b29f34558b9b45a2c6eabd4f3c6be939a3980f Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Wed, 7 May 2008 13:03:20 -0400 Subject: selinux: support deferred mapping of contexts Introduce SELinux support for deferred mapping of security contexts in the SID table upon policy reload, and use this support for inode security contexts when the context is not yet valid under the current policy. Only processes with CAP_MAC_ADMIN + mac_admin permission in policy can set undefined security contexts on inodes. Inodes with such undefined contexts are treated as having the unlabeled context until the context becomes valid upon a policy reload that defines the context. Context invalidation upon policy reload also uses this support to save the context information in the SID table and later recover it upon a subsequent policy reload that defines the context again. This support is to enable package managers and similar programs to set down file contexts unknown to the system policy at the time the file is created in order to better support placing loadable policy modules in packages and to support build systems that need to create images of different distro releases with different policies w/o requiring all of the contexts to be defined or legal in the build host policy. With this patch applied, the following sequence is possible, although in practice it is recommended that this permission only be allowed to specific program domains such as the package manager. # rmdir baz # rm bar # touch bar # chcon -t foo_exec_t bar # foo_exec_t is not yet defined chcon: failed to change context of `bar' to `system_u:object_r:foo_exec_t': Invalid argument # mkdir -Z system_u:object_r:foo_exec_t baz mkdir: failed to set default file creation context to `system_u:object_r:foo_exec_t': Invalid argument # cat setundefined.te policy_module(setundefined, 1.0) require { type unconfined_t; type unlabeled_t; } files_type(unlabeled_t) allow unconfined_t self:capability2 mac_admin; # make -f /usr/share/selinux/devel/Makefile setundefined.pp # semodule -i setundefined.pp # chcon -t foo_exec_t bar # foo_exec_t is not yet defined # mkdir -Z system_u:object_r:foo_exec_t baz # ls -Zd bar baz -rw-r--r-- root root system_u:object_r:unlabeled_t bar drwxr-xr-x root root system_u:object_r:unlabeled_t baz # cat foo.te policy_module(foo, 1.0) type foo_exec_t; files_type(foo_exec_t) # make -f /usr/share/selinux/devel/Makefile foo.pp # semodule -i foo.pp # defines foo_exec_t # ls -Zd bar baz -rw-r--r-- root root user_u:object_r:foo_exec_t bar drwxr-xr-x root root system_u:object_r:foo_exec_t baz # semodule -r foo # ls -Zd bar baz -rw-r--r-- root root system_u:object_r:unlabeled_t bar drwxr-xr-x root root system_u:object_r:unlabeled_t baz # semodule -i foo.pp # ls -Zd bar baz -rw-r--r-- root root user_u:object_r:foo_exec_t bar drwxr-xr-x root root system_u:object_r:foo_exec_t baz # semodule -r setundefined foo # chcon -t foo_exec_t bar # no longer defined and not allowed chcon: failed to change context of `bar' to `system_u:object_r:foo_exec_t': Invalid argument # rmdir baz # mkdir -Z system_u:object_r:foo_exec_t baz mkdir: failed to set default file creation context to `system_u:object_r:foo_exec_t': Invalid argument Signed-off-by: Stephen Smalley Signed-off-by: James Morris --- security/selinux/ss/mls.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'security/selinux/ss/mls.c') diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 8b1706b7b3c..a6ca0587e63 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -239,7 +239,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c) * Policy read-lock must be held for sidtab lookup. * */ -int mls_context_to_sid(char oldc, +int mls_context_to_sid(struct policydb *pol, + char oldc, char **scontext, struct context *context, struct sidtab *s, @@ -286,7 +287,7 @@ int mls_context_to_sid(char oldc, *p++ = 0; for (l = 0; l < 2; l++) { - levdatum = hashtab_search(policydb.p_levels.table, scontextp); + levdatum = hashtab_search(pol->p_levels.table, scontextp); if (!levdatum) { rc = -EINVAL; goto out; @@ -311,7 +312,7 @@ int mls_context_to_sid(char oldc, *rngptr++ = 0; } - catdatum = hashtab_search(policydb.p_cats.table, + catdatum = hashtab_search(pol->p_cats.table, scontextp); if (!catdatum) { rc = -EINVAL; @@ -327,7 +328,7 @@ int mls_context_to_sid(char oldc, if (rngptr) { int i; - rngdatum = hashtab_search(policydb.p_cats.table, rngptr); + rngdatum = hashtab_search(pol->p_cats.table, rngptr); if (!rngdatum) { rc = -EINVAL; goto out; @@ -395,7 +396,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) if (!tmpstr) { rc = -ENOMEM; } else { - rc = mls_context_to_sid(':', &tmpstr, context, + rc = mls_context_to_sid(&policydb, ':', &tmpstr, context, NULL, SECSID_NULL); kfree(freestr); } -- cgit v1.2.3-70-g09d2 From f5269710789f666a65cf1132c4f1d14fbc8d3c29 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 14 May 2008 11:27:45 -0400 Subject: SELinux: keep the code clean formating and syntax Formatting and syntax changes whitespace, tabs to spaces, trailing space put open { on same line as struct def remove unneeded {} after if statements change printk("Lu") to printk("llu") convert asm/uaccess.h to linux/uaacess.h includes remove unnecessary asm/bug.h includes convert all users of simple_strtol to strict_strtol Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 18 +++++++++++------- security/selinux/include/audit.h | 4 ++-- security/selinux/include/avc.h | 15 +++++++-------- security/selinux/netnode.c | 1 - security/selinux/netport.c | 3 +-- security/selinux/selinuxfs.c | 10 +++++++--- security/selinux/ss/avtab.c | 2 +- security/selinux/ss/mls.c | 8 ++++---- security/selinux/ss/services.c | 4 ++-- 9 files changed, 35 insertions(+), 30 deletions(-) (limited to 'security/selinux/ss/mls.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 59c6e98f7be..eca70f42e67 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -53,7 +53,7 @@ #include /* struct or_callable used in sock_rcv_skb */ #include #include -#include +#include #include #include #include @@ -104,7 +104,9 @@ int selinux_enforcing; static int __init enforcing_setup(char *str) { - selinux_enforcing = simple_strtol(str, NULL, 0); + unsigned long enforcing; + if (!strict_strtoul(str, 0, &enforcing)) + selinux_enforcing = enforcing ? 1 : 0; return 1; } __setup("enforcing=", enforcing_setup); @@ -115,7 +117,9 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE; static int __init selinux_enabled_setup(char *str) { - selinux_enabled = simple_strtol(str, NULL, 0); + unsigned long enabled; + if (!strict_strtoul(str, 0, &enabled)) + selinux_enabled = enabled ? 1 : 0; return 1; } __setup("selinux=", selinux_enabled_setup); @@ -594,7 +598,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, */ if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) && (num_opts == 0)) - goto out; + goto out; /* * parse the mount options, check if they are valid sids. @@ -2695,7 +2699,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, } static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, + const void *value, size_t size, int flags) { struct inode *inode = dentry->d_inode; @@ -5390,7 +5394,7 @@ static struct security_operations selinux_ops = { .inode_listsecurity = selinux_inode_listsecurity, .inode_need_killpriv = selinux_inode_need_killpriv, .inode_killpriv = selinux_inode_killpriv, - .inode_getsecid = selinux_inode_getsecid, + .inode_getsecid = selinux_inode_getsecid, .file_permission = selinux_file_permission, .file_alloc_security = selinux_file_alloc_security, @@ -5431,7 +5435,7 @@ static struct security_operations selinux_ops = { .task_to_inode = selinux_task_to_inode, .ipc_permission = selinux_ipc_permission, - .ipc_getsecid = selinux_ipc_getsecid, + .ipc_getsecid = selinux_ipc_getsecid, .msg_msg_alloc_security = selinux_msg_msg_alloc_security, .msg_msg_free_security = selinux_msg_msg_free_security, diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h index 6c8b9ef1557..1bdf973433c 100644 --- a/security/selinux/include/audit.h +++ b/security/selinux/include/audit.h @@ -1,7 +1,7 @@ /* * SELinux support for the Audit LSM hooks * - * Most of below header was moved from include/linux/selinux.h which + * Most of below header was moved from include/linux/selinux.h which * is released under below copyrights: * * Author: James Morris @@ -52,7 +52,7 @@ void selinux_audit_rule_free(void *rule); * -errno on failure. */ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule, - struct audit_context *actx); + struct audit_context *actx); /** * selinux_audit_rule_known - check to see if rule contains selinux fields. diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 8e23d7a873a..7b9769f5e77 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -75,13 +75,12 @@ struct avc_audit_data { /* Initialize an AVC audit data structure. */ #define AVC_AUDIT_DATA_INIT(_d,_t) \ - { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } + { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } /* * AVC statistics */ -struct avc_cache_stats -{ +struct avc_cache_stats { unsigned int lookups; unsigned int hits; unsigned int misses; @@ -97,8 +96,8 @@ struct avc_cache_stats void __init avc_init(void); void avc_audit(u32 ssid, u32 tsid, - u16 tclass, u32 requested, - struct av_decision *avd, int result, struct avc_audit_data *auditdata); + u16 tclass, u32 requested, + struct av_decision *avd, int result, struct avc_audit_data *auditdata); #define AVC_STRICT 1 /* Ignore permissive mode. */ int avc_has_perm_noaudit(u32 ssid, u32 tsid, @@ -107,8 +106,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, struct av_decision *avd); int avc_has_perm(u32 ssid, u32 tsid, - u16 tclass, u32 requested, - struct avc_audit_data *auditdata); + u16 tclass, u32 requested, + struct avc_audit_data *auditdata); u32 avc_policy_seqno(void); @@ -122,7 +121,7 @@ u32 avc_policy_seqno(void); #define AVC_CALLBACK_AUDITDENY_DISABLE 128 int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, - u16 tclass, u32 perms, + u16 tclass, u32 perms, u32 *out_retained), u32 events, u32 ssid, u32 tsid, u16 tclass, u32 perms); diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index b6ccd09379f..7100072bb1b 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -38,7 +38,6 @@ #include #include #include -#include #include "netnode.h" #include "objsec.h" diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 90b4cff7c35..fe7fba67f19 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "netport.h" #include "objsec.h" @@ -272,7 +271,7 @@ static __init int sel_netport_init(void) } ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET, - SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); + SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); if (ret != 0) panic("avc_add_callback() failed, error %d\n", ret); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index ac1ccc13a70..07a5db69571 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include /* selinuxfs pseudo filesystem for exporting the security policy API. Based on the proc code and the fs/nfsd/nfsctl.c code. */ @@ -57,14 +57,18 @@ int selinux_compat_net = SELINUX_COMPAT_NET_VALUE; static int __init checkreqprot_setup(char *str) { - selinux_checkreqprot = simple_strtoul(str, NULL, 0) ? 1 : 0; + unsigned long checkreqprot; + if (!strict_strtoul(str, 0, &checkreqprot)) + selinux_checkreqprot = checkreqprot ? 1 : 0; return 1; } __setup("checkreqprot=", checkreqprot_setup); static int __init selinux_compat_net_setup(char *str) { - selinux_compat_net = simple_strtoul(str, NULL, 0) ? 1 : 0; + unsigned long compat_net; + if (!strict_strtoul(str, 0, &compat_net)) + selinux_compat_net = compat_net ? 1 : 0; return 1; } __setup("selinux_compat_net=", selinux_compat_net_setup); diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 9e6626362bf..a1be97f8bee 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -311,7 +311,7 @@ void avtab_hash_eval(struct avtab *h, char *tag) } printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, " - "longest chain length %d sum of chain length^2 %Lu\n", + "longest chain length %d sum of chain length^2 %llu\n", tag, h->nel, slots_used, h->nslot, max_chain_len, chain2_len_sum); } diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index a6ca0587e63..77d745da48b 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -437,13 +437,13 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user, struct mls_level *usercon_clr = &(usercon->range.level[1]); /* Honor the user's default level if we can */ - if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) { + if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) *usercon_sen = *user_def; - } else if (mls_level_between(fromcon_sen, user_def, user_clr)) { + else if (mls_level_between(fromcon_sen, user_def, user_clr)) *usercon_sen = *fromcon_sen; - } else if (mls_level_between(fromcon_clr, user_low, user_def)) { + else if (mls_level_between(fromcon_clr, user_low, user_def)) *usercon_sen = *user_low; - } else + else return -EINVAL; /* Lower the clearance of available contexts diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 2d5e5a3a8aa..0696aadcab6 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2531,7 +2531,7 @@ int selinux_audit_rule_known(struct audit_krule *rule) } int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, - struct audit_context *actx) + struct audit_context *actx) { struct context *ctxt; struct mls_level *level; @@ -2645,7 +2645,7 @@ out: static int (*aurule_callback)(void) = audit_update_lsm_rules; static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, - u16 class, u32 perms, u32 *retained) + u16 class, u32 perms, u32 *retained) { int err = 0; -- cgit v1.2.3-70-g09d2