aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2005-10-30 17:59:22 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-30 20:37:11 -0500
commitd381d8a9a08cac9824096213069159be17fd2e2f (patch)
tree0c19722b8f67c29b7c08c6ab8776a9c146395d03 /security/selinux/hooks.c
parent89d155ef62e5e0c10e4b37aaa5056f0beafe10e6 (diff)
[PATCH] SELinux: canonicalize getxattr()
This patch allows SELinux to canonicalize the value returned from getxattr() via the security_inode_getsecurity() hook, which is called after the fs level getxattr() function. The purpose of this is to allow the in-core security context for an inode to override the on-disk value. This could happen in cases such as upgrading a system to a different labeling form (e.g. standard SELinux to MLS) without needing to do a full relabel of the filesystem. In such cases, we want getxattr() to return the canonical security context that the kernel is using rather than what is stored on disk. The implementation hooks into the inode_getsecurity(), adding another parameter to indicate the result of the preceding fs-level getxattr() call, so that SELinux knows whether to compare a value obtained from disk with the kernel value. We also now allow getxattr() to work for mountpoint labeled filesystems (i.e. mount with option context=foo_t), as we are able to return the kernel value to the user. Signed-off-by: James Morris <jmorris@namei.org> Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8cd33b2cd865..d9ec85292e1c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2208,9 +2208,6 @@ static int selinux_inode_getxattr (struct dentry *dentry, char *name)
2208 struct inode *inode = dentry->d_inode; 2208 struct inode *inode = dentry->d_inode;
2209 struct superblock_security_struct *sbsec = inode->i_sb->s_security; 2209 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
2210 2210
2211 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2212 return -EOPNOTSUPP;
2213
2214 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); 2211 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2215} 2212}
2216 2213
@@ -2241,33 +2238,54 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2241 return -EACCES; 2238 return -EACCES;
2242} 2239}
2243 2240
2244static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) 2241/*
2242 * Copy the in-core inode security context value to the user. If the
2243 * getxattr() prior to this succeeded, check to see if we need to
2244 * canonicalize the value to be finally returned to the user.
2245 *
2246 * Permission check is handled by selinux_inode_getxattr hook.
2247 */
2248static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
2245{ 2249{
2246 struct inode_security_struct *isec = inode->i_security; 2250 struct inode_security_struct *isec = inode->i_security;
2247 char *context; 2251 char *context;
2248 unsigned len; 2252 unsigned len;
2249 int rc; 2253 int rc;
2250 2254
2251 /* Permission check handled by selinux_inode_getxattr hook.*/ 2255 if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
2252 2256 rc = -EOPNOTSUPP;
2253 if (strcmp(name, XATTR_SELINUX_SUFFIX)) 2257 goto out;
2254 return -EOPNOTSUPP; 2258 }
2255 2259
2256 rc = security_sid_to_context(isec->sid, &context, &len); 2260 rc = security_sid_to_context(isec->sid, &context, &len);
2257 if (rc) 2261 if (rc)
2258 return rc; 2262 goto out;
2259 2263
2264 /* Probe for required buffer size */
2260 if (!buffer || !size) { 2265 if (!buffer || !size) {
2261 kfree(context); 2266 rc = len;
2262 return len; 2267 goto out_free;
2263 } 2268 }
2269
2264 if (size < len) { 2270 if (size < len) {
2265 kfree(context); 2271 rc = -ERANGE;
2266 return -ERANGE; 2272 goto out_free;
2273 }
2274
2275 if (err > 0) {
2276 if ((len == err) && !(memcmp(context, buffer, len))) {
2277 /* Don't need to canonicalize value */
2278 rc = err;
2279 goto out_free;
2280 }
2281 memset(buffer, 0, size);
2267 } 2282 }
2268 memcpy(buffer, context, len); 2283 memcpy(buffer, context, len);
2284 rc = len;
2285out_free:
2269 kfree(context); 2286 kfree(context);
2270 return len; 2287out:
2288 return rc;
2271} 2289}
2272 2290
2273static int selinux_inode_setsecurity(struct inode *inode, const char *name, 2291static int selinux_inode_setsecurity(struct inode *inode, const char *name,