mirror of
				https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
				synced 2025-11-04 07:44:51 +10:00 
			
		
		
		
	v6.6-vfs.fchmodat2
-----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCZOXT7QAKCRCRxhvAZXjc ort3AP0VIK/oJk5skgjpinQrCfvtVz0XOtawuBtn0f1weIfb6AD9Hg1rqOKnQD5z dkvn3xaEr3gPOVzqU5SvFwVoCM0cMwA= =24Ha -----END PGP SIGNATURE----- Merge tag 'v6.6-vfs.fchmodat2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull fchmodat2 system call from Christian Brauner: "This adds the fchmodat2() system call. It is a revised version of the fchmodat() system call, adding a missing flag argument. Support for both AT_SYMLINK_NOFOLLOW and AT_EMPTY_PATH are included. Adding this system call revision has been a longstanding request but so far has always fallen through the cracks. While the kernel implementation of fchmodat() does not have a flag argument the libc provided POSIX-compliant fchmodat(3) version does. Both glibc and musl have to implement a workaround in order to support AT_SYMLINK_NOFOLLOW (see [1] and [2]). The workaround is brittle because it relies not just on O_PATH and O_NOFOLLOW semantics and procfs magic links but also on our rather inconsistent symlink semantics. This gives userspace a proper fchmodat2() system call that libcs can use to properly implement fchmodat(3) and allows them to get rid of their hacks. In this case it will immediately benefit them as the current workaround is already defunct because of aformentioned inconsistencies. In addition to AT_SYMLINK_NOFOLLOW, give userspace the ability to use AT_EMPTY_PATH with fchmodat2(). This is already possible with fchownat() so there's no reason to not also support it for fchmodat2(). The implementation is simple and comes with selftests. Implementation of the system call and wiring up the system call are done as separate patches even though they could arguably be one patch. But in case there are merge conflicts from other system call additions it can be beneficial to have separate patches" Link: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/fchmodat.c;h=17eca54051ee28ba1ec3f9aed170a62630959143;hb=a492b1e5ef7ab50c6fdd4e4e9879ea5569ab0a6c#l35 [1] Link: https://git.musl-libc.org/cgit/musl/tree/src/stat/fchmodat.c?id=718f363bc2067b6487900eddc9180c84e7739f80#n28 [2] * tag 'v6.6-vfs.fchmodat2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: selftests: fchmodat2: remove duplicate unneeded defines fchmodat2: add support for AT_EMPTY_PATH selftests: Add fchmodat2 selftest arch: Register fchmodat2, usually as syscall 452 fs: Add fchmodat2() Non-functional cleanup of a "__user * filename"
This commit is contained in:
		
						commit
						475d4df827
					
				@ -491,3 +491,4 @@
 | 
			
		||||
559	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
560	common	set_mempolicy_home_node		sys_ni_syscall
 | 
			
		||||
561	common	cachestat			sys_cachestat
 | 
			
		||||
562	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -465,3 +465,4 @@
 | 
			
		||||
449	common	futex_waitv			sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,7 @@
 | 
			
		||||
#define __ARM_NR_compat_set_tls		(__ARM_NR_COMPAT_BASE + 5)
 | 
			
		||||
#define __ARM_NR_COMPAT_END		(__ARM_NR_COMPAT_BASE + 0x800)
 | 
			
		||||
 | 
			
		||||
#define __NR_compat_syscalls		452
 | 
			
		||||
#define __NR_compat_syscalls		453
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define __ARCH_WANT_SYS_CLONE
 | 
			
		||||
 | 
			
		||||
@ -909,6 +909,8 @@ __SYSCALL(__NR_futex_waitv, sys_futex_waitv)
 | 
			
		||||
__SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
 | 
			
		||||
#define __NR_cachestat 451
 | 
			
		||||
__SYSCALL(__NR_cachestat, sys_cachestat)
 | 
			
		||||
#define __NR_fchmodat2 452
 | 
			
		||||
__SYSCALL(__NR_fchmodat2, sys_fchmodat2)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Please add new compat syscalls above this comment and update
 | 
			
		||||
 | 
			
		||||
@ -372,3 +372,4 @@
 | 
			
		||||
449	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -451,3 +451,4 @@
 | 
			
		||||
449	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -457,3 +457,4 @@
 | 
			
		||||
449	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -390,3 +390,4 @@
 | 
			
		||||
449	n32	futex_waitv			sys_futex_waitv
 | 
			
		||||
450	n32	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	n32	cachestat			sys_cachestat
 | 
			
		||||
452	n32	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -366,3 +366,4 @@
 | 
			
		||||
449	n64	futex_waitv			sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	n64	cachestat			sys_cachestat
 | 
			
		||||
452	n64	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -439,3 +439,4 @@
 | 
			
		||||
449	o32	futex_waitv			sys_futex_waitv
 | 
			
		||||
450	o32	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	o32	cachestat			sys_cachestat
 | 
			
		||||
452	o32	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -450,3 +450,4 @@
 | 
			
		||||
449	common	futex_waitv			sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -538,3 +538,4 @@
 | 
			
		||||
449	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
450 	nospu	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -454,3 +454,4 @@
 | 
			
		||||
449  common	futex_waitv		sys_futex_waitv			sys_futex_waitv
 | 
			
		||||
450  common	set_mempolicy_home_node	sys_set_mempolicy_home_node	sys_set_mempolicy_home_node
 | 
			
		||||
451  common	cachestat		sys_cachestat			sys_cachestat
 | 
			
		||||
452  common	fchmodat2		sys_fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -454,3 +454,4 @@
 | 
			
		||||
449	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -497,3 +497,4 @@
 | 
			
		||||
449	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -456,3 +456,4 @@
 | 
			
		||||
449	i386	futex_waitv		sys_futex_waitv
 | 
			
		||||
450	i386	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	i386	cachestat		sys_cachestat
 | 
			
		||||
452	i386	fchmodat2		sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
@ -373,6 +373,7 @@
 | 
			
		||||
449	common	futex_waitv		sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node	sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat		sys_cachestat
 | 
			
		||||
452	common	fchmodat2		sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Due to a historical design error, certain syscalls are numbered differently
 | 
			
		||||
 | 
			
		||||
@ -422,3 +422,4 @@
 | 
			
		||||
449	common  futex_waitv                     sys_futex_waitv
 | 
			
		||||
450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node
 | 
			
		||||
451	common	cachestat			sys_cachestat
 | 
			
		||||
452	common	fchmodat2			sys_fchmodat2
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								fs/open.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								fs/open.c
									
									
									
									
									
								
							@ -671,11 +671,20 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
 | 
			
		||||
static int do_fchmodat(int dfd, const char __user *filename, umode_t mode,
 | 
			
		||||
		       unsigned int flags)
 | 
			
		||||
{
 | 
			
		||||
	struct path path;
 | 
			
		||||
	int error;
 | 
			
		||||
	unsigned int lookup_flags = LOOKUP_FOLLOW;
 | 
			
		||||
	unsigned int lookup_flags;
 | 
			
		||||
 | 
			
		||||
	if (unlikely(flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
 | 
			
		||||
	if (flags & AT_EMPTY_PATH)
 | 
			
		||||
		lookup_flags |= LOOKUP_EMPTY;
 | 
			
		||||
 | 
			
		||||
retry:
 | 
			
		||||
	error = user_path_at(dfd, filename, lookup_flags, &path);
 | 
			
		||||
	if (!error) {
 | 
			
		||||
@ -689,15 +698,21 @@ retry:
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SYSCALL_DEFINE4(fchmodat2, int, dfd, const char __user *, filename,
 | 
			
		||||
		umode_t, mode, unsigned int, flags)
 | 
			
		||||
{
 | 
			
		||||
	return do_fchmodat(dfd, filename, mode, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename,
 | 
			
		||||
		umode_t, mode)
 | 
			
		||||
{
 | 
			
		||||
	return do_fchmodat(dfd, filename, mode);
 | 
			
		||||
	return do_fchmodat(dfd, filename, mode, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
 | 
			
		||||
{
 | 
			
		||||
	return do_fchmodat(AT_FDCWD, filename, mode);
 | 
			
		||||
	return do_fchmodat(AT_FDCWD, filename, mode, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
@ -438,8 +438,10 @@ asmlinkage long sys_chdir(const char __user *filename);
 | 
			
		||||
asmlinkage long sys_fchdir(unsigned int fd);
 | 
			
		||||
asmlinkage long sys_chroot(const char __user *filename);
 | 
			
		||||
asmlinkage long sys_fchmod(unsigned int fd, umode_t mode);
 | 
			
		||||
asmlinkage long sys_fchmodat(int dfd, const char __user * filename,
 | 
			
		||||
asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
 | 
			
		||||
			     umode_t mode);
 | 
			
		||||
asmlinkage long sys_fchmodat2(int dfd, const char __user *filename,
 | 
			
		||||
			     umode_t mode, unsigned int flags);
 | 
			
		||||
asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
 | 
			
		||||
			     gid_t group, int flag);
 | 
			
		||||
asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group);
 | 
			
		||||
 | 
			
		||||
@ -820,8 +820,11 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
 | 
			
		||||
#define __NR_cachestat 451
 | 
			
		||||
__SYSCALL(__NR_cachestat, sys_cachestat)
 | 
			
		||||
 | 
			
		||||
#define __NR_fchmodat2 452
 | 
			
		||||
__SYSCALL(__NR_fchmodat2, sys_fchmodat2)
 | 
			
		||||
 | 
			
		||||
#undef __NR_syscalls
 | 
			
		||||
#define __NR_syscalls 452
 | 
			
		||||
#define __NR_syscalls 453
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 32 bit systems traditionally used different
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ TARGETS += drivers/net/bonding
 | 
			
		||||
TARGETS += drivers/net/team
 | 
			
		||||
TARGETS += efivarfs
 | 
			
		||||
TARGETS += exec
 | 
			
		||||
TARGETS += fchmodat2
 | 
			
		||||
TARGETS += filesystems
 | 
			
		||||
TARGETS += filesystems/binderfs
 | 
			
		||||
TARGETS += filesystems/epoll
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								tools/testing/selftests/fchmodat2/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tools/testing/selftests/fchmodat2/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-2.0-only
 | 
			
		||||
/*_test
 | 
			
		||||
							
								
								
									
										6
									
								
								tools/testing/selftests/fchmodat2/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tools/testing/selftests/fchmodat2/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined $(KHDR_INCLUDES)
 | 
			
		||||
TEST_GEN_PROGS := fchmodat2_test
 | 
			
		||||
 | 
			
		||||
include ../lib.mk
 | 
			
		||||
							
								
								
									
										142
									
								
								tools/testing/selftests/fchmodat2/fchmodat2_test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								tools/testing/selftests/fchmodat2/fchmodat2_test.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,142 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <syscall.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "../kselftest.h"
 | 
			
		||||
 | 
			
		||||
int sys_fchmodat2(int dfd, const char *filename, mode_t mode, int flags)
 | 
			
		||||
{
 | 
			
		||||
	int ret = syscall(__NR_fchmodat2, dfd, filename, mode, flags);
 | 
			
		||||
 | 
			
		||||
	return ret >= 0 ? ret : -errno;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int setup_testdir(void)
 | 
			
		||||
{
 | 
			
		||||
	int dfd, ret;
 | 
			
		||||
	char dirname[] = "/tmp/ksft-fchmodat2.XXXXXX";
 | 
			
		||||
 | 
			
		||||
	/* Make the top-level directory. */
 | 
			
		||||
	if (!mkdtemp(dirname))
 | 
			
		||||
		ksft_exit_fail_msg("%s: failed to create tmpdir\n", __func__);
 | 
			
		||||
 | 
			
		||||
	dfd = open(dirname, O_PATH | O_DIRECTORY);
 | 
			
		||||
	if (dfd < 0)
 | 
			
		||||
		ksft_exit_fail_msg("%s: failed to open tmpdir\n", __func__);
 | 
			
		||||
 | 
			
		||||
	ret = openat(dfd, "regfile", O_CREAT | O_WRONLY | O_TRUNC, 0644);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		ksft_exit_fail_msg("%s: failed to create file in tmpdir\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
	close(ret);
 | 
			
		||||
 | 
			
		||||
	ret = symlinkat("regfile", dfd, "symlink");
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		ksft_exit_fail_msg("%s: failed to create symlink in tmpdir\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	return dfd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int expect_mode(int dfd, const char *filename, mode_t expect_mode)
 | 
			
		||||
{
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	int ret = fstatat(dfd, filename, &st, AT_SYMLINK_NOFOLLOW);
 | 
			
		||||
 | 
			
		||||
	if (ret)
 | 
			
		||||
		ksft_exit_fail_msg("%s: %s: fstatat failed\n",
 | 
			
		||||
				__func__, filename);
 | 
			
		||||
 | 
			
		||||
	return (st.st_mode == expect_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_regfile(void)
 | 
			
		||||
{
 | 
			
		||||
	int dfd, ret;
 | 
			
		||||
 | 
			
		||||
	dfd = setup_testdir();
 | 
			
		||||
 | 
			
		||||
	ret = sys_fchmodat2(dfd, "regfile", 0640, 0);
 | 
			
		||||
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		ksft_exit_fail_msg("%s: fchmodat2(noflag) failed\n", __func__);
 | 
			
		||||
 | 
			
		||||
	if (!expect_mode(dfd, "regfile", 0100640))
 | 
			
		||||
		ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	ret = sys_fchmodat2(dfd, "regfile", 0600, AT_SYMLINK_NOFOLLOW);
 | 
			
		||||
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		ksft_exit_fail_msg("%s: fchmodat2(AT_SYMLINK_NOFOLLOW) failed\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	if (!expect_mode(dfd, "regfile", 0100600))
 | 
			
		||||
		ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2 with nofollow\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	ksft_test_result_pass("fchmodat2(regfile)\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_symlink(void)
 | 
			
		||||
{
 | 
			
		||||
	int dfd, ret;
 | 
			
		||||
 | 
			
		||||
	dfd = setup_testdir();
 | 
			
		||||
 | 
			
		||||
	ret = sys_fchmodat2(dfd, "symlink", 0640, 0);
 | 
			
		||||
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		ksft_exit_fail_msg("%s: fchmodat2(noflag) failed\n", __func__);
 | 
			
		||||
 | 
			
		||||
	if (!expect_mode(dfd, "regfile", 0100640))
 | 
			
		||||
		ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	if (!expect_mode(dfd, "symlink", 0120777))
 | 
			
		||||
		ksft_exit_fail_msg("%s: wrong symlink mode bits after fchmodat2\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	ret = sys_fchmodat2(dfd, "symlink", 0600, AT_SYMLINK_NOFOLLOW);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * On certain filesystems (xfs or btrfs), chmod operation fails. So we
 | 
			
		||||
	 * first check the symlink target but if the operation fails we mark the
 | 
			
		||||
	 * test as skipped.
 | 
			
		||||
	 *
 | 
			
		||||
	 * https://sourceware.org/legacy-ml/libc-alpha/2020-02/msg00467.html
 | 
			
		||||
	 */
 | 
			
		||||
	if (ret == 0 && !expect_mode(dfd, "symlink", 0120600))
 | 
			
		||||
		ksft_exit_fail_msg("%s: wrong symlink mode bits after fchmodat2 with nofollow\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	if (!expect_mode(dfd, "regfile", 0100640))
 | 
			
		||||
		ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2 with nofollow\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
 | 
			
		||||
	if (ret != 0)
 | 
			
		||||
		ksft_test_result_skip("fchmodat2(symlink)\n");
 | 
			
		||||
	else
 | 
			
		||||
		ksft_test_result_pass("fchmodat2(symlink)\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define NUM_TESTS 2
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	ksft_print_header();
 | 
			
		||||
	ksft_set_plan(NUM_TESTS);
 | 
			
		||||
 | 
			
		||||
	test_regfile();
 | 
			
		||||
	test_symlink();
 | 
			
		||||
 | 
			
		||||
	if (ksft_get_fail_cnt() + ksft_get_error_cnt() > 0)
 | 
			
		||||
		ksft_exit_fail();
 | 
			
		||||
	else
 | 
			
		||||
		ksft_exit_pass();
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user