2006-01-05 10:32:47 +00:00
|
|
|
/* Change the protections of file relative to open directory. Linux version.
|
2020-01-01 00:14:33 +00:00
|
|
|
Copyright (C) 2006-2020 Free Software Foundation, Inc.
|
2006-01-05 10:32:47 +00:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2012-02-09 23:18:22 +00:00
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 05:40:42 +00:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
2006-01-05 10:32:47 +00:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2020-01-22 18:01:20 +00:00
|
|
|
#include <not-cancel.h>
|
2006-01-05 10:32:47 +00:00
|
|
|
#include <stdio.h>
|
2020-01-22 18:01:20 +00:00
|
|
|
#include <sys/stat.h>
|
2006-01-05 10:32:47 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sysdep.h>
|
2020-01-22 18:01:20 +00:00
|
|
|
#include <unistd.h>
|
2006-01-05 10:32:47 +00:00
|
|
|
|
|
|
|
int
|
2015-10-19 12:04:33 +00:00
|
|
|
fchmodat (int fd, const char *file, mode_t mode, int flag)
|
2006-01-05 10:32:47 +00:00
|
|
|
{
|
2020-01-22 18:01:20 +00:00
|
|
|
if (flag == 0)
|
|
|
|
return INLINE_SYSCALL (fchmodat, 3, fd, file, mode);
|
|
|
|
else if (flag != AT_SYMLINK_NOFOLLOW)
|
2015-10-13 19:00:45 +00:00
|
|
|
return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
|
2020-01-22 18:01:20 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The kernel system call does not have a mode argument.
|
|
|
|
However, we can create an O_PATH descriptor and change that
|
|
|
|
via /proc (which does not resolve symbolic links). */
|
|
|
|
|
|
|
|
int pathfd = __openat_nocancel (fd, file,
|
|
|
|
O_PATH | O_NOFOLLOW | O_CLOEXEC);
|
|
|
|
if (pathfd < 0)
|
|
|
|
/* This may report errors such as ENFILE and EMFILE. The
|
|
|
|
caller can treat them as temporary if necessary. */
|
|
|
|
return pathfd;
|
|
|
|
|
2020-02-18 16:52:27 +00:00
|
|
|
/* Use fstatat because fstat does not work on O_PATH descriptors
|
|
|
|
before Linux 3.6. */
|
|
|
|
struct stat64 st;
|
|
|
|
if (fstatat64 (pathfd, "", &st, AT_EMPTY_PATH) != 0)
|
|
|
|
{
|
|
|
|
__close_nocancel (pathfd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Some Linux versions with some file systems can actually
|
|
|
|
change symbolic link permissions via /proc, but this is not
|
|
|
|
intentional, and it gives inconsistent results (e.g., error
|
|
|
|
return despite mode change). The expected behavior is that
|
|
|
|
symbolic link modes cannot be changed at all, and this check
|
|
|
|
enforces that. */
|
|
|
|
if (S_ISLNK (st.st_mode))
|
|
|
|
{
|
|
|
|
__close_nocancel (pathfd);
|
|
|
|
__set_errno (EOPNOTSUPP);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For most file systems, fchmod does not operate on O_PATH
|
|
|
|
descriptors, so go through /proc. */
|
2020-01-22 18:01:20 +00:00
|
|
|
char buf[32];
|
|
|
|
if (__snprintf (buf, sizeof (buf), "/proc/self/fd/%d", pathfd) < 0)
|
|
|
|
{
|
|
|
|
/* This also may report strange error codes to the caller
|
|
|
|
(although snprintf really should not fail). */
|
|
|
|
__close_nocancel (pathfd);
|
|
|
|
return -1;
|
|
|
|
}
|
2006-01-05 10:32:47 +00:00
|
|
|
|
2020-01-22 18:01:20 +00:00
|
|
|
int ret = __chmod (buf, mode);
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
if (errno == ENOENT)
|
|
|
|
/* /proc has not been mounted. Without /proc, there is no
|
|
|
|
way to upgrade the O_PATH descriptor to a full
|
|
|
|
descriptor. It is also not possible to re-open the
|
|
|
|
file without O_PATH because the file name may refer to
|
|
|
|
another file, and opening that without O_PATH may have
|
|
|
|
side effects (such as blocking, device rewinding, or
|
|
|
|
releasing POSIX locks). */
|
|
|
|
__set_errno (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
__close_nocancel (pathfd);
|
|
|
|
return ret;
|
|
|
|
}
|
2006-01-05 10:32:47 +00:00
|
|
|
}
|
2020-01-22 17:56:04 +00:00
|
|
|
libc_hidden_def (fchmodat)
|