Skip to content

Commit aa8c100

Browse files
Fix VFS path normalization and *at syscall path handling
1 parent 28a0443 commit aa8c100

6 files changed

Lines changed: 82 additions & 38 deletions

File tree

source/includes/filesystems/vfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#ifndef VFS_H
1212
#define VFS_H
1313

14+
#include <stddef.h>
1415
#include <filesystems/fat16.h>
1516
#include <filesystems/fat32.h>
1617
#include <filesystems/iso9660.h>
@@ -134,5 +135,6 @@ int vfs_unlink(const char* path);
134135
const char* vfs_getcwd();
135136

136137
const char* vfs_basename(const char* path);
138+
int vfs_normalize_path(const char* in, char* out, size_t out_sz);
137139

138140
#endif // VFS_H

source/includes/stream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ int fd_close(int fd);
5252
int fd_dup(int oldfd);
5353
int fd_dup2(int oldfd, int newfd);
5454
int fd_flags(int fd);
55+
const char* fd_get_path(int fd);
5556
uint32_t fd_file_size(int fd);
5657
uint32_t* fd_pos_ptr(int fd);
5758

source/kernel/C/filesystems/fat16.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,6 @@ int fat16_read(fat16_file_t* f, uint8_t* out, uint32_t size) {
516516
f->fs->bs.sectors_per_cluster * 512;
517517
uint16_t cluster = f->entry.first_cluster;
518518

519-
printf("READ CALLED: pos=%u size=%u\n", f->pos, size);
520-
521519
if (cluster_size == 0 || cluster < 2)
522520
return 0;
523521

source/kernel/C/filesystems/vfs.c

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,11 @@ int vfs_resolve_mount(const char* path, vfs_mount_res_t* out) {
7171
return 0;
7272
}
7373

74-
static void vfs_normalize_path(const char* in, char* out) {
75-
memset(out, 0, 256);
74+
int vfs_normalize_path(const char* in, char* out, size_t out_sz) {
75+
if (!in || !out || out_sz < 2)
76+
return -1;
77+
78+
memset(out, 0, out_sz);
7679
char tmp[256];
7780

7881
// Start with absolute or relative
@@ -113,16 +116,17 @@ static void vfs_normalize_path(const char* in, char* out) {
113116

114117
// Copy next component
115118
while (*p && *p != '/') {
116-
if (oi >= 255) {
117-
out[255] = '\0';
118-
return;
119+
if ((size_t)oi >= out_sz - 1) {
120+
out[out_sz - 1] = '\0';
121+
return -2;
119122
}
120123
out[oi++] = *p++;
121124
}
122125
}
123126

124127
if (oi == 0) out[oi++] = '/';
125128
out[oi] = '\0';
129+
return 0;
126130
}
127131

128132
int vfs_read(vfs_file_t* file, uint8_t* buf, uint32_t size)
@@ -215,7 +219,8 @@ int vfs_ls(const char* path)
215219
}
216220

217221
char norm[256];
218-
vfs_normalize_path(path, norm);
222+
if (vfs_normalize_path(path, norm, sizeof(norm)) != 0)
223+
return -1;
219224

220225
vfs_mount_res_t res;
221226
if (vfs_resolve_mount(norm, &res) != 0)
@@ -322,14 +327,13 @@ int vfs_open(const char* path, int flags, vfs_file_t* out)
322327
}
323328

324329
char norm[256];
325-
vfs_normalize_path(path, norm);
330+
if (vfs_normalize_path(path, norm, sizeof(norm)) != 0)
331+
return -1;
326332

327333
vfs_mount_res_t res;
328334
if (vfs_resolve_mount(norm, &res) != 0)
329335
return -2;
330336

331-
printf("[OPEN] %s", norm);
332-
333337
if (res.mnt->type == FS_PROC) {
334338
strncpy(out->rel_path, res.rel_path, sizeof(out->rel_path));
335339
out->mnt = res.mnt;
@@ -454,7 +458,8 @@ int vfs_mkdir(const char* path) {
454458
}
455459

456460
char norm[256];
457-
vfs_normalize_path(path, norm);
461+
if (vfs_normalize_path(path, norm, sizeof(norm)) != 0)
462+
return -1;
458463

459464
vfs_mount_res_t res;
460465
if (vfs_resolve_mount(norm, &res) != 0) return -1;
@@ -477,7 +482,8 @@ int vfs_mkdir(const char* path) {
477482
int vfs_rm_recursive(const char* path)
478483
{
479484
char norm[256];
480-
vfs_normalize_path(path, norm);
485+
if (vfs_normalize_path(path, norm, sizeof(norm)) != 0)
486+
return -1;
481487

482488
vfs_mount_res_t res;
483489
if (vfs_resolve_mount(norm, &res) != 0)
@@ -545,7 +551,8 @@ int vfs_cd(const char* path)
545551
}
546552

547553
char norm[256];
548-
vfs_normalize_path(path, norm);
554+
if (vfs_normalize_path(path, norm, sizeof(norm)) != 0)
555+
return -1;
549556

550557
vfs_mount_res_t res;
551558
if (vfs_resolve_mount(norm, &res) != 0)
@@ -633,7 +640,8 @@ int vfs_create_path(const char* path, uint8_t attr) {
633640
}
634641

635642
char norm[256];
636-
vfs_normalize_path(path, norm);
643+
if (vfs_normalize_path(path, norm, sizeof(norm)) != 0)
644+
return -1;
637645

638646
vfs_mount_res_t res;
639647
if (vfs_resolve_mount(norm, &res) != 0) return -1;
@@ -659,7 +667,8 @@ int vfs_unlink(const char* path)
659667
}
660668
/* Normalize */
661669
char norm[256];
662-
vfs_normalize_path(path, norm);
670+
if (vfs_normalize_path(path, norm, sizeof(norm)) != 0)
671+
return -1;
663672

664673
/* Resolve mount */
665674
vfs_mount_res_t res;
@@ -717,8 +726,10 @@ int vfs_unlink(const char* path)
717726
int vfs_mv(const char* src, const char* dst)
718727
{
719728
char src_norm[256], dst_norm[256];
720-
vfs_normalize_path(src, src_norm);
721-
vfs_normalize_path(dst, dst_norm);
729+
if (vfs_normalize_path(src, src_norm, sizeof(src_norm)) != 0)
730+
return -1;
731+
if (vfs_normalize_path(dst, dst_norm, sizeof(dst_norm)) != 0)
732+
return -1;
722733

723734
vfs_mount_res_t src_res, dst_res;
724735
if (vfs_resolve_mount(src_norm, &src_res) != 0) return -1;
@@ -825,4 +836,4 @@ const char* vfs_basename(const char* path) {
825836
path++;
826837
}
827838
return last;
828-
}
839+
}

source/kernel/C/stream.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ typedef struct {
3030
int flags;
3131
vfs_file_t* file;
3232
vfs_file_t storage;
33+
char path[256];
3334
} fd_object_t;
3435

3536
typedef struct {
@@ -51,6 +52,7 @@ static fd_object_t* fd_object_alloc(vfs_file_t* file, bool owns_file, int flags)
5152
fd_objects[i].owns_file = owns_file;
5253
fd_objects[i].flags = flags;
5354
fd_objects[i].file = file;
55+
memset(fd_objects[i].path, 0, sizeof(fd_objects[i].path));
5456

5557
if (!owns_file)
5658
memset(&fd_objects[i].storage, 0, sizeof(vfs_file_t));
@@ -206,6 +208,8 @@ int fd_open(const char* path, int flags)
206208

207209
object->file = &object->storage;
208210
memset(object->file, 0, sizeof(vfs_file_t));
211+
if (path)
212+
vfs_normalize_path(path, object->path, sizeof(object->path));
209213

210214
if (vfs_open(path, flags, object->file) != 0) {
211215
fd_object_release(object);
@@ -265,6 +269,17 @@ int fd_flags(int fd)
265269
return fd_table[fd].object->flags;
266270
}
267271

272+
const char* fd_get_path(int fd)
273+
{
274+
if (!fd_valid(fd) || !fd_table[fd].object)
275+
return NULL;
276+
277+
if (fd_table[fd].object->path[0] == '\0')
278+
return NULL;
279+
280+
return fd_table[fd].object->path;
281+
}
282+
268283
uint32_t fd_file_size(int fd)
269284
{
270285
vfs_file_t* file = fd_get_file(fd);

source/kernel/C/syscalls.c

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -328,17 +328,37 @@ static void fill_stat_from_info(linux_stat_t* st, const vfs_stat_info_t* info) {
328328
st->st_blocks = (info->size + 511) / 512;
329329
}
330330

331-
static bool fill_vfs_stat_for_path(const char* path, vfs_stat_info_t* info) {
331+
static bool resolve_path_at(int dirfd, const char* path, char* out, size_t out_sz) {
332+
if (!path || !out)
333+
return false;
334+
335+
if (path[0] == '/')
336+
return vfs_normalize_path(path, out, out_sz) == 0;
337+
338+
if (dirfd == LINUX_AT_FDCWD || dirfd == 0)
339+
return vfs_normalize_path(path, out, out_sz) == 0;
340+
341+
if (!fd_valid(dirfd))
342+
return false;
343+
344+
const char* base = fd_get_path(dirfd);
345+
if (!base)
346+
base = vfs_getcwd();
347+
348+
char joined[512];
349+
snprintf(joined, sizeof(joined), "%s/%s", base, path);
350+
return vfs_normalize_path(joined, out, out_sz) == 0;
351+
}
352+
353+
static bool fill_vfs_stat_for_path_at(int dirfd, const char* path, vfs_stat_info_t* info) {
332354
if (!path || !info)
333355
return false;
334356

335357
memset(info, 0, sizeof(*info));
336358

337359
char norm[256];
338-
if (path[0] == '/')
339-
snprintf(norm, sizeof(norm), "%s", path);
340-
else
341-
snprintf(norm, sizeof(norm), "%s/%s", vfs_getcwd(), path);
360+
if (!resolve_path_at(dirfd, path, norm, sizeof(norm)))
361+
return false;
342362

343363
if (strcmp(norm, "/") == 0) {
344364
info->exists = true;
@@ -678,10 +698,11 @@ static int64 sys_open_common(int dirfd, const char* path, int flags, int mode) {
678698
if (path == NULL)
679699
return -LINUX_EINVAL;
680700

681-
if (dirfd != LINUX_AT_FDCWD && dirfd != 0)
701+
char resolved_path[256];
702+
if (!resolve_path_at(dirfd, path, resolved_path, sizeof(resolved_path)))
682703
return -LINUX_EINVAL;
683704

684-
int fd = fd_open(path, linux_flags_to_vfs(flags));
705+
int fd = fd_open(resolved_path, linux_flags_to_vfs(flags));
685706
if (fd == -1)
686707
return -LINUX_ENFILE;
687708

@@ -714,7 +735,7 @@ static int64 sys_stat(const char* path, linux_stat_t* st) {
714735
return -LINUX_EINVAL;
715736

716737
vfs_stat_info_t info;
717-
if (!fill_vfs_stat_for_path(path, &info))
738+
if (!fill_vfs_stat_for_path_at(LINUX_AT_FDCWD, path, &info))
718739
return -LINUX_ENOENT;
719740

720741
fill_stat_from_info(st, &info);
@@ -733,11 +754,8 @@ static int64 sys_newfstatat(int dirfd, const char* path, linux_stat_t* st, int f
733754

734755
if (!path)
735756
return -LINUX_EINVAL;
736-
if (dirfd != LINUX_AT_FDCWD && dirfd != 0)
737-
return -LINUX_EINVAL;
738-
739757
vfs_stat_info_t info;
740-
if (!fill_vfs_stat_for_path(path, &info))
758+
if (!fill_vfs_stat_for_path_at(dirfd, path, &info))
741759
return -LINUX_ENOENT;
742760
fill_stat_from_info(st, &info);
743761
return 0;
@@ -894,11 +912,8 @@ static int64 sys_access_common(int dirfd, const char* path, int mode) {
894912
(void)mode;
895913
if (!path)
896914
return -LINUX_EINVAL;
897-
if (dirfd != LINUX_AT_FDCWD && dirfd != 0)
898-
return -LINUX_EINVAL;
899-
900915
vfs_stat_info_t info;
901-
return fill_vfs_stat_for_path(path, &info) ? 0 : -LINUX_ENOENT;
916+
return fill_vfs_stat_for_path_at(dirfd, path, &info) ? 0 : -LINUX_ENOENT;
902917
}
903918

904919
static int64 sys_lseek(uint64_t fd, int64_t offset, uint64_t whence) {
@@ -976,12 +991,14 @@ static int64 sys_chdir(const char* path) {
976991
}
977992

978993
static int64 sys_readlinkat(int dirfd, const char* path, char* buf, uint64_t bufsiz) {
979-
if (dirfd != LINUX_AT_FDCWD && dirfd != 0)
980-
return -LINUX_EINVAL;
981994
if (!path)
982995
return -LINUX_EINVAL;
983996

984-
if (strcmp(path, "/proc/self/exe") == 0 || strcmp(path, "self/exe") == 0)
997+
char resolved_path[256];
998+
if (!resolve_path_at(dirfd, path, resolved_path, sizeof(resolved_path)))
999+
return -LINUX_EINVAL;
1000+
1001+
if (strcmp(resolved_path, "/proc/self/exe") == 0 || strcmp(resolved_path, "self/exe") == 0)
9851002
return copy_readlink_result(current_exec_path, buf, bufsiz);
9861003

9871004
return -LINUX_ENOENT;

0 commit comments

Comments
 (0)