Created
June 1, 2025 00:40
-
-
Save berdario/740bdeefea62c373d97931e2d4c51be5 to your computer and use it in GitHub Desktop.
openat & fchmod issue within child processes and smb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE // Required for clone() | |
#include <sched.h> // For clone() | |
#include <stdio.h> // For printf, perror, fopen, fclose, remove | |
#include <stdlib.h> // For malloc, free, EXIT_SUCCESS, EXIT_FAILURE | |
#include <unistd.h> // For getpid, close, syscall | |
#include <sys/wait.h> // For waitpid() | |
#include <sys/syscall.h> // For SYS_getpid | |
#include <fcntl.h> // For openat(), AT_FDCWD, O_RDWR | |
#include <sys/stat.h> // For fchmod(), S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH | |
#include <signal.h> // For sigaction, SIGCHLD, SIG_DFL, SIG_IGN | |
#define STACK_SIZE (1024 * 1024) // 1MB stack for the child process | |
static int child_func(void *arg) { | |
printf("Child: Process started, PID (via syscall(SYS_getpid)) = %ld\n", (long)syscall(SYS_getpid)); | |
printf("Child: UID = %d, GID = %d\n", getuid(), getgid()); | |
int fd; | |
printf("Child: Attempting to open 'foo' using openat()...\n"); | |
fd = openat(AT_FDCWD, "foo", O_RDWR | O_CREAT); | |
if (fd == -1) { | |
perror("Child: openat failed for 'foo'"); | |
return 1; | |
} | |
printf("Child: 'foo' opened successfully via openat(), file descriptor = %d\n", fd); | |
printf("Child: Attempting to change permissions of 'foo' to 0644 using fchmod()...\n"); | |
if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { | |
perror("Child: fchmod failed for 'foo'"); | |
close(fd); | |
return 1; | |
} | |
printf("Child: Permissions of 'foo' changed successfully to 0644.\n"); | |
if (close(fd) == -1) { | |
perror("Child: close failed for 'foo'"); | |
return 1; | |
} | |
printf("Child: 'foo' closed.\n"); | |
printf("Child: Exiting successfully.\n"); | |
return 0; | |
} | |
int main() { | |
void *child_stack; | |
pid_t child_pid; | |
printf("Parent: Process started, PID = %ld\n", (long)getpid()); | |
child_stack = malloc(STACK_SIZE); | |
if (child_stack == NULL) { | |
perror("Parent: Failed to allocate stack for child process"); | |
remove("foo"); | |
return EXIT_FAILURE; | |
} | |
void *stack_top = child_stack + STACK_SIZE; | |
printf("Parent: Attempting to clone a new process...\n"); | |
child_pid = clone(child_func, stack_top, CLONE_VM | SIGCHLD, NULL); | |
if (child_pid == -1) { | |
perror("Parent: clone failed"); | |
free(child_stack); | |
remove("foo"); | |
return EXIT_FAILURE; | |
} | |
printf("Parent: clone() successful. Child process PID = %ld\n", (long)child_pid); | |
printf("Parent: Waiting for child process to terminate...\n"); | |
int status; | |
if (waitpid(child_pid, &status, 0) == -1) { | |
perror("Parent: waitpid failed"); | |
} else { | |
if (WIFEXITED(status)) { | |
printf("Parent: Child process exited with status %d.\n", WEXITSTATUS(status)); | |
} else if (WIFSIGNALED(status)) { | |
printf("Parent: Child process killed by signal %d.\n", WTERMSIG(status)); | |
} else { | |
printf("Parent: Child process ended with unknown status.\n"); | |
} | |
} | |
// Let's do it again, if fchmod failed, the file had still been created, which can change the behavior of the 2nd child being cloned. | |
printf("Parent: Attempting to clone a new process...\n"); | |
child_pid = clone(child_func, stack_top, CLONE_VM | SIGCHLD, NULL); | |
if (child_pid == -1) { | |
perror("Parent: clone failed"); | |
free(child_stack); | |
remove("foo"); | |
return EXIT_FAILURE; | |
} | |
printf("Parent: clone() successful. Child process PID = %ld\n", (long)child_pid); | |
printf("Parent: Waiting for child process to terminate...\n"); | |
if (waitpid(child_pid, &status, 0) == -1) { | |
perror("Parent: waitpid failed"); | |
} else { | |
if (WIFEXITED(status)) { | |
printf("Parent: Child process exited with status %d.\n", WEXITSTATUS(status)); | |
} else if (WIFSIGNALED(status)) { | |
printf("Parent: Child process killed by signal %d.\n", WTERMSIG(status)); | |
} else { | |
printf("Parent: Child process ended with unknown status.\n"); | |
} | |
} | |
free(child_stack); | |
printf("Parent: Child stack memory freed.\n"); | |
if (remove("foo") == 0) { | |
printf("Parent: 'foo' file removed successfully.\n"); | |
} else { | |
perror("Parent: Failed to remove 'foo' file"); | |
} | |
printf("Parent: Exiting.\n"); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment