diff options
author | James Morris <jmorris@namei.org> | 2005-10-30 17:59:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 20:37:11 -0500 |
commit | d381d8a9a08cac9824096213069159be17fd2e2f (patch) | |
tree | 0c19722b8f67c29b7c08c6ab8776a9c146395d03 /fs | |
parent | 89d155ef62e5e0c10e4b37aaa5056f0beafe10e6 (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 'fs')
-rw-r--r-- | fs/xattr.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index 3f9c64bea151..f6e00c0e114f 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -143,7 +143,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) | |||
143 | if (size) { | 143 | if (size) { |
144 | if (size > XATTR_SIZE_MAX) | 144 | if (size > XATTR_SIZE_MAX) |
145 | size = XATTR_SIZE_MAX; | 145 | size = XATTR_SIZE_MAX; |
146 | kvalue = kmalloc(size, GFP_KERNEL); | 146 | kvalue = kzalloc(size, GFP_KERNEL); |
147 | if (!kvalue) | 147 | if (!kvalue) |
148 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | } | 149 | } |
@@ -154,11 +154,15 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) | |||
154 | error = -EOPNOTSUPP; | 154 | error = -EOPNOTSUPP; |
155 | if (d->d_inode->i_op && d->d_inode->i_op->getxattr) | 155 | if (d->d_inode->i_op && d->d_inode->i_op->getxattr) |
156 | error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); | 156 | error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); |
157 | else if (!strncmp(kname, XATTR_SECURITY_PREFIX, | 157 | |
158 | sizeof XATTR_SECURITY_PREFIX - 1)) { | 158 | if (!strncmp(kname, XATTR_SECURITY_PREFIX, |
159 | sizeof XATTR_SECURITY_PREFIX - 1)) { | ||
159 | const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; | 160 | const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; |
160 | error = security_inode_getsecurity(d->d_inode, suffix, kvalue, | 161 | int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue, |
161 | size); | 162 | size, error); |
163 | /* Security module active: overwrite error value */ | ||
164 | if (rv != -EOPNOTSUPP) | ||
165 | error = rv; | ||
162 | } | 166 | } |
163 | if (error > 0) { | 167 | if (error > 0) { |
164 | if (size && copy_to_user(value, kvalue, error)) | 168 | if (size && copy_to_user(value, kvalue, error)) |