This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: XFS reports lchmod failure, but changes file system contents
On Wed, Feb 12, 2020 at 03:19:51PM -0500, Rich Felker wrote:
> On Wed, Feb 12, 2020 at 09:17:41PM +0100, Andreas Schwab wrote:
> > On Feb 12 2020, Florian Weimer wrote:
> >
> > > * Al Viro:
> > >
> > >> On Wed, Feb 12, 2020 at 08:15:08PM +0100, Florian Weimer wrote:
> > >>
> > >>> | Further, I've found some inconsistent behavior with ext4: chmod on the
> > >>> | magic symlink fails with EOPNOTSUPP as in Florian's test, but fchmod
> > >>> | on the O_PATH fd succeeds and changes the symlink mode. This is with
> > >>> | 5.4. Cany anyone else confirm this? Is it a problem?
> > >>>
> > >>> It looks broken to me because fchmod (as an inode-changing operation)
> > >>> is not supposed to work on O_PATH descriptors.
> > >>
> > >> Why? O_PATH does have an associated inode just fine; where does
> > >> that "not supposed to" come from?
> > >
> > > It fails on most file systems right now. I thought that was expected.
> > > Other system calls (fsetxattr IIRC) do not work on O_PATH descriptors,
> > > either. I assumed that an O_PATH descriptor was not intending to
> > > confer that capability. Even openat fails.
> >
> > According to open(2), this is expected:
> >
> > O_PATH (since Linux 2.6.39)
> > Obtain a file descriptor that can be used for two purposes: to
> > indicate a location in the filesystem tree and to perform opera-
> > tions that act purely at the file descriptor level. The file
> > itself is not opened, and other file operations (e.g., read(2),
> > write(2), fchmod(2), fchown(2), fgetxattr(2), ioctl(2), mmap(2))
> > fail with the error EBADF.
>
> That text is outdated and should be corrected. Fixing fchmod fchown,
> fstat, etc. to operate on O_PATH file descriptors was a very
> intentional change in the kernel.
Wait. First of all, in the testcase it's chmod(2) applied to /proc/*/fd/*; that's
no different for O_PATH descriptors. Location in the tree *is* associated with
O_PATH fd; that's the only thing they exist for.
fchmod(2) will certainly fail for those, as it always had:
int ksys_fchmod(unsigned int fd, umode_t mode)
{
struct fd f = fdget(fd);
int err = -EBADF;
if (f.file) {
audit_file(f.file);
err = chmod_common(&f.file->f_path, mode);
fdput(f);
}
return err;
}
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
{
return ksys_fchmod(fd, mode);
}
... and that fdget() will give you -EBADF. If you've managed to get
fchmod(2) the syscall to give you anything other than that, I want
to see details.