From 2a453f362d34674b2adfc9f29bb781a0ba7a69c2 Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Sun, 28 Oct 2018 01:00:03 +0300 Subject: initial --- Makefile | 26 ++++++++++ README.md | 1 + drm_master_util.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 drm_master_util.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f69be8d --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +CC = gcc +CFLAGS = -O2 -Wall -W +CFLAGS += `pkg-config --cflags libdrm` +LDFLAGS = `pkg-config --libs libdrm` +PROGRAM = drm_master_util +INSTALL = /usr/bin/install +PREFIX = /usr + +all: $(PROGRAM) + +$(PROGRAM): drm_master_util.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +install: $(PROGRAM) + $(INSTALL) $(PROGRAM) $(PREFIX)/bin + chmod u+s $(PREFIX)/bin/${PROGRAM} + +clean: + rm -f *.o $(PROGRAM) + +distclean: clean + +%.o: %.c + $(CC) $(CFLAGS) -c $^ -I. -o $@ + +.PHONY: all install clean distclean diff --git a/README.md b/README.md new file mode 100644 index 0000000..b923e75 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# drm_master_util diff --git a/drm_master_util.c b/drm_master_util.c new file mode 100644 index 0000000..73884af --- /dev/null +++ b/drm_master_util.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRM_HACK_SOCKET_NAME "xorg_drm_master_util" + +int recv_fd(int sock) +{ + // This function does the arcane magic recving + // file descriptors over unix domain sockets + struct msghdr msg; + struct iovec iov[1]; + struct cmsghdr *cmsg = NULL; + char ctrl_buf[CMSG_SPACE(sizeof(int))]; + char data[1]; + + memset(&msg, 0, sizeof(struct msghdr)); + memset(ctrl_buf, 0, CMSG_SPACE(sizeof(int))); + + iov[0].iov_base = data; + iov[0].iov_len = sizeof(data); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = ctrl_buf; + msg.msg_controllen = CMSG_SPACE(sizeof(int)); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + recvmsg(sock, &msg, 0); + + cmsg = CMSG_FIRSTHDR(&msg); + + return *((int *) CMSG_DATA(cmsg)); +} + +void usage(const char *name) +{ + printf("usage: %s\n", name); + printf("\n" + "-h, --help: print this help\n" + "-s, --set: drmSetMaster\n" + "-d, --drop: drmDropMaster\n" + "-t, --test: test\n" + "-r, --root: ensure i'm root\n" + "\n"); +} + +void check_error(char *prog, int err) +{ + if (err) { + fprintf(stderr, "%s: %s\n", prog, strerror(errno)); + exit(err); + } +} + +enum action {HELP, SET, DROP, TEST}; + +int main(int argc, char *argv[]) +{ + enum action act = HELP; + int opt, optindex = 0; + int ret = 0; + bool ensure_root = false; + static struct option longopts[] = { + {"help", 0, 0, 'h'}, + {"set", 0, 0, 's'}, + {"drop", 0, 0, 'd'}, + {"test", 0, 0, 't'}, + {"root", 0, 0, 'r'}, + {0, 0, 0, 0} + }; + + if (argv[1] == NULL) { + usage(argv[0]); + exit(0); + } + + while ((opt = getopt_long(argc, argv, "hsdtr", + longopts, &optindex)) != EOF) { + switch (opt) { + case 's': act = SET; break; + case 'd': act = DROP; break; + case 't': act = TEST; break; + case 'r': ensure_root = true; break; + } + } + + if (optind < argc) { + fprintf(stderr, "Error: extra parameter found.\n"); + exit(1); + } + + if (ensure_root) { + uid_t uid = getuid(); + uid_t euid = geteuid(); + + assert(euid == 0); + + ret = setuid(euid); + check_error("setuid", ret); + + uid = getuid(); + euid = getuid(); + + assert(uid == 0); + } + + if (act == HELP) { + usage(argv[0]); + exit(0); + } + + struct sockaddr_un addr; + int sock; + + // Create and connect a unix domain socket + sock = socket(AF_UNIX, SOCK_STREAM, 0); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strcpy(&addr.sun_path[1], DRM_HACK_SOCKET_NAME); + connect(sock, (struct sockaddr *)&addr, sizeof(addr)); + + int fd = recv_fd(sock); + close(sock); + + assert(fd != 0); + + if (act == SET) { + ret = drmSetMaster(fd); + check_error("drmSetMaster", ret); + } else if (act == DROP) { + ret = drmDropMaster(fd); + check_error("drmDropMaster", ret); + } else if (act == TEST) { + printf("received fd: %d\n", fd); + dprintf(fd, "drm_master_util: writing to received fd ;)\n"); + } + + return 0; +} -- cgit v1.2.3