From 96f556756f7a64809ffb3c6f82ef7f31e7749443 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Tue, 28 Apr 2026 20:56:04 +0200 Subject: [PATCH] Apply patch: ncpfs-2.2.6-mount-issue-ver2.patch --- .../ncpfs-2.2.6-mount-issue-ver2.patch | 329 ++++++++++++++++++ sutil/ncpm_common.c | 22 +- sutil/ncpmount.c | 10 +- sutil/ncpumount.c | 196 ++++++++++- 4 files changed, 545 insertions(+), 12 deletions(-) create mode 100644 .patches/ncpfs-2.2.6-r6/ncpfs-2.2.6-mount-issue-ver2.patch diff --git a/.patches/ncpfs-2.2.6-r6/ncpfs-2.2.6-mount-issue-ver2.patch b/.patches/ncpfs-2.2.6-r6/ncpfs-2.2.6-mount-issue-ver2.patch new file mode 100644 index 0000000..65ea688 --- /dev/null +++ b/.patches/ncpfs-2.2.6-r6/ncpfs-2.2.6-mount-issue-ver2.patch @@ -0,0 +1,329 @@ +Index: ncpfs-2.2.6/sutil/ncpm_common.c +=================================================================== +--- ncpfs-2.2.6.orig/sutil/ncpm_common.c ++++ ncpfs-2.2.6/sutil/ncpm_common.c +@@ -444,7 +444,7 @@ static int ncp_mount_v2(const char* moun + } + datav2.file_mode = data->file_mode; + datav2.dir_mode = data->dir_mode; +- err = proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav2); ++ err = proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*) &datav2); + if (err) + return errno; + return 0; +@@ -508,7 +508,7 @@ static int ncp_mount_v3(const char* moun + exit(0); /* Should not return from process_connection */ + } + close(pp[0]); +- err=proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav3); ++ err=proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*) &datav3); + if (err) { + err = errno; + /* Mount unsuccesful so we have to kill daemon */ +@@ -559,7 +559,7 @@ static int ncp_mount_v4(const char* moun + sprintf(mountopts, "version=%u,flags=%u,owner=%u,uid=%u,gid=%u,mode=%u,dirmode=%u,timeout=%u,retry=%u,wdogpid=%u,ncpfd=%u,infofd=%u", + NCP_MOUNT_VERSION_V5, ncpflags, data->mounted_uid, data->uid, data->gid, data->file_mode, + data->dir_mode, data->time_out, data->retry_count, wdog_pid, data->ncp_fd, pp[1]); +- err=proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, mountopts); ++ err=proc_ncpm_mount(mount_name, ".", "ncpfs", flags, mountopts); + } else { + err=-1; + } +@@ -577,7 +577,7 @@ static int ncp_mount_v4(const char* moun + datav4.file_mode = data->file_mode; + datav4.dir_mode = data->dir_mode; + datav4.wdog_pid = wdog_pid; +- err = proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*)&datav4); ++ err = proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*)&datav4); + if (err) { + err = errno; + /* Mount unsuccesful so we have to kill daemon */ +@@ -1395,6 +1395,17 @@ process_connection (const struct ncp_mou + } + #endif /* MOUNT3 */ + ++static int check_name(const char *name) ++{ ++ char *s; ++ for (s = "\n\t\\"; *s; s++) { ++ if (strchr(name, *s)) { ++ return -1; ++ } ++ } ++ return 0; ++} ++ + static const struct smntflags { + unsigned int flag; + const char* name; +@@ -1416,6 +1427,9 @@ void add_mnt_entry(char* mount_name, cha + int fd; + FILE* mtab; + ++ if (check_name(mount_name) == -1 || check_name(mpnt) == -1) ++ errexit(107, _("Illegal character in mount entry\n")); ++ + ment.mnt_fsname = mount_name; + ment.mnt_dir = mpnt; + ment.mnt_type = (char*)"ncpfs"; +Index: ncpfs-2.2.6/sutil/ncpmount.c +=================================================================== +--- ncpfs-2.2.6.orig/sutil/ncpmount.c ++++ ncpfs-2.2.6/sutil/ncpmount.c +@@ -359,11 +359,17 @@ main(int argc, char *argv[]) + usage(); + return -1; + } ++ + realpath(argv[optind], mount_point); + +- if (stat(mount_point, &st) == -1) ++ if (chdir(mount_point)) ++ { ++ errexit(31, _("Could not change directory into mount target %s: %s\n"), ++ mount_point, strerror(errno)); ++ } ++ if (stat(".", &st) == -1) + { +- errexit(31, _("Could not find mount point %s: %s\n"), ++ errexit(31, _("Mount point %s does not exist: %s\n"), + mount_point, strerror(errno)); + } + if (mount_ok(&st) != 0) +Index: ncpfs-2.2.6/sutil/ncpumount.c +=================================================================== +--- ncpfs-2.2.6.orig/sutil/ncpumount.c ++++ ncpfs-2.2.6/sutil/ncpumount.c +@@ -61,6 +61,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -70,10 +72,19 @@ + #include + #include + ++#include ++ + #include "private/libintl.h" + + #define _(X) X + ++#ifndef MS_REC ++#define MS_REC 16384 ++#endif ++#ifndef MS_SLAVE ++#define MS_SLAVE (1<<19) ++#endif ++ + static char *progname; + static int is_ncplogout = 0; + +@@ -229,11 +240,188 @@ static int clearMtab (const char* mount_ + return err; + } + ++ ++int ncp_mnt_umount(const char *abs_mnt, const char *rel_mnt) ++{ ++ if (umount(rel_mnt) != 0) { ++ eprintf(_("Could not umount %s: %s\n"), ++ abs_mnt, strerror(errno)); ++ return -1; ++ } ++ return 0; ++} ++ ++ ++static int check_is_mount_child(void *p) ++{ ++ const char **a = p; ++ const char *last = a[0]; ++ const char *mnt = a[1]; ++ int res; ++ const char *procmounts = "/proc/mounts"; ++ int found; ++ FILE *fp; ++ struct mntent *entp; ++ ++ res = mount("", "/", "", MS_SLAVE | MS_REC, NULL); ++ if (res == -1) { ++ eprintf(_("Failed to mark mounts slave: %s\n"), ++ strerror(errno)); ++ return 1; ++ } ++ ++ res = mount(".", "/tmp", "", MS_BIND | MS_REC, NULL); ++ if (res == -1) { ++ eprintf(_("Failed to bind parent to /tmp: %s\n"), ++ strerror(errno)); ++ return 1; ++ } ++ ++ fp = setmntent(procmounts, "r"); ++ if (fp == NULL) { ++ eprintf(_("Failed to open %s: %s\n"), ++ procmounts, strerror(errno)); ++ return 1; ++ } ++ ++ found = 0; ++ while ((entp = getmntent(fp)) != NULL) { ++ if (strncmp(entp->mnt_dir, "/tmp/", 5) == 0 && ++ strcmp(entp->mnt_dir + 5, last) == 0) { ++ found = 1; ++ break; ++ } ++ } ++ endmntent(fp); ++ ++ if (!found) { ++ eprintf(_("%s not mounted\n"), mnt); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++ ++static int check_is_mount(const char *last, const char *mnt) ++{ ++ char buf[131072]; ++ pid_t pid, p; ++ int status; ++ const char *a[2] = { last, mnt }; ++ ++ pid = clone(check_is_mount_child, buf + 65536, CLONE_NEWNS, (void *) a); ++ if (pid == (pid_t) -1) { ++ eprintf(_("Failed to clone namespace: %s\n"), ++ strerror(errno)); ++ return -1; ++ } ++ p = waitpid(pid, &status, __WCLONE); ++ if (p == (pid_t) -1) { ++ eprintf(_("Waitpid failed: %s\n"), ++ strerror(errno)); ++ return -1; ++ } ++ if (!WIFEXITED(status)) { ++ eprintf(_("Child terminated abnormally (status %i)\n"), ++ status); ++ return -1; ++ } ++ if (WEXITSTATUS(status) != 0) ++ return -1; ++ ++ return 0; ++} ++ ++ ++static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) ++{ ++ char *tmp; ++ const char *parent; ++ char buf[PATH_MAX]; ++ int res; ++ ++ tmp = strrchr(copy, '/'); ++ if (tmp == NULL || tmp[1] == '\0') { ++ eprintf(_("Internal error: invalid abs path: <%s>\n"), ++ copy); ++ return -1; ++ } ++ if (tmp != copy) { ++ *tmp = '\0'; ++ parent = copy; ++ *lastp = tmp + 1; ++ } else if (tmp[1] != '\0') { ++ *lastp = tmp + 1; ++ parent = "/"; ++ } else { ++ *lastp = "."; ++ parent = "/"; ++ } ++ *currdir_fd = open(".", O_RDONLY); ++ if (*currdir_fd == -1) { ++ eprintf(_("Failed to open current directory: %s\n"), ++ strerror(errno)); ++ return -1; ++ } ++ res = chdir(parent); ++ if (res == -1) { ++ eprintf(_("Failed to chdir to %s: %s\n"), ++ parent, strerror(errno)); ++ return -1; ++ } ++ if (getcwd(buf, sizeof(buf)) == NULL) { ++ eprintf(_("Failed to obtain current directory: %s\n"), ++ strerror(errno)); ++ return -1; ++ } ++ if (strcmp(buf, parent) != 0) { ++ eprintf(_("Mountpoint moved (%s -> %s)\n"), ++ parent, buf); ++ return -1; ++ ++ } ++ ++ return 0; ++} ++ ++ ++static int unmount_ncp(const char *mount_point) ++{ ++ int currdir_fd = -1; ++ char *copy; ++ const char *last; ++ int res; ++ ++ copy = strdup(mount_point); ++ if (copy == NULL) { ++ eprintf(_("Failed to allocate memory\n")); ++ return -1; ++ } ++ res = chdir_to_parent(copy, &last, &currdir_fd); ++ if (res == -1) ++ goto out; ++ res = check_is_mount(last, mount_point); ++ if (res == -1) ++ goto out; ++ res = ncp_mnt_umount(mount_point, last); ++ ++out: ++ free(copy); ++ if (currdir_fd != -1) { ++ fchdir(currdir_fd); ++ close(currdir_fd); ++ } ++ ++ return res; ++} ++ + static int + do_umount(const char *mount_point) + { + int fid = open(mount_point, O_RDONLY, 0); + uid_t mount_uid; ++ int res; + + if (fid == -1) { + eprintf(_("Could not open %s: %s\n"), +@@ -253,12 +441,8 @@ do_umount(const char *mount_point) + return -1; + } + close(fid); +- if (umount(mount_point) != 0) { +- eprintf(_("Could not umount %s: %s\n"), +- mount_point, strerror(errno)); +- return -1; +- } +- return 0; ++ res = unmount_ncp(mount_point); ++ return res; + } + + diff --git a/sutil/ncpm_common.c b/sutil/ncpm_common.c index 0f0957f..b361f47 100644 --- a/sutil/ncpm_common.c +++ b/sutil/ncpm_common.c @@ -444,7 +444,7 @@ static int ncp_mount_v2(const char* mount_name, unsigned long flags, const struc } datav2.file_mode = data->file_mode; datav2.dir_mode = data->dir_mode; - err = proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav2); + err = proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*) &datav2); if (err) return errno; return 0; @@ -508,7 +508,7 @@ static int ncp_mount_v3(const char* mount_name, unsigned long flags, const struc exit(0); /* Should not return from process_connection */ } close(pp[0]); - err=proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*) &datav3); + err=proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*) &datav3); if (err) { err = errno; /* Mount unsuccesful so we have to kill daemon */ @@ -559,7 +559,7 @@ static int ncp_mount_v4(const char* mount_name, unsigned long flags, struct ncp_ sprintf(mountopts, "version=%u,flags=%u,owner=%u,uid=%u,gid=%u,mode=%u,dirmode=%u,timeout=%u,retry=%u,wdogpid=%u,ncpfd=%u,infofd=%u", NCP_MOUNT_VERSION_V5, ncpflags, data->mounted_uid, data->uid, data->gid, data->file_mode, data->dir_mode, data->time_out, data->retry_count, wdog_pid, data->ncp_fd, pp[1]); - err=proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, mountopts); + err=proc_ncpm_mount(mount_name, ".", "ncpfs", flags, mountopts); } else { err=-1; } @@ -577,7 +577,7 @@ static int ncp_mount_v4(const char* mount_name, unsigned long flags, struct ncp_ datav4.file_mode = data->file_mode; datav4.dir_mode = data->dir_mode; datav4.wdog_pid = wdog_pid; - err = proc_ncpm_mount(mount_name, data->mount_point, "ncpfs", flags, (void*)&datav4); + err = proc_ncpm_mount(mount_name, ".", "ncpfs", flags, (void*)&datav4); if (err) { err = errno; /* Mount unsuccesful so we have to kill daemon */ @@ -1395,6 +1395,17 @@ process_connection (const struct ncp_mount_data_independent* mnt, int pipe_fd) } #endif /* MOUNT3 */ +static int check_name(const char *name) +{ + char *s; + for (s = "\n\t\\"; *s; s++) { + if (strchr(name, *s)) { + return -1; + } + } + return 0; +} + static const struct smntflags { unsigned int flag; const char* name; @@ -1416,6 +1427,9 @@ void add_mnt_entry(char* mount_name, char* mpnt, unsigned long flags) { int fd; FILE* mtab; + if (check_name(mount_name) == -1 || check_name(mpnt) == -1) + errexit(107, _("Illegal character in mount entry\n")); + ment.mnt_fsname = mount_name; ment.mnt_dir = mpnt; ment.mnt_type = (char*)"ncpfs"; diff --git a/sutil/ncpmount.c b/sutil/ncpmount.c index 0b8a717..247ded0 100644 --- a/sutil/ncpmount.c +++ b/sutil/ncpmount.c @@ -359,11 +359,17 @@ main(int argc, char *argv[]) usage(); return -1; } + realpath(argv[optind], mount_point); - if (stat(mount_point, &st) == -1) + if (chdir(mount_point)) { - errexit(31, _("Could not find mount point %s: %s\n"), + errexit(31, _("Could not change directory into mount target %s: %s\n"), + mount_point, strerror(errno)); + } + if (stat(".", &st) == -1) + { + errexit(31, _("Mount point %s does not exist: %s\n"), mount_point, strerror(errno)); } if (mount_ok(&st) != 0) diff --git a/sutil/ncpumount.c b/sutil/ncpumount.c index 1efb1ac..412e881 100644 --- a/sutil/ncpumount.c +++ b/sutil/ncpumount.c @@ -61,6 +61,8 @@ #include #include #include +#include +#include #include #include @@ -70,10 +72,19 @@ #include #include +#include + #include "private/libintl.h" #define _(X) X +#ifndef MS_REC +#define MS_REC 16384 +#endif +#ifndef MS_SLAVE +#define MS_SLAVE (1<<19) +#endif + static char *progname; static int is_ncplogout = 0; @@ -229,11 +240,188 @@ static int clearMtab (const char* mount_points[], unsigned int numEntries) { return err; } + +int ncp_mnt_umount(const char *abs_mnt, const char *rel_mnt) +{ + if (umount(rel_mnt) != 0) { + eprintf(_("Could not umount %s: %s\n"), + abs_mnt, strerror(errno)); + return -1; + } + return 0; +} + + +static int check_is_mount_child(void *p) +{ + const char **a = p; + const char *last = a[0]; + const char *mnt = a[1]; + int res; + const char *procmounts = "/proc/mounts"; + int found; + FILE *fp; + struct mntent *entp; + + res = mount("", "/", "", MS_SLAVE | MS_REC, NULL); + if (res == -1) { + eprintf(_("Failed to mark mounts slave: %s\n"), + strerror(errno)); + return 1; + } + + res = mount(".", "/tmp", "", MS_BIND | MS_REC, NULL); + if (res == -1) { + eprintf(_("Failed to bind parent to /tmp: %s\n"), + strerror(errno)); + return 1; + } + + fp = setmntent(procmounts, "r"); + if (fp == NULL) { + eprintf(_("Failed to open %s: %s\n"), + procmounts, strerror(errno)); + return 1; + } + + found = 0; + while ((entp = getmntent(fp)) != NULL) { + if (strncmp(entp->mnt_dir, "/tmp/", 5) == 0 && + strcmp(entp->mnt_dir + 5, last) == 0) { + found = 1; + break; + } + } + endmntent(fp); + + if (!found) { + eprintf(_("%s not mounted\n"), mnt); + return 1; + } + + return 0; +} + + +static int check_is_mount(const char *last, const char *mnt) +{ + char buf[131072]; + pid_t pid, p; + int status; + const char *a[2] = { last, mnt }; + + pid = clone(check_is_mount_child, buf + 65536, CLONE_NEWNS, (void *) a); + if (pid == (pid_t) -1) { + eprintf(_("Failed to clone namespace: %s\n"), + strerror(errno)); + return -1; + } + p = waitpid(pid, &status, __WCLONE); + if (p == (pid_t) -1) { + eprintf(_("Waitpid failed: %s\n"), + strerror(errno)); + return -1; + } + if (!WIFEXITED(status)) { + eprintf(_("Child terminated abnormally (status %i)\n"), + status); + return -1; + } + if (WEXITSTATUS(status) != 0) + return -1; + + return 0; +} + + +static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) +{ + char *tmp; + const char *parent; + char buf[PATH_MAX]; + int res; + + tmp = strrchr(copy, '/'); + if (tmp == NULL || tmp[1] == '\0') { + eprintf(_("Internal error: invalid abs path: <%s>\n"), + copy); + return -1; + } + if (tmp != copy) { + *tmp = '\0'; + parent = copy; + *lastp = tmp + 1; + } else if (tmp[1] != '\0') { + *lastp = tmp + 1; + parent = "/"; + } else { + *lastp = "."; + parent = "/"; + } + *currdir_fd = open(".", O_RDONLY); + if (*currdir_fd == -1) { + eprintf(_("Failed to open current directory: %s\n"), + strerror(errno)); + return -1; + } + res = chdir(parent); + if (res == -1) { + eprintf(_("Failed to chdir to %s: %s\n"), + parent, strerror(errno)); + return -1; + } + if (getcwd(buf, sizeof(buf)) == NULL) { + eprintf(_("Failed to obtain current directory: %s\n"), + strerror(errno)); + return -1; + } + if (strcmp(buf, parent) != 0) { + eprintf(_("Mountpoint moved (%s -> %s)\n"), + parent, buf); + return -1; + + } + + return 0; +} + + +static int unmount_ncp(const char *mount_point) +{ + int currdir_fd = -1; + char *copy; + const char *last; + int res; + + copy = strdup(mount_point); + if (copy == NULL) { + eprintf(_("Failed to allocate memory\n")); + return -1; + } + res = chdir_to_parent(copy, &last, &currdir_fd); + if (res == -1) + goto out; + res = check_is_mount(last, mount_point); + if (res == -1) + goto out; + res = ncp_mnt_umount(mount_point, last); + +out: + free(copy); + if (currdir_fd != -1) { + fchdir(currdir_fd); + close(currdir_fd); + } + + return res; +} + static int do_umount(const char *mount_point) { int fid = open(mount_point, O_RDONLY, 0); uid_t mount_uid; + int res; if (fid == -1) { eprintf(_("Could not open %s: %s\n"), @@ -253,12 +441,8 @@ do_umount(const char *mount_point) return -1; } close(fid); - if (umount(mount_point) != 0) { - eprintf(_("Could not umount %s: %s\n"), - mount_point, strerror(errno)); - return -1; - } - return 0; + res = unmount_ncp(mount_point); + return res; }