aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@maxwell.aristanetworks.com>2009-11-08 02:26:59 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:24:53 -0500
commitf44d3e7857e5d21413fc9a2b61948190c73705e7 (patch)
treed93591de4747cd59e4ee8ba8dfe97867cbdad6fd /fs/sysfs
parentd3a3b0adad0865c12e39b712ca89efbd0a3a0dbc (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.c41
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
126static 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
126int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, 149int 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;
162out: 179out: