mirror of
https://github.com/X11Libre/xf86-video-intel.git
synced 2026-03-24 01:24:12 +00:00
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>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user