diff options
author | Eric W. Biederman <ebiederm@maxwell.aristanetworks.com> | 2009-11-08 02:26:59 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:24:53 -0500 |
commit | f44d3e7857e5d21413fc9a2b61948190c73705e7 (patch) | |
tree | d93591de4747cd59e4ee8ba8dfe97867cbdad6fd /fs/sysfs | |
parent | d3a3b0adad0865c12e39b712ca89efbd0a3a0dbc (diff) |
sysfs: Update sysfs_setxattr so it updates secdata under the sysfs_mutex
The sysfs_mutex is required to ensure updates are and will remain
atomic with respect to other inode iattr updates, that do not happen
through the filesystem.
Acked-by: Serge Hallyn <serue@us.ibm.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/inode.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e1443518398e..000bd9865004 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -123,23 +123,39 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | |||
123 | return error; | 123 | return error; |
124 | } | 124 | } |
125 | 125 | ||
126 | static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len) | ||
127 | { | ||
128 | struct sysfs_inode_attrs *iattrs; | ||
129 | void *old_secdata; | ||
130 | size_t old_secdata_len; | ||
131 | |||
132 | iattrs = sd->s_iattr; | ||
133 | if (!iattrs) | ||
134 | iattrs = sysfs_init_inode_attrs(sd); | ||
135 | if (!iattrs) | ||
136 | return -ENOMEM; | ||
137 | |||
138 | old_secdata = iattrs->ia_secdata; | ||
139 | old_secdata_len = iattrs->ia_secdata_len; | ||
140 | |||
141 | iattrs->ia_secdata = *secdata; | ||
142 | iattrs->ia_secdata_len = *secdata_len; | ||
143 | |||
144 | *secdata = old_secdata; | ||
145 | *secdata_len = old_secdata_len; | ||
146 | return 0; | ||
147 | } | ||
148 | |||
126 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 149 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
127 | size_t size, int flags) | 150 | size_t size, int flags) |
128 | { | 151 | { |
129 | struct sysfs_dirent *sd = dentry->d_fsdata; | 152 | struct sysfs_dirent *sd = dentry->d_fsdata; |
130 | struct sysfs_inode_attrs *iattrs; | ||
131 | void *secdata; | 153 | void *secdata; |
132 | int error; | 154 | int error; |
133 | u32 secdata_len = 0; | 155 | u32 secdata_len = 0; |
134 | 156 | ||
135 | if (!sd) | 157 | if (!sd) |
136 | return -EINVAL; | 158 | return -EINVAL; |
137 | if (!sd->s_iattr) | ||
138 | sd->s_iattr = sysfs_init_inode_attrs(sd); | ||
139 | if (!sd->s_iattr) | ||
140 | return -ENOMEM; | ||
141 | |||
142 | iattrs = sd->s_iattr; | ||
143 | 159 | ||
144 | if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { | 160 | if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { |
145 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; | 161 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; |
@@ -151,12 +167,13 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
151 | &secdata, &secdata_len); | 167 | &secdata, &secdata_len); |
152 | if (error) | 168 | if (error) |
153 | goto out; | 169 | goto out; |
154 | if (iattrs->ia_secdata) | ||
155 | security_release_secctx(iattrs->ia_secdata, | ||
156 | iattrs->ia_secdata_len); | ||
157 | iattrs->ia_secdata = secdata; | ||
158 | iattrs->ia_secdata_len = secdata_len; | ||
159 | 170 | ||
171 | mutex_lock(&sysfs_mutex); | ||
172 | error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len); | ||
173 | mutex_unlock(&sysfs_mutex); | ||
174 | |||
175 | if (secdata) | ||
176 | security_release_secctx(secdata, secdata_len); | ||
160 | } else | 177 | } else |
161 | return -EINVAL; | 178 | return -EINVAL; |
162 | out: | 179 | out: |