"Serge E. Hallyn" <serue@xxxxxxxxxx> writes: > Quoting Eric W. Biederman (ebiederm@xxxxxxxxxxxx): >> From: Eric W. Biederman <ebiederm@xxxxxxxxxxxxxxxxxx> >> >> 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. >> >> Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxxxxxxxx> >> --- >> 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 e28cecf..8a08250 100644 >> --- a/fs/sysfs/inode.c >> +++ b/fs/sysfs/inode.c >> @@ -122,23 +122,39 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) >> return error; >> } >> >> +static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len) >> +{ >> + struct sysfs_inode_attrs *iattrs; >> + void *old_secdata; >> + size_t old_secdata_len; >> + >> + iattrs = sd->s_iattr; >> + if (!iattrs) >> + iattrs = sysfs_init_inode_attrs(sd); >> + if (!iattrs) >> + return -ENOMEM; >> + >> + old_secdata = iattrs->ia_secdata; >> + old_secdata_len = iattrs->ia_secdata_len; >> + >> + iattrs->ia_secdata = *secdata; >> + iattrs->ia_secdata_len = *secdata_len; >> + >> + *secdata = old_secdata; >> + *secdata_len = old_secdata_len; >> + return 0; >> +} >> + >> int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, >> size_t size, int flags) >> { >> struct sysfs_dirent *sd = dentry->d_fsdata; >> - struct sysfs_inode_attrs *iattrs; >> void *secdata; >> int error; >> u32 secdata_len = 0; >> >> if (!sd) >> return -EINVAL; >> - if (!sd->s_iattr) >> - sd->s_iattr = sysfs_init_inode_attrs(sd); >> - if (!sd->s_iattr) >> - return -ENOMEM; >> - >> - iattrs = sd->s_iattr; >> >> if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { >> const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; >> @@ -150,12 +166,13 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, >> &secdata, &secdata_len); >> if (error) >> goto out; >> - if (iattrs->ia_secdata) >> - security_release_secctx(iattrs->ia_secdata, >> - iattrs->ia_secdata_len); >> - iattrs->ia_secdata = secdata; >> - iattrs->ia_secdata_len = secdata_len; >> >> + mutex_lock(&sysfs_mutex); >> + error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len); > > You're ignoring the potential -ENOMEM return value here? > > Worse, if -ENOMEM, then secdata was never set, so you call > security_release_secctx() on a random value left on the stack... No. It is more elegant than that. If sysfs_sd_setsecdata fails secdata holds the freshly allocated secdata value. If sysfs_sd_setsecdata succeeds secdata holds the old value of secdata. Eric -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html