From eeb0f9098450dbe470fc9b60627d15df62b04239 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Wed, 16 Dec 2015 15:15:20 +0000 Subject: Fix s6-envuidgid behaviour when -D is given but not -u/-g/-B --- src/daemontools-extras/s6-envuidgid.c | 108 +++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 40 deletions(-) (limited to 'src/daemontools-extras/s6-envuidgid.c') diff --git a/src/daemontools-extras/s6-envuidgid.c b/src/daemontools-extras/s6-envuidgid.c index 2971e6a..57c178f 100644 --- a/src/daemontools-extras/s6-envuidgid.c +++ b/src/daemontools-extras/s6-envuidgid.c @@ -16,17 +16,48 @@ #define USAGE "s6-envuidgid [ -i | -D defaultuid:defaultgid ] [ -u | -g | -B ] [ -n ] account prog..." #define dieusage() strerr_dieusage(100, USAGE) +static inline unsigned int scan_defaults (char const *s, uint64 *uid, gid_t *gid, unsigned int *n, gid_t *tab) +{ + unsigned int pos = uint64_scan(s, uid) ; + if (!pos) + { + if (*s != ':') return 0 ; + *uid = 0 ; + } + s += pos ; + if (!*s) goto zgid ; + if (*s++ != ':') return 0 ; + if (!*s) goto zgid ; + pos = gid_scan(s, gid) ; + if (!pos) + { + if (*s != ':') return 0 ; + *gid = 0 ; + } + s += pos ; + if (!*s) goto zn ; + if (*s++ != ':') return 0 ; + if (!*s) goto zn ; + return gid_scanlist(tab, NGROUPS_MAX, s, n) ; + + zgid: + *gid = 0 ; + zn: + *n = 0 ; + return 1 ; +} + int main (int argc, char *const *argv, char const *const *envp) { char const *user = 0 ; char const *group = 0 ; - int what = 0 ; + unsigned int what = 7 ; int numfallback = 0 ; int insist = 1 ; - unsigned int pos ; uint64 uid ; gid_t gid ; - char fmt[19 + UINT64_FMT + (NGROUPS_MAX+1) * GID_FMT] ; + unsigned int n ; + gid_t tab[NGROUPS_MAX] ; PROG = "s6-envuidgid" ; { subgetopt_t l = SUBGETOPT_ZERO ; @@ -39,27 +70,12 @@ int main (int argc, char *const *argv, char const *const *envp) case 'u' : what = 1 ; break ; case 'g' : what = 2 ; break ; case 'B' : what = 3 ; break ; - case 'n' : what = 3 ; numfallback = 1 ; break ; + case 'n' : what &= 3 ; numfallback = 1 ; break ; case 'i' : insist = 1 ; break ; case 'D' : - { - unsigned int pos = uint64_scan(l.arg, &uid) ; - if (!pos) - { - if (l.arg[pos] != ':') dieusage() ; - uid = 0 ; - } - if (!l.arg[pos]) gid = 0 ; - else - { - if (l.arg[pos++] != ':') dieusage() ; - if (!l.arg[pos]) gid = 0 ; - else if (!gid0_scan(l.arg + pos, &gid)) dieusage() ; - } + if (!scan_defaults(l.arg, &uid, &gid, &n, tab)) dieusage() ; insist = 0 ; - what = 3 ; break ; - } default : dieusage() ; } } @@ -69,7 +85,7 @@ int main (int argc, char *const *argv, char const *const *envp) switch (what) { - case 0 : /* account */ + case 7 : /* account */ case 1 : /* user */ user = argv[0] ; break ; @@ -77,8 +93,9 @@ int main (int argc, char *const *argv, char const *const *envp) group = argv[0] ; break ; case 3 : /* both */ + { + unsigned int pos = str_chr(argv[0], ':') ; user = argv[0] ; - pos = str_chr(argv[0], ':') ; if (argv[0][pos]) { argv[0][pos] = 0 ; @@ -87,20 +104,16 @@ int main (int argc, char *const *argv, char const *const *envp) if (!group[0]) group = 0 ; } break ; + } default : strerr_dief1x(101, "inconsistent option management - please submit a bug-report") ; } - pos = 0 ; - if (group) { struct group *gr = getgrnam(group) ; if (gr) gid = gr->gr_gid ; else if (numfallback && gid_scan(group, &gid)) ; else if (insist) strerr_dief2x(1, "unknown group: ", group) ; - byte_copy(fmt + pos, 4, "GID=") ; pos += 4 ; - pos += gid_fmt(fmt + pos, gid) ; - fmt[pos++] = 0 ; } if (user) @@ -109,26 +122,41 @@ int main (int argc, char *const *argv, char const *const *envp) if (pw) { uid = pw->pw_uid ; - if (!what) + if (what == 7) { - gid_t tab[NGROUPS_MAX] ; - int n = prot_readgroups(argv[0], tab, NGROUPS_MAX) ; - if (n < 0) + int r = prot_readgroups(argv[0], tab, NGROUPS_MAX) ; + if (r < 0) strerr_diefu2sys(111, "get supplementary groups for ", argv[0]) ; - byte_copy(fmt + pos, 4, "GID=") ; pos += 4 ; - pos += gid_fmt(fmt + pos, pw->pw_gid) ; - byte_copy(fmt + pos, 9, "\0GIDLIST=") ; pos += 9 ; - pos += gid_fmtlist(fmt + pos, tab, n) ; - fmt[pos++] = 0 ; + n = r ; + gid = pw->pw_gid ; } } else if (numfallback && uint64_scan(user, &uid)) ; else if (insist) strerr_dief2x(1, "unknown user: ", user) ; - byte_copy(fmt + pos, 4, "UID=") ; pos += 4 ; - pos += uint64_fmt(fmt + pos, uid) ; - fmt[pos++] = 0 ; } - pathexec_r((char const *const *)argv + 1, envp, env_len(envp), fmt, pos) ; + { + unsigned int pos = 0 ; + char fmt[19 + UINT64_FMT + (NGROUPS_MAX+1) * GID_FMT] ; + if (what & 1) + { + byte_copy(fmt + pos, 4, "UID=") ; pos += 4 ; + pos += uint64_fmt(fmt + pos, uid) ; + fmt[pos++] = 0 ; + } + if (what & 2) + { + byte_copy(fmt + pos, 4, "GID=") ; pos += 4 ; + pos += gid_fmt(fmt + pos, gid) ; + fmt[pos++] = 0 ; + } + if (what & 4) + { + byte_copy(fmt + pos, 8, "GIDLIST=") ; pos += 8 ; + pos += gid_fmtlist(fmt + pos, tab, n) ; + fmt[pos++] = 0 ; + } + pathexec_r((char const *const *)argv + 1, envp, env_len(envp), fmt, pos) ; + } strerr_dieexec(111, argv[1]) ; } -- cgit v1.2.3