(ATTR_CTIME|ATTR_SIZE|ATTR_MODE))
attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
+ if ((de->d_inode->i_mode & S_ISUID) &&
+ !(attr->ia_mode & S_ISUID) &&
+ !(attr->ia_valid & ATTR_KILL_SUID))
+ attr->ia_valid |= ATTR_KILL_SUID;
+
+ if (((de->d_inode->i_mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) &&
+ !(attr->ia_mode & S_ISGID) &&
+ !(attr->ia_valid & ATTR_KILL_SGID))
+ attr->ia_valid |= ATTR_KILL_SGID;
+
return ll_setattr_raw(de->d_inode, attr);
}
/* Bypass la_vaild == LA_MODE,
* this is for changing file with SUID or SGID. */
if ((la->la_valid & ~LA_MODE) &&
+ !(ma->ma_attr_flags & MDS_PERM_BYPASS) &&
(uc->mu_fsuid != tmp_la->la_uid) &&
!mdd_capable(uc, CAP_FOWNER))
RETURN(-EPERM);
if (in & MDS_OPEN_OWNEROVERRIDE)
ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE;
+ if (in & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+ ma->ma_attr_flags |= MDS_PERM_BYPASS;
+
/*XXX need ATTR_RAW?*/
in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|