From: Werner Fink Date: Mon, 20 Dec 2010 12:22:24 +0000 (+0100) Subject: Do not let sysctl abort due a missed file or directory under /proc. X-Git-Tag: v3.3.0~36 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4736dad559f2ab0f1caa8231de7d766f4ada029d;p=procps-ng Do not let sysctl abort due a missed file or directory under /proc. Include signal.h for compiling w. Signed-off-by: Werner Fink --- diff --git a/sysctl.c b/sysctl.c index 1470df9a..9be79ce1 100644 --- a/sysctl.c +++ b/sysctl.c @@ -128,6 +128,7 @@ static int ReadSetting(const char *restrict const name) { char *restrict outname; char inbuf[1025]; FILE *restrict fp; + struct stat ts; if (!name || !*name) { fprintf(stderr, ERR_INVALID_KEY, name); @@ -144,6 +145,25 @@ static int ReadSetting(const char *restrict const name) { outname = strdup(name); slashdot(outname,'/','.'); /* change / to . */ + if (stat(tmpname, &ts) < 0) { + if (!IgnoreError) { + perror(tmpname); + rc = -1; + } + goto out; + } + if ((ts.st_mode & S_IRUSR) == 0) + goto out; + + if (S_ISDIR(ts.st_mode)) { + size_t len; + len = strlen(tmpname); + tmpname[len] = '/'; + tmpname[len+1] = '\0'; + rc = DisplayAll(tmpname); + goto out; + } + fp = fopen(tmpname, "r"); if (!fp) { @@ -164,6 +184,7 @@ static int ReadSetting(const char *restrict const name) { break; } } else { + errno = 0; if(fgets(inbuf, sizeof inbuf - 1, fp)) { // this loop is required, see // /sbin/sysctl -a | egrep -6 dev.cdrom.info @@ -194,18 +215,20 @@ static int ReadSetting(const char *restrict const name) { len = strlen(tmpname); tmpname[len] = '/'; tmpname[len+1] = '\0'; + fclose(fp); rc = DisplayAll(tmpname); - break; + goto out; } default: fprintf(stderr, ERR_UNKNOWN_READING, strerror(errno), outname); rc = -1; + case 0: break; } } fclose(fp); } - +out: free(tmpname); free(outname); return rc; @@ -265,8 +288,9 @@ static int WriteSetting(const char *setting) { const char *value; const char *equals; char *tmpname; - FILE *fp; char *outname; + FILE *fp; + struct stat ts; if (!name) { /* probably don't want to display this err */ return 0; @@ -299,6 +323,24 @@ static int WriteSetting(const char *setting) { outname[equals-name] = 0; slashdot(outname,'/','.'); /* change / to . */ + if (stat(tmpname, &ts) < 0) { + if (!IgnoreError) { + perror(tmpname); + rc = -1; + } + goto out; + } + + if ((ts.st_mode & S_IWUSR) == 0) { + fprintf(stderr, ERR_UNKNOWN_WRITING, strerror(EACCES), outname); + goto out; + } + + if (S_ISDIR(ts.st_mode)) { + fprintf(stderr, ERR_UNKNOWN_WRITING, strerror(EACCES), outname); + goto out; + } + fp = fopen(tmpname, "w"); if (!fp) { @@ -343,7 +385,7 @@ static int WriteSetting(const char *setting) { } } } - +out: free(tmpname); free(outname); return rc; diff --git a/w.c b/w.c index c2e996a8..f479433c 100644 --- a/w.c +++ b/w.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include