1717#include "../kselftest_harness.h"
1818#include "../clone3/clone3_selftests.h"
1919
20+
21+ #ifndef F_LINUX_SPECIFIC_BASE
22+ #define F_LINUX_SPECIFIC_BASE 1024
23+ #endif
24+
25+ #ifndef F_DUPFD_QUERY
26+ #define F_DUPFD_QUERY (F_LINUX_SPECIFIC_BASE + 3)
27+ #endif
28+
2029static inline int sys_close_range (unsigned int fd , unsigned int max_fd ,
2130 unsigned int flags )
2231{
@@ -45,6 +54,15 @@ TEST(core_close_range)
4554 SKIP (return , "close_range() syscall not supported" );
4655 }
4756
57+ for (i = 0 ; i < 100 ; i ++ ) {
58+ ret = fcntl (open_fds [i ], F_DUPFD_QUERY , open_fds [i + 1 ]);
59+ if (ret < 0 ) {
60+ EXPECT_EQ (errno , EINVAL );
61+ } else {
62+ EXPECT_EQ (ret , 0 );
63+ }
64+ }
65+
4866 EXPECT_EQ (0 , sys_close_range (open_fds [0 ], open_fds [50 ], 0 ));
4967
5068 for (i = 0 ; i <= 50 ; i ++ )
@@ -358,7 +376,7 @@ TEST(close_range_cloexec_unshare)
358376 */
359377TEST (close_range_cloexec_syzbot )
360378{
361- int fd1 , fd2 , fd3 , flags , ret , status ;
379+ int fd1 , fd2 , fd3 , fd4 , flags , ret , status ;
362380 pid_t pid ;
363381 struct __clone_args args = {
364382 .flags = CLONE_FILES ,
@@ -372,6 +390,13 @@ TEST(close_range_cloexec_syzbot)
372390 fd2 = dup2 (fd1 , 1000 );
373391 EXPECT_GT (fd2 , 0 );
374392
393+ flags = fcntl (fd1 , F_DUPFD_QUERY , fd2 );
394+ if (flags < 0 ) {
395+ EXPECT_EQ (errno , EINVAL );
396+ } else {
397+ EXPECT_EQ (flags , 1 );
398+ }
399+
375400 pid = sys_clone3 (& args , sizeof (args ));
376401 ASSERT_GE (pid , 0 );
377402
@@ -396,6 +421,15 @@ TEST(close_range_cloexec_syzbot)
396421 fd3 = dup2 (fd1 , 42 );
397422 EXPECT_GT (fd3 , 0 );
398423
424+ flags = fcntl (fd1 , F_DUPFD_QUERY , fd3 );
425+ if (flags < 0 ) {
426+ EXPECT_EQ (errno , EINVAL );
427+ } else {
428+ EXPECT_EQ (flags , 1 );
429+ }
430+
431+
432+
399433 /*
400434 * Duplicating the file descriptor must remove the
401435 * FD_CLOEXEC flag.
@@ -426,13 +460,32 @@ TEST(close_range_cloexec_syzbot)
426460 fd3 = dup2 (fd1 , 42 );
427461 EXPECT_GT (fd3 , 0 );
428462
463+ flags = fcntl (fd1 , F_DUPFD_QUERY , fd3 );
464+ if (flags < 0 ) {
465+ EXPECT_EQ (errno , EINVAL );
466+ } else {
467+ EXPECT_EQ (flags , 1 );
468+ }
469+
470+ fd4 = open ("/dev/null" , O_RDWR );
471+ EXPECT_GT (fd4 , 0 );
472+
473+ /* Same inode, different file pointers. */
474+ flags = fcntl (fd1 , F_DUPFD_QUERY , fd4 );
475+ if (flags < 0 ) {
476+ EXPECT_EQ (errno , EINVAL );
477+ } else {
478+ EXPECT_EQ (flags , 0 );
479+ }
480+
429481 flags = fcntl (fd3 , F_GETFD );
430482 EXPECT_GT (flags , -1 );
431483 EXPECT_EQ (flags & FD_CLOEXEC , 0 );
432484
433485 EXPECT_EQ (close (fd1 ), 0 );
434486 EXPECT_EQ (close (fd2 ), 0 );
435487 EXPECT_EQ (close (fd3 ), 0 );
488+ EXPECT_EQ (close (fd4 ), 0 );
436489}
437490
438491/*
0 commit comments