Linux Kernel Selftest development
 help / color / mirror / Atom feed
* [PATCH] Add Selftest to test fork() syscall
@ 2024-10-22 20:42 Shivam Chaudhary
  2024-10-23 20:45 ` Shuah Khan
  0 siblings, 1 reply; 4+ messages in thread
From: Shivam Chaudhary @ 2024-10-22 20:42 UTC (permalink / raw)
  To: selftests; +Cc: linux-kselftest, skhan, Shivam Chaudhary

This test verifies the correct behavior of the fork() system call,
which creates a child process by duplicating the parent process.

The test checks the following:
- The child PID returned by fork() is present in /proc.
- The child PID is different from the parent PID.
- The memory allocated to a variable in the child process is independent
  of the parent process.

Test logs :

- Run without root
 TAP version 13
 1..1
 ok 1 # SKIP This test needs root to run!

- Run with root
TAP version 13
1..1
 # Inside the parent process.
 # Child PID got from fork() return : 56038
 # Parent PID from getpid(): 56037
 # Inside the child process.
 1..2
 ok 1 Child Pid from /proc and fork() matching
 ok 2 Child Pid != Parent pid
 1..3
 ok 3 After modification in child No effect on the value of 'var' in parent
 # Totals: pass:3 fail:0 xfail:0 xpass:0 skip:0 error:0

Signed-off-by: Shivam Chaudhary <cvam0000@gmail.com>
---

Here is my proposal for a new directory, /syscalls, to add syscall selftests,
as there is currently no dedicated space for these tests. I encountered this
issue while writing the test case for the delete_module syscall and was unsure
where to place it. As a heads-up, the delete_module test is currently under
review, and I would like to add it to this directory.

 tools/testing/selftests/Makefile              |   1 +
 tools/testing/selftests/syscalls/.gitignore   |   1 +
 .../syscalls/fork_syscall/.gitignore          |   1 +
 .../selftests/syscalls/fork_syscall/Makefile  |   5 +
 .../syscalls/fork_syscall/fork_syscall.c      | 151 ++++++++++++++++++
 5 files changed, 159 insertions(+)
 create mode 100644 tools/testing/selftests/syscalls/.gitignore
 create mode 100644 tools/testing/selftests/syscalls/fork_syscall/.gitignore
 create mode 100644 tools/testing/selftests/syscalls/fork_syscall/Makefile
 create mode 100644 tools/testing/selftests/syscalls/fork_syscall/fork_syscall.c

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 363d031a16f7..9265c17c5de3 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -97,6 +97,7 @@ TARGETS += sparc64
 TARGETS += splice
 TARGETS += static_keys
 TARGETS += sync
+TARGETS += syscalls/fork_syscall
 TARGETS += syscall_user_dispatch
 TARGETS += sysctl
 TARGETS += tc-testing
diff --git a/tools/testing/selftests/syscalls/.gitignore b/tools/testing/selftests/syscalls/.gitignore
new file mode 100644
index 000000000000..c7ae138d3f0c
--- /dev/null
+++ b/tools/testing/selftests/syscalls/.gitignore
@@ -0,0 +1 @@
+// SPDX-License-Identifier: GPL-2.0
\ No newline at end of file
diff --git a/tools/testing/selftests/syscalls/fork_syscall/.gitignore b/tools/testing/selftests/syscalls/fork_syscall/.gitignore
new file mode 100644
index 000000000000..788cc1ff70bd
--- /dev/null
+++ b/tools/testing/selftests/syscalls/fork_syscall/.gitignore
@@ -0,0 +1 @@
+# SPDX-License-Identifier: GPL-2.0-only
\ No newline at end of file
diff --git a/tools/testing/selftests/syscalls/fork_syscall/Makefile b/tools/testing/selftests/syscalls/fork_syscall/Makefile
new file mode 100644
index 000000000000..56033a3d5a87
--- /dev/null
+++ b/tools/testing/selftests/syscalls/fork_syscall/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+TEST_GEN_PROGS := fork_syscall
+CFLAGS += -Wall
+
+include ../lib.mk
\ No newline at end of file
diff --git a/tools/testing/selftests/syscalls/fork_syscall/fork_syscall.c b/tools/testing/selftests/syscalls/fork_syscall/fork_syscall.c
new file mode 100644
index 000000000000..eab22831f7e1
--- /dev/null
+++ b/tools/testing/selftests/syscalls/fork_syscall/fork_syscall.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* kselftest for fork() system call
+ *
+ * Summery : fork() system call is used to create a new process
+ * by duplicating an existing one. The new process, known as the
+ * child process, is a copy of the parent process.
+ * 
+ * Child process is dublicate process but has different PID and 
+ * memory allocation.
+ * 
+ * About the test : With this test we are testing the following:
+ * - Child PID which fork() returns to Parent is present in /proc
+ * - Child PID is not same as Parent PID.
+ * - Memory allocation to a variable in child and parent process
+ *   is different.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <ctype.h>
+
+#include "../../kselftest.h"
+
+// Function to check if a string is numeric (PID check)
+int is_numeric(const char *str) {
+    while (*str) {
+        if (!isdigit(*str)) return 0;
+        str++;
+    }
+    return 1;
+}
+
+// Function to find the child PID in /proc
+pid_t find_child_pid(pid_t parent_pid) {
+    DIR *proc_dir = opendir("/proc");
+    struct dirent *entry;
+
+    if (proc_dir == NULL) {
+        perror("Failed to open /proc directory");
+        ksft_exit_fail();
+        return 1;
+    }
+
+    // Iterate through the /proc directory to find PIDs
+    while ((entry = readdir(proc_dir)) != NULL) {
+        // Check if the entry is a PID
+        if (is_numeric(entry->d_name)) {  
+            pid_t pid = atoi(entry->d_name);
+
+            // Construct the path to /proc/<pid>/
+            //stat to check the parent PID
+
+            char path[40], buffer[100];
+            snprintf(path, 40, "/proc/%d/stat", pid);
+
+            FILE *stat_file = fopen(path, "r");
+            if (stat_file != NULL) {
+                fgets(buffer, 100, stat_file);
+                fclose(stat_file);
+
+                // The fourth field in /proc/<pid>/stat is the parent PID
+                pid_t ppid;
+                sscanf(buffer, "%*d %*s %*c %d", &ppid);
+
+                if (ppid == parent_pid) {
+                    closedir(proc_dir);
+                    // Return the child PID if the parent PID matches
+                    return pid;  
+                }
+            }
+        }
+    }
+
+    closedir(proc_dir);
+
+    // Return -1 if no child PID was found
+    return -1;  
+}
+
+int main(void) {
+
+    // Setting up kselftest framework
+	ksft_print_header();
+	ksft_set_plan(1);
+
+    // Check if test is run a root
+	if (geteuid()) {
+		ksft_test_result_skip("This test needs root to run!\n");
+		return 1;
+	}
+
+    // forking
+    pid_t pid = fork();
+
+    // Declare a variable in both parent and child processes
+    int var = 17;  
+
+    if (pid == -1) {
+		ksft_test_result_error("%s.\n", strerror(errno));
+		ksft_finished();
+		return 1;
+
+    } else if (pid == 0) {
+        // This is the child process
+        ksft_print_msg("Inside the child process.\n");
+        var = 1998;
+
+    } else {
+        // This is the parent process
+        pid_t ppid=getpid();
+        ksft_print_msg("Inside the parent process.\n");
+        ksft_print_msg("Child PID got from fork() return : %d\n", pid);
+        ksft_print_msg("Parent PID from getpid(): %d\n",ppid);
+
+        // Find the child PID in /proc
+        pid_t child_pid = find_child_pid(getpid());
+        if (child_pid != -1) {
+            ksft_set_plan(2);
+            if(child_pid == pid && pid != ppid && var != 1998) {
+                ksft_test_result_pass("Child Pid from /proc and fork() matching\n");
+                ksft_test_result_pass("Child Pid != Parent pid\n");
+                ksft_set_plan(3);
+                ksft_test_result_pass(
+                    "After modification in child No effect on the value of 'var' in parent\n");
+                ksft_exit_pass();
+		        return 0;
+            }
+            else {
+                ksft_exit_fail();
+			    return 1;
+            }
+        }
+        else {
+            ksft_test_result_fail("Child Pid from /proc and fork() does not match");
+            ksft_exit_fail();
+			return 1;
+        }
+
+        // Wait for the child process to finish
+        wait(NULL);
+    }
+
+    return 0;
+}
+
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] Add Selftest to test fork() syscall
  2024-10-22 20:42 [PATCH] Add Selftest to test fork() syscall Shivam Chaudhary
@ 2024-10-23 20:45 ` Shuah Khan
  2024-10-23 21:11   ` Shivam Chaudhary
  0 siblings, 1 reply; 4+ messages in thread
From: Shuah Khan @ 2024-10-23 20:45 UTC (permalink / raw)
  To: Shivam Chaudhary, selftests; +Cc: linux-kselftest, Shuah Khan

On 10/22/24 14:42, Shivam Chaudhary wrote:
> This test verifies the correct behavior of the fork() system call,
> which creates a child process by duplicating the parent process.
> 
> The test checks the following:
> - The child PID returned by fork() is present in /proc.
> - The child PID is different from the parent PID.
> - The memory allocated to a variable in the child process is independent
>    of the parent process.

Short log should incude the subsystem:

e.g: selftests: add test for fork() syscall

In anycase, I don't see any value to adding this test.
fork() is a heavily used system call.
  
thanks,
-- Shuah

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Add Selftest to test fork() syscall
  2024-10-23 20:45 ` Shuah Khan
@ 2024-10-23 21:11   ` Shivam Chaudhary
  2024-10-23 22:06     ` Shuah Khan
  0 siblings, 1 reply; 4+ messages in thread
From: Shivam Chaudhary @ 2024-10-23 21:11 UTC (permalink / raw)
  To: Shuah Khan, selftests; +Cc: linux-kselftest


On 24/10/24 2:15 AM, Shuah Khan wrote:
> On 10/22/24 14:42, Shivam Chaudhary wrote:
>> This test verifies the correct behavior of the fork() system call,
>> which creates a child process by duplicating the parent process.
>>
>> The test checks the following:
>> - The child PID returned by fork() is present in /proc.
>> - The child PID is different from the parent PID.
>> - The memory allocated to a variable in the child process is independent
>>    of the parent process.
>
> Short log should incude the subsystem:
>
> e.g: selftests: add test for fork() syscall
>
> In anycase, I don't see any value to adding this test.
> fork() is a heavily used system call.
>

Thanks for responding Shuah,

Yes, you are correct that fork() is a heavily used syscall, that is why 
my concern is that

it could fail millions of other program that depends on fork() if any 
error or regression

occurs in the future. In my opinion, that is why we should test it every 
way possible.


thanks
Shivam


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Add Selftest to test fork() syscall
  2024-10-23 21:11   ` Shivam Chaudhary
@ 2024-10-23 22:06     ` Shuah Khan
  0 siblings, 0 replies; 4+ messages in thread
From: Shuah Khan @ 2024-10-23 22:06 UTC (permalink / raw)
  To: Shivam Chaudhary, selftests; +Cc: linux-kselftest, Shuah Khan

On 10/23/24 15:11, Shivam Chaudhary wrote:
> 
> On 24/10/24 2:15 AM, Shuah Khan wrote:
>> On 10/22/24 14:42, Shivam Chaudhary wrote:
>>> This test verifies the correct behavior of the fork() system call,
>>> which creates a child process by duplicating the parent process.
>>>
>>> The test checks the following:
>>> - The child PID returned by fork() is present in /proc.
>>> - The child PID is different from the parent PID.
>>> - The memory allocated to a variable in the child process is independent
>>>    of the parent process.
>>
>> Short log should incude the subsystem:
>>
>> e.g: selftests: add test for fork() syscall
>>
>> In anycase, I don't see any value to adding this test.
>> fork() is a heavily used system call.
>>
> 
> Thanks for responding Shuah,
> 
> Yes, you are correct that fork() is a heavily used syscall, that is why my concern is that
> 
> it could fail millions of other program that depends on fork() if any error or regression
> 
> occurs in the future. In my opinion, that is why we should test it every way possible.
> 
> 

Sorry. I don't see any value in adding this test.

thanks,
-- Shuah


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-10-23 22:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-22 20:42 [PATCH] Add Selftest to test fork() syscall Shivam Chaudhary
2024-10-23 20:45 ` Shuah Khan
2024-10-23 21:11   ` Shivam Chaudhary
2024-10-23 22:06     ` Shuah Khan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox