LINUX.ORG.RU

Non-root Xorg на Intel'е

 , , ,


0

2

Сделал rootless xorg по инструкции с Wiki, все работает. Однако работает только на xf86-video-intel драйвере. Если же я пытаюсь запустить с modesetting драйвером, то в логе появляются ошибки:

[   211.402] (EE) modeset(0): drmSetMaster failed: Permission denied
[   211.402] (EE) 
[   211.402] (EE) AddScreen/ScreenInit failed for driver 0
Возможно ли как-то сделать Non-root Xorg с modesetting драйвером?

★★★★★
Ответ на: комментарий от Deleted
$ eix xorg-server

Установленные версии:  1.19.5-r1(17:25:37 17.03.2018)(glamor udev xorg -debug -dmx -doc
-ipv6 -kdrive -libressl -minimal -selinux -static-libs -suid -systemd -tslib -unwind
-wayland -xcsecurity -xephyr -xnest -xvfb)
Kron4ek ★★★★★
() автор топика
Ответ на: комментарий от Kron4ek

xcsecurity включи.

Если не поможет:
По идее там надо смотреть xorg.conf, состоит ли пользователь в группе video, как заводишь иксы (.xinitrc, dm какой).

Deleted
()
Ответ на: комментарий от Deleted

Кто-то советует suid вкл... Короче, пробуй. Мой опыт подсказывает, что добавление пользователя в группу video решало вопрос...

Deleted
()
Ответ на: комментарий от Deleted

К сожалению, ни xcsecurty, ни группа video не помогли. А suid принудительно запускает X с правами root. Похоже, с драйвером modesetting Xorg можно запустить только с правами root.

Kron4ek ★★★★★
() автор топика
Ответ на: комментарий от Kron4ek

Нет. Просто там много шагов, действий. Хрен его знает, что ты там накрутил, как реализовал. Кухня то твоя ;)

Deleted
()
Ответ на: комментарий от Deleted

Сделал, как в Wiki написано. И это работает, как я и сказал, для драйвера intel. Но там ни слова про modesetting.

Kron4ek ★★★★★
() автор топика
Ответ на: комментарий от Kron4ek

Есть вики у Арча. По настройкам черпать инфо можно и нужно смело ;) Ну и, конечно, англоресурсы. Меня без рута не пускало в Иксы, если не тыкал нужный use флаг (какой, призабыл). Я сейчас сам собираю. Можно посмотреть ebuild.

Deleted
()
Ответ на: комментарий от Deleted

На Арч вики сказано только «Xorg may run with standard user privileges with the help of logind» . Кстати, когда пользовался Арчем, там Xorg запускался без рута и с modesetting, и с intel. Может, действительно logind нужен, который elogind в Gentoo.

Kron4ek ★★★★★
() автор топика
Последнее исправление: Kron4ek (всего исправлений: 1)
Ответ на: комментарий от Kron4ek

да накрутил ты просто лишних телодвижений. Честно. Меса, Х, правильно описать дровишки в make.conf и всё. Я нихрена не открывал Вики. Всё и так заводилось.

Deleted
()
Ответ на: комментарий от Deleted

Ты, наверное, спутал запуск без root прав и работу без root прав. Startx можно и без sudo выполнять (если xorg собран с флагом suid), но X все равно будет работать от пользователя root (можешь в top посмотреть). Xorg от обычного пользователя (https://wiki.gentoo.org/wiki/Non_root_Xorg) на modesetting'е не работает, в таком случае Xorg пишет ошибку в лог - я именно это пытаюсь исправить.

Kron4ek ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Ты мне опять про другое говоришь, chmod u+s - это suid бит. С suid Xorg работает с правами root'а, мне нужно чтобы он работал с правами пользователя. SUID только позволяет выполнять startx от пользователя, но запущенный Xorg все равно работает от root'а.

Kron4ek ★★★★★
() автор топика
Последнее исправление: Kron4ek (всего исправлений: 2)
Ответ на: комментарий от Deleted

Вместо chmod u+s можно собрать Xorg с suid use флагом, но не решает проблемы. Потому что non-root xorg - это наоборот запуск без suid флага.

Kron4ek ★★★★★
() автор топика
27 октября 2018 г.
Ответ на: комментарий от ch1p

Привет, у тебя получилось решить эту проблему?

Нет, и на форуме Gentoo тоже никто не подсказал.

Я сейчас на Arch'е, тут Xorg и на modesettings работает без root прав. Полагаю, это заслуга systemd-logind. И на Gentoo с systemd тоже должно работать.

Kron4ek ★★★★★
() автор топика
Последнее исправление: Kron4ek (всего исправлений: 1)
Ответ на: комментарий от Kron4ek

ну с нуво это работало, только пользователя надо добавить в группу input или вроде того, а значит у иксов доступ к абсолютно всем устройствам

anonymous
()
Ответ на: комментарий от anonymous

Не в этом суть. Суть в том, что на modesetting'е Xorg не стартует без root прав, хоть ты тресни. Не важно, есть ты в группе input или нет.

Kron4ek ★★★★★
() автор топика
Последнее исправление: Kron4ek (всего исправлений: 1)
Ответ на: комментарий от Kron4ek

Ладно, тогда так. Наверное можно сделать хак, пропатчить драйвер и заменить этот код:

ret = drmSetMaster(ms->fd);
if (ret)
    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n", ...

на такой, который будет работать с правами пользователя, например вызывать там программу, у которой есть suid бит, которая и будет вызывать drmSetMaster. Вроде должно сработать. Какие проблемы это теоретически сулит?

ch1p
()
Ответ на: комментарий от Kron4ek

Я сделал, у меня работает.

1. suid утилита: https://github.com/gch1p/drm_master_util (make && make install)

2. патч для x11-base/xorg-server-1.19.5-r2, можно положить в /etc/portage/patches/x11-base/xorg-server (ну и там надо сделать чтобы в pre_src_prepare вызывался epatch_user, но это отдельная тема)

diff --git hw/xfree86/drivers/modesetting/driver.c hw/xfree86/drivers/modesetting/driver.c
index 4d5c4e3..afc411c 100644
--- hw/xfree86/drivers/modesetting/driver.c
+++ hw/xfree86/drivers/modesetting/driver.c
@@ -34,7 +34,12 @@
 #endif
 
 #include <unistd.h>
+#include <stdio.h>
 #include <fcntl.h>
+#include <sys/wait.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "compiler.h"
@@ -62,6 +67,8 @@
 #include "driver.h"
 #include "sh3224.h"
 
+#define DRM_HACK_SOCKET_NAME "xorg_drm_master_util"
+
 static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y);
 static Bool CloseScreen(ScreenPtr pScreen);
 static Bool EnterVT(ScrnInfoPtr pScrn);
@@ -1495,11 +1502,66 @@ msSharedPixmapNotifyDamage(PixmapPtr ppix)
     return ret;
 }
 
+static int
+send_fd(int sock, int fd)
+{
+    // This function does the arcane magic for sending
+    // 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)));
+
+    data[0] = ' ';
+    iov[0].iov_base = data;
+    iov[0].iov_len = sizeof(data);
+
+    msg.msg_name = NULL;
+    msg.msg_namelen = 0;
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+    msg.msg_controllen =  CMSG_SPACE(sizeof(int));
+    msg.msg_control = ctrl_buf;
+
+    cmsg = CMSG_FIRSTHDR(&msg);
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type = SCM_RIGHTS;
+    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+
+    *((int *) CMSG_DATA(cmsg)) = fd;
+
+    return sendmsg(sock, &msg, 0);
+}
+
+static void*
+thread_func(void* argument)
+{
+    int ret;
+    int option = *(int *)argument;
+    char cmd[32];
+    sprintf(cmd, "/usr/bin/drm_master_util %s -r", (!option ? "-s" : "-d"));
+
+    ret = system(cmd);
+    if (ret == -1 || WEXITSTATUS(ret) != 0) {
+        fprintf(stderr, "%s\n", strerror(errno));
+        //exit(1);
+    }
+
+    pthread_exit(NULL); // you could also return NULL here to exit no difference
+}
+
 static Bool
 SetMaster(ScrnInfoPtr pScrn)
 {
     modesettingPtr ms = modesettingPTR(pScrn);
-    int ret;
+    int ret = 0;
+    pthread_t my_thread;
+    struct sockaddr_un addr;
+    int sock, conn, option = 0;
 
 #ifdef XF86_PDEV_SERVER_FD
     if (ms->pEnt->location.type == BUS_PLATFORM &&
@@ -1507,10 +1569,25 @@ SetMaster(ScrnInfoPtr pScrn)
         return TRUE;
 #endif
 
-    ret = drmSetMaster(ms->fd);
-    if (ret)
+    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);
+    bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+
+    listen(sock, 1);
+    pthread_create(&my_thread, NULL, thread_func, &option);
+
+    conn = accept(sock, NULL, 0);
+    send_fd(conn, ms->fd);
+    close(conn);
+    close(sock);
+
+    pthread_join(my_thread, NULL);
+
+    /*if (ret == -1 || WEXITSTATUS(ret) != 0)
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n",
-                   strerror(errno));
+                   strerror(errno));*/
 
     return ret == 0;
 }
@@ -1749,6 +1826,9 @@ static void
 LeaveVT(ScrnInfoPtr pScrn)
 {
     modesettingPtr ms = modesettingPTR(pScrn);
+    pthread_t my_thread;
+    struct sockaddr_un addr;
+    int sock, conn, option = 1;
 
     xf86_hide_cursors(pScrn);
 
@@ -1760,7 +1840,21 @@ LeaveVT(ScrnInfoPtr pScrn)
         return;
 #endif
 
-    drmDropMaster(ms->fd);
+    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);
+    bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+
+    listen(sock, 1);
+    pthread_create(&my_thread, NULL, thread_func, &option);
+
+    conn = accept(sock, NULL, 0);
+    send_fd(conn, ms->fd);
+    close(conn);
+    close(sock);
+
+    pthread_join(my_thread, NULL);
 }
 
 /*
ch1p
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.