static int mdd_xattr_sanity_check(const struct lu_env *env,
struct mdd_object *obj,
- const struct lu_attr *attr)
+ const struct lu_attr *attr,
+ const char *name)
{
struct lu_ucred *uc = lu_ucred_assert(env);
ENTRY;
if (attr->la_flags & (LUSTRE_IMMUTABLE_FL | LUSTRE_APPEND_FL))
RETURN(-EPERM);
- if ((uc->uc_fsuid != attr->la_uid) && !md_capable(uc, CFS_CAP_FOWNER))
- RETURN(-EPERM);
+ if (strncmp(XATTR_USER_PREFIX, name,
+ sizeof(XATTR_USER_PREFIX) - 1) == 0) {
+ /* For sticky directories, only the owner and privileged user
+ * can write attributes. */
+ if (S_ISDIR(attr->la_mode) && (attr->la_mode & S_ISVTX) &&
+ (uc->uc_fsuid != attr->la_uid) &&
+ !md_capable(uc, CFS_CAP_FOWNER))
+ RETURN(-EPERM);
+ } else {
+ if ((uc->uc_fsuid != attr->la_uid) &&
+ !md_capable(uc, CFS_CAP_FOWNER))
+ RETURN(-EPERM);
+ }
RETURN(0);
}
if (rc)
RETURN(rc);
- rc = mdd_xattr_sanity_check(env, mdd_obj, attr);
+ rc = mdd_xattr_sanity_check(env, mdd_obj, attr, name);
if (rc)
RETURN(rc);
if (rc)
RETURN(rc);
- rc = mdd_xattr_sanity_check(env, mdd_obj, attr);
+ rc = mdd_xattr_sanity_check(env, mdd_obj, attr, name);
if (rc)
RETURN(rc);