From: Stefan Sperling Subject: Re: gotsysd: use PATH_MAX for realpath To: Martijn van Duren , "gameoftrees@openbsd.org" Date: Sun, 11 Oct 2026 10:16:28 +0200 On Sun, Oct 11, 2026 at 09:15:12AM +0200, Stefan Sperling wrote: > For realpath(3) specifically we can work around this problem by passing > NULL for the output buffer, forcing dynamic allocation of the buffer. > We already do this in many cases, all other ones need to be converted > to pass NULL. M gotd/parse.y | 14+ 1- M gotsysd/libexec/gotsys-repo-create/gotsys-repo-create.c | 6+ 2- M gotsysd/parse.y | 27+ 2- 3 files changed, 47 insertions(+), 5 deletions(-) commit - 21052e4a4742a630c583361b135296c061b6ea55 commit + b52e6d7b066bfba53c5b32ed47de6192b9999863 blob - 44d3566166c62cfe42884a1c13490e84ff78e37d blob + 5a674f1db04dd83b19fe9a04e04a96d22e0ad79b --- gotd/parse.y +++ gotd/parse.y @@ -675,13 +675,15 @@ repository : REPOSITORY STRING { repoopts1 : PATH STRING { if (gotd_proc_id == GOTD_PROC_GOTD || gotd_proc_id == GOTD_PROC_GITWRAPPER) { + char *repo_path; if (!got_path_is_absolute($2)) { yyerror("%s: path %s is not absolute", __func__, $2); free($2); YYERROR; } - if (realpath($2, new_repo->path) == NULL) { + repo_path = realpath($2, NULL); + if (repo_path == NULL) { /* * To give admins a chance to create * missing repositories at run-time @@ -707,8 +709,19 @@ repoopts1 : PATH STRING { sizeof(new_repo->path)) >= sizeof(new_repo->path)) { yyerror("path too long"); + free($2); YYERROR; } + } else { + if (strlcpy(new_repo->path, repo_path, + sizeof(new_repo->path)) >= + sizeof(new_repo->path)) { + yyerror("path too long"); + free(repo_path); + free($2); + YYERROR; + } + free(repo_path); } } free($2); blob - d8abeaf2d0a5fc1569525fd0be4ea5b228d59506 blob + b8bf3241a098461bb0a4aea4ad824b5a7cc7a996 --- gotsysd/libexec/gotsys-repo-create/gotsys-repo-create.c +++ gotsysd/libexec/gotsys-repo-create/gotsys-repo-create.c @@ -387,7 +387,7 @@ main(int argc, char **argv) struct gotsysd_imsgev iev; struct event evsigint, evsigterm, evsighup, evsigusr1; struct passwd *pw; - char *username; + char *username, *p; struct stat sb; #if 0 static int attached; @@ -409,8 +409,12 @@ main(int argc, char **argv) errx(1, "usage: %s username repos_path", getprogname()); username = argv[1]; - if (realpath(argv[2], repos_path) == NULL) + p = realpath(argv[2], NULL); + if (p == NULL) err(1, "realpath %s", argv[2]); + if (strlcpy(repos_path, p, sizeof(repos_path)) >= sizeof(repos_path)) + err(1, "path too long: %s", p); + free(p); pw = getpwnam(username); if (pw == NULL) blob - 7b32606e939f3b783aa31c929c68ff3cfc2e0bef blob + 0a0b6f036a36391125168e6314bdc58c360ae83e --- gotsysd/parse.y +++ gotsysd/parse.y @@ -191,11 +191,14 @@ listen_addr : '*' { $$ = NULL; } ; main : LISTEN ON STRING { + char *p; + if (!got_path_is_absolute($3)) yyerror("bad unix socket path \"%s\": " "must be an absolute path", $3); - if (realpath($3, gotsysd->unix_socket_path) == NULL) { + p = realpath($3, NULL); + if (p == NULL) { if (errno != ENOENT && errno != EACCES) { yyerror("realpath %s: %s", $3, strerror(errno)); @@ -211,6 +214,17 @@ main : LISTEN ON STRING { free($3); YYERROR; } + } else { + if (strlcpy(gotsysd->unix_socket_path, p, + sizeof(gotsysd->unix_socket_path)) >= + sizeof(gotsysd->unix_socket_path)) { + yyerror("unix socket path too long: %s", + p); + free(p); + free($3); + YYERROR; + } + free(p); } free($3); } @@ -235,6 +249,8 @@ main : LISTEN ON STRING { free($3); } | REPOSITORY DIRECTORY STRING { + char *p; + if (!got_path_is_absolute($3)) { yyerror("bad path \"%s\": " "must be an absolute path", $3); @@ -242,11 +258,20 @@ main : LISTEN ON STRING { YYERROR; } - if (realpath($3, gotsysd->repos_path) == NULL) { + p = realpath($3, NULL); + if (p == NULL) { yyerror("realpath %s: %s", $3, strerror(errno)); free($3); YYERROR; } + if (strlcpy(gotsysd->repos_path, p, + sizeof(gotsysd->repos_path)) >= + sizeof(gotsysd->repos_path)) { + yyerror("repository path too long: %s", p); + free(p); + free($3); + YYERROR; + } free($3); } | UID RANGE NUMBER NUMBER {