--- /dev/null
+From: Jeffrey Hutzelman <jhutz@cmu.edu>
+Date: Tue, 18 Jun 2013 12:35:36 -0400
+Subject: userok.c: Fix fixed-size on-stack path buffers
+
+Several functions in src/auth/userok.c construct pathnames in fixed
+size buffers on their stacks. Those buffers are simultaneously too
+small for the purpose for which they are used and too large to be
+placed on the stack. This change replaces these fixed-size buffers
+with dynamically-allocated buffers which are either exactly the right
+size (due to asprintf) or have size AFSDIR_PATH_MAX.
+
+FIXES 130719
+
+Reviewed-on: http://gerrit.openafs.org/9986
+Tested-by: BuildBot <buildbot@rampaginggeek.com>
+Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
+(cherry picked from commit 68e02987f62e1c507ddf7fd35847338b130c243d)
+
+This file has diverged quite substantially between master and 1.6.x,
+so though it is marked as a "cherry-pick", this patch was substantially
+rewritten for the 1.6 branch. In particular, we must use afs_asprintf()
+since asprintf() is not available everywhere.
+
+Change-Id: Iac62cb8293e7b28b422e7401eccb1f26841aff66
+(cherry picked from commit 27c71d3f62b605ca30800769c9bea2c649337032)
+---
+ src/auth/userok.c | 104 +++++++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 75 insertions(+), 29 deletions(-)
+
+diff --git a/src/auth/userok.c b/src/auth/userok.c
+index 68b6fbf..3a9e493 100644
+--- a/src/auth/userok.c
++++ b/src/auth/userok.c
+@@ -108,8 +108,8 @@ afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
+ int
+ afsconf_DeleteUser(struct afsconf_dir *adir, char *auser)
+ {
+- char tbuffer[1024];
+- char nbuffer[1024];
++ char *filename, *nfilename;
++ char *buffer;
+ FILE *tf;
+ FILE *nf;
+ int flag;
+@@ -119,8 +119,17 @@ afsconf_DeleteUser(struct afsconf_dir *adir, char *auser)
+ struct stat tstat;
+ afs_int32 code;
+
++ buffer = malloc(AFSDIR_PATH_MAX);
++ if (buffer == NULL)
++ return ENOMEM;
++ filename = malloc(AFSDIR_PATH_MAX);
++ if (filename == NULL) {
++ free(buffer);
++ return ENOMEM;
++ }
++
+ LOCK_GLOBAL_MUTEX;
+- strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
++ strcompose(filename, AFSDIR_PATH_MAX, adir->name, "/",
+ AFSDIR_ULIST_FILE, NULL);
+ #ifndef AFS_NT40_ENV
+ {
+@@ -129,64 +138,86 @@ afsconf_DeleteUser(struct afsconf_dir *adir, char *auser)
+ * of the temporary file will work even if UserList is a symlink
+ * into a different filesystem.
+ */
+- char resolved_path[1024];
+-
+- if (realpath(tbuffer, resolved_path)) {
+- strcpy(tbuffer, resolved_path);
++ nfilename = malloc(AFSDIR_PATH_MAX);
++ if (nfilename == NULL) {
++ UNLOCK_GLOBAL_MUTEX;
++ free(filename);
++ free(buffer);
++ return ENOMEM;
++ }
++ if (realpath(filename, nfilename)) {
++ free(filename);
++ filename = nfilename;
++ } else {
++ free(nfilename);
+ }
+ }
+ #endif /* AFS_NT40_ENV */
+- tf = fopen(tbuffer, "r");
++ if (afs_asprintf(&nfilename, "%s.NXX", filename) < 0) {
++ UNLOCK_GLOBAL_MUTEX;
++ free(filename);
++ free(buffer);
++ return -1;
++ }
++ tf = fopen(filename, "r");
+ if (!tf) {
+ UNLOCK_GLOBAL_MUTEX;
++ free(filename);
++ free(nfilename);
++ free(buffer);
+ return -1;
+ }
+- code = stat(tbuffer, &tstat);
++ code = stat(filename, &tstat);
+ if (code < 0) {
+ UNLOCK_GLOBAL_MUTEX;
++ free(filename);
++ free(nfilename);
++ free(buffer);
+ return code;
+ }
+- strcpy(nbuffer, tbuffer);
+- strcat(nbuffer, ".NXX");
+- nf = fopen(nbuffer, "w+");
++ nf = fopen(nfilename, "w+");
+ if (!nf) {
+ fclose(tf);
+ UNLOCK_GLOBAL_MUTEX;
++ free(filename);
++ free(nfilename);
++ free(buffer);
+ return EIO;
+ }
+ flag = 0;
+ found = 0;
+ while (1) {
+ /* check for our user id */
+- tp = fgets(nbuffer, sizeof(nbuffer), tf);
++ tp = fgets(buffer, AFSDIR_PATH_MAX, tf);
+ if (tp == NULL)
+ break;
+- code = sscanf(nbuffer, "%64s", tname);
++ code = sscanf(buffer, "%64s", tname);
+ if (code == 1 && strcmp(tname, auser) == 0) {
+ /* found the guy, don't copy to output file */
+ found = 1;
+ } else {
+ /* otherwise copy original line to output */
+- fprintf(nf, "%s", nbuffer);
++ fprintf(nf, "%s", buffer);
+ }
+ }
+ fclose(tf);
++ free(buffer);
+ if (ferror(nf))
+ flag = 1;
+ if (fclose(nf) == EOF)
+ flag = 1;
+- strcpy(nbuffer, tbuffer);
+- strcat(nbuffer, ".NXX"); /* generate new file name again */
+ if (flag == 0) {
+ /* try the rename */
+- flag = renamefile(nbuffer, tbuffer);
++ flag = renamefile(nfilename, filename);
+ if (flag == 0)
+- flag = chmod(tbuffer, tstat.st_mode);
++ flag = chmod(filename, tstat.st_mode);
+ } else
+- unlink(nbuffer);
++ unlink(nfilename);
+
+ /* finally, decide what to return to the caller */
+ UNLOCK_GLOBAL_MUTEX;
++ free(filename);
++ free(nfilename);
+ if (flag)
+ return EIO; /* something mysterious went wrong */
+ if (!found)
+@@ -199,25 +230,30 @@ int
+ afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
+ afs_int32 abufferLen)
+ {
+- char tbuffer[256];
++ char *tbuffer;
+ FILE *tf;
+ char tname[64 + 1];
+ char *tp;
+ int flag;
+ afs_int32 code;
+
++ tbuffer = malloc(AFSDIR_PATH_MAX);
++ if (tbuffer == NULL)
++ return ENOMEM;
++
+ LOCK_GLOBAL_MUTEX;
+- strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
++ strcompose(tbuffer, AFSDIR_PATH_MAX, adir->name, "/",
+ AFSDIR_ULIST_FILE, NULL);
+ tf = fopen(tbuffer, "r");
+ if (!tf) {
+ UNLOCK_GLOBAL_MUTEX;
++ free(tbuffer);
+ return 1;
+ }
+ flag = 1;
+ while (1) {
+ /* check for our user id */
+- tp = fgets(tbuffer, sizeof(tbuffer), tf);
++ tp = fgets(tbuffer, AFSDIR_PATH_MAX, tf);
+ if (tp == NULL)
+ break;
+ code = sscanf(tbuffer, "%64s", tname);
+@@ -230,6 +266,7 @@ afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
+ strcpy(abuffer, tname);
+ fclose(tf);
+ UNLOCK_GLOBAL_MUTEX;
++ free(tbuffer);
+ return flag;
+ }
+
+@@ -237,22 +274,28 @@ afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
+ static int
+ FindUser(struct afsconf_dir *adir, char *auser)
+ {
+- char tbuffer[256];
++ char *tbuffer;
+ bufio_p bp;
+ char tname[64 + 1];
+ int flag;
+ afs_int32 code;
+ int rc;
+
+- strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
++ tbuffer = malloc(AFSDIR_PATH_MAX);
++ if (tbuffer == NULL)
++ return 0;
++
++ strcompose(tbuffer, AFSDIR_PATH_MAX, adir->name, "/", AFSDIR_ULIST_FILE,
+ NULL);
+ bp = BufioOpen(tbuffer, O_RDONLY, 0);
+- if (!bp)
++ if (!bp) {
++ free(tbuffer);
+ return 0;
++ }
+ flag = 0;
+ while (1) {
+ /* check for our user id */
+- rc = BufioGets(bp, tbuffer, sizeof(tbuffer));
++ rc = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
+ if (rc < 0)
+ break;
+ code = sscanf(tbuffer, "%64s", tname);
+@@ -262,6 +305,7 @@ FindUser(struct afsconf_dir *adir, char *auser)
+ }
+ }
+ BufioClose(bp);
++ free(tbuffer);
+ return flag;
+ }
+
+@@ -271,7 +315,7 @@ afsconf_AddUser(struct afsconf_dir *adir, char *aname)
+ {
+ FILE *tf;
+ afs_int32 code;
+- char tbuffer[256];
++ char *tbuffer;
+
+ LOCK_GLOBAL_MUTEX;
+ if (FindUser(adir, aname)) {
+@@ -279,9 +323,11 @@ afsconf_AddUser(struct afsconf_dir *adir, char *aname)
+ return EEXIST; /* already in the list */
+ }
+
+- strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
++ tbuffer = malloc(AFSDIR_PATH_MAX);
++ strcompose(tbuffer, AFSDIR_PATH_MAX, adir->name, "/", AFSDIR_ULIST_FILE,
+ NULL);
+ tf = fopen(tbuffer, "a+");
++ free(tbuffer);
+ if (!tf) {
+ UNLOCK_GLOBAL_MUTEX;
+ return EIO;