int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr) { struct sysfs_inode_attrs *sd_attrs; struct iattr *iattrs; unsigned int ia_valid = iattr->ia_valid; sd_attrs = sd->s_iattr; if (!sd_attrs) { /* setting attributes for the first time, allocate now */ sd_attrs = sysfs_init_inode_attrs(sd); if (!sd_attrs) return -ENOMEM; sd->s_iattr = sd_attrs; } /* attributes were changed at least once in past */ iattrs = &sd_attrs->ia_iattr; if (ia_valid & ATTR_UID) iattrs->ia_uid = iattr->ia_uid; if (ia_valid & ATTR_GID) iattrs->ia_gid = iattr->ia_gid; if (ia_valid & ATTR_ATIME) iattrs->ia_atime = iattr->ia_atime; if (ia_valid & ATTR_MTIME) iattrs->ia_mtime = iattr->ia_mtime; if (ia_valid & ATTR_CTIME) iattrs->ia_ctime = iattr->ia_ctime; if (ia_valid & ATTR_MODE) { umode_t mode = iattr->ia_mode; iattrs->ia_mode = sd->s_mode = mode; } return 0; }
int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) { struct inode * inode = dentry->d_inode; struct sysfs_dirent * sd = dentry->d_fsdata; struct sysfs_inode_attrs *sd_attrs; struct iattr *iattrs; unsigned int ia_valid = iattr->ia_valid; int error; if (!sd) return -EINVAL; sd_attrs = sd->s_iattr; error = inode_change_ok(inode, iattr); if (error) return error; iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ error = inode_setattr(inode, iattr); if (error) return error; if (!sd_attrs) { /* setting attributes for the first time, allocate now */ sd_attrs = sysfs_init_inode_attrs(sd); if (!sd_attrs) return -ENOMEM; sd->s_iattr = sd_attrs; } /* attributes were changed at least once in past */ iattrs = &sd_attrs->ia_iattr; if (ia_valid & ATTR_UID) iattrs->ia_uid = iattr->ia_uid; if (ia_valid & ATTR_GID) iattrs->ia_gid = iattr->ia_gid; if (ia_valid & ATTR_ATIME) iattrs->ia_atime = timespec_trunc(iattr->ia_atime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MTIME) iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_CTIME) iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MODE) { umode_t mode = iattr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) mode &= ~S_ISGID; iattrs->ia_mode = sd->s_mode = mode; } return error; }
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; error = security_inode_setsecurity(dentry->d_inode, suffix, value, size, flags); if (error) goto out; error = security_inode_getsecctx(dentry->d_inode, &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; } else return -EINVAL; out: 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; }