edited kernel: linux 6.9.8
machine for building: AMD 9950X, debian 12, linux 6.1.0
Codes
kernel/sys.c
# codes above are omitted.
#endif /* CONFIG_COMPAT */
SYSCALL_DEFINE0(mycall) {
printk(KERN_INFO "Hello Linux 6.9.8 by Konrad\n");
return 0;
}
SYSCALL_DEFINE2(mycopy, const char __user *, s_file, const char __user *, t_file) {
struct kstat k_buf;
char copy_buf[1024];
char s_filename[256], t_filename[256];
struct file *read_file = NULL, *write_file = NULL;
long read_num;
/* Get source and target file name */
read_num = strncpy_from_user(s_filename, s_file, sizeof(s_filename));
if (read_num < 0 || read_num >= sizeof(s_filename)) {
printk(KERN_ERR "Failed to copy source filename from user space\n");
return read_num < 0 ? read_num : -ENAMETOOLONG;
}
read_num = strncpy_from_user(t_filename, t_file, sizeof(t_filename));
if (read_num < 0 || read_num >= sizeof(t_filename)) {
printk(KERN_ERR "Failed to copy target filename from user space\n");
return read_num < 0 ? read_num : -ENAMETOOLONG;
}
/* Print file paths */
printk(KERN_INFO "Source file: %s\n", s_filename);
printk(KERN_INFO "Target file: %s\n", t_filename);
/* Get source file mode */
if (vfs_stat(s_filename, &k_buf) != 0) {
printk(KERN_ERR "Failed to stat source file: %s\n", s_filename);
return -ENOENT;
}
/* Open files */
read_file = filp_open(s_filename, O_RDONLY, 0);
if (IS_ERR(read_file)) {
printk(KERN_ERR "Failed to open source file: %ld\n", PTR_ERR(read_file));
return PTR_ERR(read_file);
}
write_file = filp_open(t_filename, O_WRONLY | O_CREAT | O_TRUNC, k_buf.mode);
if (IS_ERR(write_file)) {
printk(KERN_ERR "Failed to open target file: %ld\n", PTR_ERR(write_file));
filp_close(read_file, NULL);
return PTR_ERR(write_file);
}
/* Do copy */
for (;;) {
read_num = kernel_read(read_file, copy_buf, sizeof(copy_buf), &read_file->f_pos);
if (read_num < 0) {
printk(KERN_ERR "Failed to read from source file: %ld\n", read_num);
filp_close(read_file, NULL);
filp_close(write_file, NULL);
return read_num;
} else if (read_num == 0)
break;
kernel_write(write_file, copy_buf, read_num, &write_file->f_pos);
}
filp_close(read_file, NULL);
filp_close(write_file, NULL);
return 0;
}
arch/x86/entry/syscalls/syscall_64.tbl
Error
The first syscall mycall(462) works well, but the second mycopy(463) for copying files did not work with testing codes below:
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <errno.h>
#define MYCOPY_SYSCALL 463
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <source_file> <destination_file>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (chdir("/usr/src/syscall") != 0) {
perror("Failed to change directory");
exit(EXIT_FAILURE);
}
const char *src_file = argv[1];
const char *dest_file = argv[2];
printf("Source file: %s\n", src_file);
printf("Destination file: %s\n", dest_file);
long result = syscall(MYCOPY_SYSCALL, src_file, dest_file);
if (result == -1) {
printf("Error: errno=%d\n", errno);
perror("Error in mycopy syscall");
exit(EXIT_FAILURE);
} else {
printf("File copied successfully from %s to %s\n", src_file, dest_file);
}
return 0;
}
more running info is listed in the img:
and run with abs path
and the permissions for /usr
are 777
recursively.
according to the error info, it might be vfs_stat()
in kernel/sys.c
, but i do not know the reason, anyone can help ?
/* Get source file mode */
if (vfs_stat(s_filename, &k_buf) != 0) {
printk(KERN_ERR "Failed to stat source file: %s\n", s_filename);
return -ENOENT;
}