aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2008-05-07 13:03:20 -0400
committerJames Morris <jmorris@namei.org>2008-07-14 01:01:34 -0400
commit12b29f34558b9b45a2c6eabd4f3c6be939a3980f (patch)
tree9b7921724226cd81901070026572bf05014dc41c /security
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
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 <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/hooks.c20
-rw-r--r--security/selinux/include/security.h5
-rw-r--r--security/selinux/ss/context.h27
-rw-r--r--security/selinux/ss/mls.c11
-rw-r--r--security/selinux/ss/mls.h3
-rw-r--r--security/selinux/ss/services.c245
-rw-r--r--security/selinux/ss/sidtab.c58
-rw-r--r--security/selinux/ss/sidtab.h7
8 files changed, 248 insertions, 128 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1c864c0efe2b..59c6e98f7bea 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2495,7 +2495,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2495 } 2495 }
2496 2496
2497 if (value && len) { 2497 if (value && len) {
2498 rc = security_sid_to_context(newsid, &context, &clen); 2498 rc = security_sid_to_context_force(newsid, &context, &clen);
2499 if (rc) { 2499 if (rc) {
2500 kfree(namep); 2500 kfree(namep);
2501 return rc; 2501 return rc;
@@ -2669,6 +2669,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2669 return rc; 2669 return rc;
2670 2670
2671 rc = security_context_to_sid(value, size, &newsid); 2671 rc = security_context_to_sid(value, size, &newsid);
2672 if (rc == -EINVAL) {
2673 if (!capable(CAP_MAC_ADMIN))
2674 return rc;
2675 rc = security_context_to_sid_force(value, size, &newsid);
2676 }
2672 if (rc) 2677 if (rc)
2673 return rc; 2678 return rc;
2674 2679
@@ -2703,10 +2708,11 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
2703 return; 2708 return;
2704 } 2709 }
2705 2710
2706 rc = security_context_to_sid(value, size, &newsid); 2711 rc = security_context_to_sid_force(value, size, &newsid);
2707 if (rc) { 2712 if (rc) {
2708 printk(KERN_WARNING "%s: unable to obtain SID for context " 2713 printk(KERN_ERR "SELinux: unable to map context to SID"
2709 "%s, rc=%d\n", __func__, (char *)value, -rc); 2714 "for (%s, %lu), rc=%d\n",
2715 inode->i_sb->s_id, inode->i_ino, -rc);
2710 return; 2716 return;
2711 } 2717 }
2712 2718
@@ -5153,6 +5159,12 @@ static int selinux_setprocattr(struct task_struct *p,
5153 size--; 5159 size--;
5154 } 5160 }
5155 error = security_context_to_sid(value, size, &sid); 5161 error = security_context_to_sid(value, size, &sid);
5162 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5163 if (!capable(CAP_MAC_ADMIN))
5164 return error;
5165 error = security_context_to_sid_force(value, size,
5166 &sid);
5167 }
5156 if (error) 5168 if (error)
5157 return error; 5169 return error;
5158 } 5170 }
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index ad30ac4273d6..7c543003d653 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -93,12 +93,17 @@ int security_change_sid(u32 ssid, u32 tsid,
93int security_sid_to_context(u32 sid, char **scontext, 93int security_sid_to_context(u32 sid, char **scontext,
94 u32 *scontext_len); 94 u32 *scontext_len);
95 95
96int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
97
96int security_context_to_sid(const char *scontext, u32 scontext_len, 98int security_context_to_sid(const char *scontext, u32 scontext_len,
97 u32 *out_sid); 99 u32 *out_sid);
98 100
99int security_context_to_sid_default(const char *scontext, u32 scontext_len, 101int security_context_to_sid_default(const char *scontext, u32 scontext_len,
100 u32 *out_sid, u32 def_sid, gfp_t gfp_flags); 102 u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
101 103
104int security_context_to_sid_force(const char *scontext, u32 scontext_len,
105 u32 *sid);
106
102int security_get_user_sids(u32 callsid, char *username, 107int security_get_user_sids(u32 callsid, char *username,
103 u32 **sids, u32 *nel); 108 u32 **sids, u32 *nel);
104 109
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index b9a6f7fc62fc..658c2bd17da8 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -28,6 +28,8 @@ struct context {
28 u32 role; 28 u32 role;
29 u32 type; 29 u32 type;
30 struct mls_range range; 30 struct mls_range range;
31 char *str; /* string representation if context cannot be mapped. */
32 u32 len; /* length of string in bytes */
31}; 33};
32 34
33static inline void mls_context_init(struct context *c) 35static inline void mls_context_init(struct context *c)
@@ -106,20 +108,43 @@ static inline void context_init(struct context *c)
106 108
107static inline int context_cpy(struct context *dst, struct context *src) 109static inline int context_cpy(struct context *dst, struct context *src)
108{ 110{
111 int rc;
112
109 dst->user = src->user; 113 dst->user = src->user;
110 dst->role = src->role; 114 dst->role = src->role;
111 dst->type = src->type; 115 dst->type = src->type;
112 return mls_context_cpy(dst, src); 116 if (src->str) {
117 dst->str = kstrdup(src->str, GFP_ATOMIC);
118 if (!dst->str)
119 return -ENOMEM;
120 dst->len = src->len;
121 } else {
122 dst->str = NULL;
123 dst->len = 0;
124 }
125 rc = mls_context_cpy(dst, src);
126 if (rc) {
127 kfree(dst->str);
128 return rc;
129 }
130 return 0;
113} 131}
114 132
115static inline void context_destroy(struct context *c) 133static inline void context_destroy(struct context *c)
116{ 134{
117 c->user = c->role = c->type = 0; 135 c->user = c->role = c->type = 0;
136 kfree(c->str);
137 c->str = NULL;
138 c->len = 0;
118 mls_context_destroy(c); 139 mls_context_destroy(c);
119} 140}
120 141
121static inline int context_cmp(struct context *c1, struct context *c2) 142static inline int context_cmp(struct context *c1, struct context *c2)
122{ 143{
144 if (c1->len && c2->len)
145 return (c1->len == c2->len && !strcmp(c1->str, c2->str));
146 if (c1->len || c2->len)
147 return 0;
123 return ((c1->user == c2->user) && 148 return ((c1->user == c2->user) &&
124 (c1->role == c2->role) && 149 (c1->role == c2->role) &&
125 (c1->type == c2->type) && 150 (c1->type == c2->type) &&
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 8b1706b7b3cc..a6ca0587e634 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)
239 * Policy read-lock must be held for sidtab lookup. 239 * Policy read-lock must be held for sidtab lookup.
240 * 240 *
241 */ 241 */
242int mls_context_to_sid(char oldc, 242int mls_context_to_sid(struct policydb *pol,
243 char oldc,
243 char **scontext, 244 char **scontext,
244 struct context *context, 245 struct context *context,
245 struct sidtab *s, 246 struct sidtab *s,
@@ -286,7 +287,7 @@ int mls_context_to_sid(char oldc,
286 *p++ = 0;