summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-07-17 16:14:16 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-07-17 16:14:16 +0100
commit3140d72826b5227f7f7ac9a428faa4bcfd4b377b (patch)
tree085f8745071adfbd1d4b05fc1a6d7bc22efdf8b9
parentbcd09ff6eb76bc4df046ece4da29b1455fed8dff (diff)
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) <iface> " 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 <chris@chris-wilson.co.uk>
-rw-r--r--tools/backlight_helper.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/tools/backlight_helper.c b/tools/backlight_helper.c
index 24958ec6..8b2667dc 100644
--- a/tools/backlight_helper.c
+++ b/tools/backlight_helper.c
@@ -1,43 +1,57 @@
#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#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 <iface>\n", argv[0]);
- return 1;
- }
+ if (argc != 2)
+ die("Usage: xf86-video-intel-backlight-helper <iface>\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;