Whamcloud - gitweb
LU-1482 mdd: Setting xattr are properly checked with and without ACLs
[fs/lustre-release.git] / lustre / mdd / mdd_object.c
index 8743d96..7774803 100644 (file)
@@ -907,7 +907,8 @@ stop:
 
 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;
@@ -915,8 +916,19 @@ static int mdd_xattr_sanity_check(const struct lu_env *env,
        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);
 }
@@ -1038,7 +1050,7 @@ static int mdd_xattr_set(const struct lu_env *env, struct md_object *obj,
        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);
 
@@ -1151,7 +1163,7 @@ static int mdd_xattr_del(const struct lu_env *env, struct md_object *obj,
        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);