Search code examples
linux-kernelnfs

Why nfsd clears S_ISUID bit in SETATTR if I try to set S_ISUID and owner at the same time?


NFSv3 protocol specifies that SETATTR can set file/dir mode and owner at the same time (as well as few other things). And yet Linux implementation of nfsd behaves in a quite strange way:

/* Revoke setuid/setgid on chown */
if (!S_ISDIR(inode->i_mode) &&
    ((iap->ia_valid & ATTR_UID) || (iap->ia_valid & ATTR_GID))) {
    iap->ia_valid |= ATTR_KILL_PRIV;
    if (iap->ia_valid & ATTR_MODE) {
        /* we're setting mode too, just clear the s*id bits */
        iap->ia_mode &= ~S_ISUID;
        if (iap->ia_mode & S_IXGRP)
            iap->ia_mode &= ~S_ISGID;
    } else {
        /* set ATTR_KILL_* bits and let VFS handle it */
        iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID);
    }
}

What is the reason for this? I spent a lot of time tracking it down in some old app (that for some reason could not copy a file via NFS without losing suid bit). Is it a bug? It happens even if new owner is the same.


Solution

  • It is a bug in Linux implementation of NFS server. See NFS specs.