From 3140d72826b5227f7f7ac9a428faa4bcfd4b377b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 17 Jul 2014 16:14:16 +0100 Subject: [PATCH] backlight: Prevent dereference of potential NULL argv Adam Sampson spotted that "It's possible (but not very sensible) to exec a program with an empty argument list, so argv[0] is not necessarily a valid pointer. For example: $ cat exec0.c int main(int argc, char *argv[]) { char *empty[1] = { NULL }; execvp(argv[1], empty); perror("execvp"); return 1; } $ ./exec0 /usr/libexec/xf86-video-intel-backlight-helper Usage: (null) " He sensibly suggested that we hardcode the program name to avoid the NULL dereference. Being the paranoid type, we should also be careful not to write to any file descriptors outside of our control (i.e. stderr), so disable the messages unless we are debugging. Reported-by: Adam Sampson Signed-off-by: Chris Wilson --- tools/backlight_helper.c | 56 ++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/tools/backlight_helper.c b/tools/backlight_helper.c index 24958ec..8b2667d 100644 --- a/tools/backlight_helper.c +++ b/tools/backlight_helper.c @@ -1,43 +1,57 @@ #include #include +#include +#include #include #include +#include #include #include +#define DBG 0 + +#if defined(__GNUC__) && (__GNUC__ > 3) +__attribute__((format(printf, 1, 2), noreturn)) +#endif +static void die(const char *format, ...) +{ + if (DBG) { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + } + + exit(1); +} + int main(int argc, char *argv[]) { struct stat st; char buf[1024]; int len, fd; - if (argc != 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return 1; - } + if (argc != 2) + die("Usage: xf86-video-intel-backlight-helper \n"); + + if (strchr(argv[1], '/') != NULL) + die("Invalid interface '%s': contains '/'\n", argv[1]); + + if (snprintf(buf, sizeof(buf), + "/sys/class/backlight/%s/brightness", + argv[1]) >= sizeof(buf)) + die("Invalid interface '%s': name too long\n", argv[1]); - if (strchr(argv[1], '/') != NULL) { - fprintf(stderr, "Invalid interface name\n"); - return 1; - } - if (snprintf(buf, sizeof(buf), "/sys/class/backlight/%s/brightness", - argv[1]) >= sizeof(buf)) { - fprintf(stderr, "Interface name is too long\n"); - return 1; - } fd = open(buf, O_RDWR); - if (fd < 0 || fstat(fd, &st) || major(st.st_dev)) { - fprintf(stderr, "Cannot access backlight interface '%s'\n", argv[1]); - return 1; - } + if (fd < 0 || fstat(fd, &st) || major(st.st_dev)) + die("Invalid interface '%s': unknown backlight file\n", argv[1]); while (fgets(buf, sizeof(buf), stdin)) { len = strlen(buf); - if (write(fd, buf, len) != len) { - fprintf(stderr, "Failed to update backlight interface '%s'\n", argv[1]); - return 2; - } + if (write(fd, buf, len) != len) + die("Failed to update backlight interface '%s': errno=%d\n", argv[1], errno); } return 0; -- 2.7.4