--- src/lib-storage/mailbox-list.c.orig 2010-09-14 11:03:18.000000000 -0400 +++ src/lib-storage/mailbox-list.c 2010-10-14 15:20:15.000000000 -0400 @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include /* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and @@ -450,7 +453,7 @@ } if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) { - /* directory's GID is used automatically for new + /* directory is sgid, so GID is used automatically for new files */ *gid_r = (gid_t)-1; } else if ((st.st_mode & 0070) >> 3 == (st.st_mode & 0007)) { @@ -460,8 +463,39 @@ } else if (getegid() == st.st_gid) { /* using our own gid, no need to change it */ *gid_r = (gid_t)-1; - } else { - *gid_r = st.st_gid; + } + + else { + /* test for unusable inheritance. logic sets fgid_me to st.gid + for unlikely case of lookup failure and we just fall through */ + int j, ngroups = 999; + gid_t *groups; + gid_t fgid_me = st.st_gid; + + groups = malloc(ngroups * sizeof (gid_t)); + if (groups != NULL) { + uid_t egid = getegid(); + struct passwd *pw = getpwuid(geteuid()); + if (pw != NULL) { + /* get pw entry for test using my current effective uid */ + if (getgrouplist(pw->pw_name, egid, groups, &ngroups) != -1) { + /* get list of group IDs my euid belongs to, ngroups + will be set to the number of groups I belong to */ + fgid_me = egid; + for (j = 0; j < ngroups; j++) { + /* enumerate list, test to see if i belong + to gid of parent directory */ + if (st.st_gid == groups[j]) { + /* if so, switch to parent gid */ + fgid_me = st.st_gid; + } + } + } + } + free(groups); + } + + *gid_r = fgid_me; } }