diff options
| author | Rich Felker <dalias@aerifal.cx> | 2011-09-21 23:57:51 -0400 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2011-09-21 23:57:51 -0400 | 
| commit | 0d4d94efd5dfe9348582c92a2de6923bb66492ac (patch) | |
| tree | a623becc30cc59b49d629b58d1039399e7be5918 | |
| parent | 12d547b262c2c8c4e23d0a62eb59581929c2da89 (diff) | |
| download | musl-0d4d94efd5dfe9348582c92a2de6923bb66492ac.tar.gz | |
protect against/handle cancellation reading shadow passwords
| -rw-r--r-- | src/passwd/getspnam_r.c | 12 | 
1 files changed, 11 insertions, 1 deletions
| diff --git a/src/passwd/getspnam_r.c b/src/passwd/getspnam_r.c index 9e29aa9c..9f3378e9 100644 --- a/src/passwd/getspnam_r.c +++ b/src/passwd/getspnam_r.c @@ -2,6 +2,7 @@  #include <unistd.h>  #include <sys/stat.h>  #include <ctype.h> +#include <pthread.h>  #include "pwf.h"  /* This implementation support Openwall-style TCB passwords in place of @@ -16,6 +17,11 @@ static long xatol(const char *s)  	return isdigit(*s) ? atol(s) : -1;  } +static void cleanup(void *p) +{ +	fclose(p); +} +  int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct spwd **res)  {  	char path[20+NAME_MAX]; @@ -25,6 +31,7 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct  	size_t k, l = strlen(name);  	char *s;  	int skip = 0; +	int cs;  	*res = 0; @@ -44,7 +51,9 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct  		struct stat st = { 0 };  		errno = EINVAL;  		if (fstat(fd, &st) || !S_ISREG(st.st_mode) || !(f = fdopen(fd, "rb"))) { +			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);  			close(fd); +			pthread_setcancelstate(cs, 0);  			return errno;  		}  	} else { @@ -52,6 +61,7 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct  		if (!f) return errno;  	} +	pthread_cleanup_push(cleanup, f);  	while (fgets(buf, size, f) && (k=strlen(buf))>0) {  		if (skip || strncmp(name, buf, l)) {  			skip = buf[k-1] != '\n'; @@ -92,6 +102,6 @@ int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct  		*res = sp;  		break;  	} -	fclose(f); +	pthread_cleanup_pop(1);  	return rv;  } | 
