From patchwork Tue Feb 11 15:25:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 37967 Received: (qmail 83922 invoked by alias); 11 Feb 2020 15:25:40 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 83902 invoked by uid 89); 11 Feb 2020 15:25:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy=backporting, releasing, 3.6 X-HELO: us-smtp-1.mimecast.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581434736; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tAR+3uu+dpRJw2i8fG4vfNj1KOgeGuF/kfsZx4jw+So=; b=YOslVLlZeLpREKZoJD5/GthLxv4sFFNc3KT6kfxUxCwA6vM5x8dsgtXrKT+QJP9sASHDtI jjy7Z6Lu++reot8EM7PXhtv1+yJ1+apv7Iug2KoSN3HSJYEcnm3621W0h6XuvuN9MEjr79 7+HdmJUIjsh3vUBTKjrTKwSIgHqrBeY= From: Florian Weimer To: Paul Eggert Cc: libc-alpha@sourceware.org Subject: Re: [PATCH 3/5] Linux: Emulate fchmodat with AT_SYMLINK_NOFOLLOW using O_PATH [BZ #14578] References: <3391fd4d8a6c8d6457985665b1b824dddf64e422.1579723048.git.fweimer@redhat.com> <1a62d1a2-6232-7d2a-f68f-6170d2b0dfc8@cs.ucla.edu> <87y2tcnnnw.fsf@mid.deneb.enyo.de> <47b703f6-fb1d-4cae-b874-6ec8b6d8df4e@cs.ucla.edu> Date: Tue, 11 Feb 2020 16:25:29 +0100 In-Reply-To: <47b703f6-fb1d-4cae-b874-6ec8b6d8df4e@cs.ucla.edu> (Paul Eggert's message of "Sun, 9 Feb 2020 02:06:07 -0800") Message-ID: <87k14tjgd2.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com * Paul Eggert: > On 2/9/20 12:57 AM, Florian Weimer wrote: >> What do you think about introducing new symbol versions vs keeping >> things as they are in the patch today? > > I'm not quite following the relationship between the two > alternatives. Isn't the symbol version independent of whether we keep > things as they are now, or install the patch that you proposed, or > install that patch with my further suggestions? That is, I don't see > why the patch (or patch variant) would require us to change symbol > versions. > >> If we do not introduce new symbol versions, we should strive to >> backport this change widely, so that users do not run into obscure >> failures. > > Yes, backporting would be good. Essentially Gnulib is already doing > that, for Gnulib-using apps. Okay, this is what I'm going to commit soon, with no symbol version changes. Thanks, Florian 8<------------------------------------------------------------------8< /proc/self/fd files are special and chmod on O_PATH descriptors in that directory operates on the symbolic link itself (like lchmod). ----- sysdeps/unix/sysv/linux/fchmodat.c | 57 +++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c index c41ebb290d..719053b333 100644 --- a/sysdeps/unix/sysv/linux/fchmodat.c +++ b/sysdeps/unix/sysv/linux/fchmodat.c @@ -18,24 +18,61 @@ #include #include -#include +#include #include -#include -#include +#include #include -#include #include +#include int fchmodat (int fd, const char *file, mode_t mode, int flag) { - if (flag & ~AT_SYMLINK_NOFOLLOW) + if (flag == 0) + return INLINE_SYSCALL (fchmodat, 3, fd, file, mode); + else if (flag != AT_SYMLINK_NOFOLLOW) return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); -#ifndef __NR_lchmod /* Linux so far has no lchmod syscall. */ - if (flag & AT_SYMLINK_NOFOLLOW) - return INLINE_SYSCALL_ERROR_RETURN_VALUE (ENOTSUP); -#endif + 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). */ - return INLINE_SYSCALL (fchmodat, 3, fd, file, mode); + 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; + + 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; + } + + /* This operates directly on the symbolic link if it is one. + /proc/self/fd files look like symbolic links, but they are + not. (fchmod and fchmodat do not work on O_PATH descriptors, + similar to fstat before Linux 3.6.) */ + 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; + } } libc_hidden_def (fchmodat)