ecore-drm: Cleanup ecore_drm init/shutdown functions

As we don't need to spawn the suid binary anymore, we can remove all
the old code that was doing socketpair, passing messages, etc, etc.
Replace with proper ecore_drm_dbus function calls.

Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
Chris Michael 2014-07-15 09:28:03 -04:00
parent e711a294b2
commit 61070f779f
1 changed files with 15 additions and 295 deletions

View File

@ -3,256 +3,14 @@
#endif
#include "ecore_drm_private.h"
#include <sys/wait.h>
#include <sys/socket.h>
#include <signal.h>
#define RIGHTS_LEN CMSG_LEN(sizeof(int))
#define IOVSET(_iov, _addr, _len) \
(_iov)->iov_base = (void *)(_addr); \
(_iov)->iov_len = (_len);
/* local variables */
static int _ecore_drm_init_count = 0;
static int _ecore_drm_sockets[2] = { -1, -1 };
static struct cmsghdr *cmsgptr = NULL;
static char *sid;
/* external variables */
struct udev *udev;
int _ecore_drm_log_dom = -1;
#ifdef LOG_TO_FILE
FILE *lg;
#endif
static Eina_Bool
_ecore_drm_sockets_create(void)
{
if (_ecore_drm_sockets[0] > -1) return EINA_TRUE;
/* create a pair of sequenced sockets (fixed-length)
* NB: when reading from one of these, it is required that we read
* an entire packet with each read() call */
if (socketpair(AF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK,
0, _ecore_drm_sockets) < 0)
{
ERR("Socketpair Failed: %m");
return EINA_FALSE;
}
/* NB: We don't want cloexec for the sockets. That would cause them to be
* closed when we exec the child process but we need them open so that
* we can pass messages */
/* if (fcntl(_ecore_drm_sockets[0], F_SETFD, FD_CLOEXEC) < 0) */
/* { */
/* ERR("Failed to set CLOEXEC: %m"); */
/* return EINA_FALSE; */
/* } */
/* DBG("Parent Socket: %d", _ecore_drm_sockets[0]); */
/* DBG("Child Socket: %d", _ecore_drm_sockets[1]); */
return EINA_TRUE;
}
static Eina_Bool
_ecore_drm_launcher_spawn(void)
{
pid_t pid;
if ((pid = fork()) < 0) return EINA_FALSE;
if (pid == 0)
{
char renv[64], wenv[64], buff[PATH_MAX];
char *args[1] = { NULL };
sigset_t mask;
/* read socket for slave is 1 */
snprintf(renv, sizeof(renv), "ECORE_DRM_LAUNCHER_SOCKET_READ=%d",
_ecore_drm_sockets[1]);
/* write socket for slave is 0 */
snprintf(wenv, sizeof(wenv), "ECORE_DRM_LAUNCHER_SOCKET_WRITE=%d",
_ecore_drm_sockets[0]);
/* assemble exec path */
snprintf(buff, sizeof(buff),
"%s/ecore_drm/bin/%s/ecore_drm_launch",
PACKAGE_LIB_DIR, MODULE_ARCH);
/* don't give our signal mask to the child */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTTIN);
sigaddset(&mask, SIGTTOU);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
/* NB: We need to use execve here so that capabilities are inherited.
* Also, this should set Our (ecore_drm) effective uid to be the
* owner of the launched process (setuid in this case) */
char *ev[3] = { strdup(renv), strdup(wenv), NULL };
execve(buff, args, ev);
}
else
{
int status;
while (waitpid(pid, &status, WNOHANG) < 0)
if (errno != EINTR) break;
return EINA_TRUE;
}
return EINA_FALSE;
}
static ssize_t
_ecore_drm_socket_send(int opcode, int fd, void *data, size_t bytes)
{
Ecore_Drm_Message dmsg;
struct iovec iov[2];
struct msghdr msg;
ssize_t size;
int *iptr;
/* Simplified version of sending messages. We don't need to send any
* 'credentials' with this as it is just basically an IPC to send over
* our request to the slave process */
/* NB: Hmm, don't think we need to set any socket options here */
memset(&dmsg, 0, sizeof(dmsg));
IOVSET(iov + 0, &dmsg, sizeof(dmsg));
IOVSET(iov + 1, &data, bytes);
dmsg.opcode = opcode;
dmsg.size = bytes;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 2;
msg.msg_flags = 0;
if ((!cmsgptr) && (!(cmsgptr = malloc(RIGHTS_LEN))))
return -1;
cmsgptr->cmsg_level = SOL_SOCKET;
cmsgptr->cmsg_type = SCM_RIGHTS;
cmsgptr->cmsg_len = RIGHTS_LEN;
msg.msg_control = cmsgptr;
msg.msg_controllen = RIGHTS_LEN;
iptr = (int *)(CMSG_DATA(cmsgptr));
if (fd > -1) *iptr = fd;
else *iptr = _ecore_drm_sockets[1];
errno = 0;
size = sendmsg(_ecore_drm_sockets[1], &msg, MSG_EOR);
if (errno != 0)
{
DBG("Error Sending Message: %m");
}
/* DBG("Sent %li bytes to Socket %d", size, _ecore_drm_sockets[1]); */
return size;
}
static int
_ecore_drm_socket_receive(int opcode EINA_UNUSED, int *fd, void **data, size_t bytes)
{
int ret = ECORE_DRM_OP_FAILURE;
Ecore_Drm_Message dmsg;
struct cmsghdr *cmsg;
struct iovec iov[2];
struct msghdr msg;
char buff[CMSG_SPACE(sizeof(fd))];
int *iptr;
/* ssize_t size; */
memset(&dmsg, 0, sizeof(dmsg));
memset(&buff, 0, sizeof(buff));
IOVSET(iov + 0, &dmsg, sizeof(dmsg));
IOVSET(iov + 1, &buff, sizeof(buff));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 2;
msg.msg_flags = 0;
if ((!cmsgptr) && (!(cmsgptr = malloc(RIGHTS_LEN))))
return -1;
msg.msg_control = cmsgptr;
msg.msg_controllen = RIGHTS_LEN;
errno = 0;
recvmsg(_ecore_drm_sockets[0], &msg, 0);
if (errno != 0)
{
ERR("Failed to receive message: %m");
return -1;
}
/* DBG("Received %li bytes from %d", size, _ecore_drm_sockets[0]); */
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg))
{
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
switch (cmsg->cmsg_type)
{
case SCM_RIGHTS:
iptr = (int *)(CMSG_DATA(cmsg));
if (fd) *fd = *iptr;
switch (dmsg.opcode)
{
case ECORE_DRM_OP_DEVICE_OPEN:
case ECORE_DRM_OP_DEVICE_CLOSE:
case ECORE_DRM_OP_TTY_OPEN:
case ECORE_DRM_OP_DEVICE_MASTER_DROP:
case ECORE_DRM_OP_DEVICE_MASTER_SET:
if ((fd) && (*fd >= 0)) ret = ECORE_DRM_OP_SUCCESS;
if (data) memcpy(*data, buff, bytes);
break;
default:
break;
}
break;
default:
break;
}
}
return ret;
}
void
_ecore_drm_message_send(int opcode, int fd, void *data, size_t bytes)
{
_ecore_drm_socket_send(opcode, fd, data, bytes);
}
Eina_Bool
_ecore_drm_message_receive(int opcode, int *fd, void **data, size_t bytes)
{
int ret = ECORE_DRM_OP_FAILURE;
ret = _ecore_drm_socket_receive(opcode, fd, data, bytes);
if (ret != ECORE_DRM_OP_SUCCESS) return EINA_FALSE;
return EINA_TRUE;
}
/**
* @defgroup Ecore_Drm_Init_Group Drm Library Init and Shutdown Functions
@ -295,30 +53,6 @@ ecore_drm_init(void)
/* set logging level */
eina_log_level_set(EINA_LOG_LEVEL_DBG);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
/* optionally log output to a file */
#ifdef LOG_TO_FILE
int log_fd;
char log_path[PATH_MAX];
mode_t um;
/* assemble logging file path */
strcpy(log_path, "/tmp/ecore_drm_XXXXXX");
/* create temporary logging file */
um = umask(S_IRWXG | S_IRWXO);
log_fd = mkstemp(log_path);
umask(um);
/* try to open logging file */
if (!(lg = fdopen(log_fd, "w")))
goto log_err;
eina_log_print_cb_set(eina_log_print_cb_file, lg);
#endif
/* try to create logging domain */
_ecore_drm_log_dom =
eina_log_domain_register("ecore_drm", ECORE_DRM_DEFAULT_LOG_COLOR);
@ -332,39 +66,28 @@ ecore_drm_init(void)
if (!eina_log_domain_level_check(_ecore_drm_log_dom, EINA_LOG_LEVEL_DBG))
eina_log_domain_level_set("ecore_drm", EINA_LOG_LEVEL_DBG);
/* get sd-login properties we need */
if (sd_pid_get_session(getpid(), &sid) < 0) goto log_err;
/* try to init dbus */
if (!_ecore_drm_dbus_init(sid)) goto dbus_err;
/* try to init udev */
if (!(udev = udev_new()))
goto udev_err;
/* try to create the socketpair */
if (!_ecore_drm_sockets_create())
goto sock_err;
/* try to run Spartacus */
if (!_ecore_drm_launcher_spawn())
goto spawn_err;
if (!(udev = udev_new())) goto udev_err;
/* return init count */
return _ecore_drm_init_count;
spawn_err:
close(_ecore_drm_sockets[0]);
close(_ecore_drm_sockets[1]);
sock_err:
if (udev) udev_unref(udev);
udev_err:
_ecore_drm_dbus_shutdown();
dbus_err:
ecore_event_shutdown();
ecore_shutdown();
eina_log_domain_unregister(_ecore_drm_log_dom);
_ecore_drm_log_dom = -1;
free(sid);
log_err:
#ifdef LOG_TO_FILE
if (lg) fclose(lg);
#endif
/* shutdown eina */
eina_shutdown();
return --_ecore_drm_init_count;
}
@ -385,9 +108,8 @@ ecore_drm_shutdown(void)
/* close udev handle */
if (udev) udev_unref(udev);
/* close sockets */
close(_ecore_drm_sockets[0]);
close(_ecore_drm_sockets[1]);
/* cleanup dbus */
_ecore_drm_dbus_shutdown();
/* shutdown ecore_event */
ecore_event_shutdown();
@ -399,13 +121,11 @@ ecore_drm_shutdown(void)
eina_log_domain_unregister(_ecore_drm_log_dom);
_ecore_drm_log_dom = -1;
#ifdef LOG_TO_FILE
if (lg) fclose(lg);
#endif
/* shutdown eina */
eina_shutdown();
free(sid);
/* return init count */
return _ecore_drm_init_count;
}