diff --color -ru a/pam_cap/pam_cap.c b/pam_cap/pam_cap.c --- a/pam_cap/pam_cap.c 2021-02-05 06:52:17.000000000 +0100 +++ b/pam_cap/pam_cap.c 2021-04-23 09:48:00.091122637 +0200 @@ -218,7 +218,7 @@ if (!cap_set_proc(cap_s)) { ok = 1; } - goto cleanup_cap_s; + goto cleanup_conf; } iab = cap_iab_from_text(conf_caps); @@ -238,10 +238,9 @@ _pam_drop(conf_caps); cleanup_cap_s: - if (cap_s) { - cap_free(cap_s); - cap_s = NULL; - } + cap_free(cap_s); + cap_s = NULL; + return ok; } diff --color -ru a/progs/capsh.c b/progs/capsh.c --- a/progs/capsh.c 2021-02-05 06:52:17.000000000 +0100 +++ b/progs/capsh.c 2021-04-23 09:48:00.095122691 +0200 @@ -336,8 +336,8 @@ */ static char *find_self(const char *arg0) { - int i; - char *parts, *dir, *scratch; + int i, status=1; + char *p = NULL, *parts, *dir, *scratch; const char *path; for (i = strlen(arg0)-1; i >= 0 && arg0[i] != '/'; i--); @@ -352,21 +352,45 @@ } parts = strdup(path); + if (parts == NULL) { + fprintf(stderr, "insufficient memory for parts of path\n"); + exit(1); + } + scratch = malloc(2+strlen(path)+strlen(arg0)); - if (parts == NULL || scratch == NULL) { + if (scratch == NULL) { fprintf(stderr, "insufficient memory for path building\n"); - exit(1); + goto free_parts; } - for (i=0; (dir = strtok(parts, ":")); parts = NULL) { + for (p = parts; (dir = strtok(p, ":")); p = NULL) { sprintf(scratch, "%s/%s", dir, arg0); if (access(scratch, X_OK) == 0) { - return scratch; + status = 0; + break; } } + if (status) { + fprintf(stderr, "unable to find executable '%s' in PATH\n", arg0); + free(scratch); + } + +free_parts: + free(parts); + if (status) { + exit(status); + } + return scratch; +} - fprintf(stderr, "unable to find executable '%s' in PATH\n", arg0); - exit(1); +static long safe_sysconf(int name) +{ + long ans = sysconf(name); + if (ans <= 0) { + fprintf(stderr, "sysconf(%d) returned a non-positive number: %ld\n", name, ans); + exit(1); + } + return ans; } int main(int argc, char *argv[], char *envp[]) @@ -617,7 +641,9 @@ * Given we are now in a new directory tree, its good practice * to start off in a sane location */ - status = chdir("/"); + if (status == 0) { + status = chdir("/"); + } cap_free(orig); @@ -718,14 +744,14 @@ gid_t *group_list; int g_count; - length = sysconf(_SC_GETGR_R_SIZE_MAX); + length = safe_sysconf(_SC_GETGR_R_SIZE_MAX); buf = calloc(1, length); if (NULL == buf) { fprintf(stderr, "No memory for [%s] operation\n", argv[i]); exit(1); } - max_groups = sysconf(_SC_NGROUPS_MAX); + max_groups = safe_sysconf(_SC_NGROUPS_MAX); group_list = calloc(max_groups, sizeof(gid_t)); if (NULL == group_list) { fprintf(stderr, "No memory for gid list\n"); @@ -741,8 +767,7 @@ } if (!isdigit(*ptr)) { struct group *g, grp; - getgrnam_r(ptr, &grp, buf, length, &g); - if (NULL == g) { + if (getgrnam_r(ptr, &grp, buf, length, &g) || NULL == g) { fprintf(stderr, "Failed to identify gid for group [%s]\n", ptr); exit(1); } @@ -835,6 +860,7 @@ argv[argc] = NULL; execve(argv[i], argv+i, envp); fprintf(stderr, "execve '%s' failed!\n", argv[i]); + free(argv[i]); exit(1); } else if (!strncmp("--shell=", argv[i], 8)) { shell = argv[i]+8; diff --color -ru a/psx/psx.c b/psx/psx.c --- a/psx/psx.c 2021-02-05 06:52:17.000000000 +0100 +++ b/psx/psx.c 2021-04-23 09:48:00.095122691 +0200 @@ -454,6 +454,10 @@ int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { psx_starter_t *starter = calloc(1, sizeof(psx_starter_t)); + if (starter == NULL) { + perror("failed at thread creation"); + exit(1); + } starter->fn = start_routine; starter->arg = arg; /*