summaryrefslogtreecommitdiff
path: root/src/lib/ecore_drm/ecore_drm.c
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2014-07-15 09:28:03 -0400
committerChris Michael <cp.michael@samsung.com>2014-07-15 09:44:14 -0400
commit61070f779fa73fbb515c72c905affe27c9874c7c (patch)
tree066481938b47416b2ad111eeb082e909a858cd6b /src/lib/ecore_drm/ecore_drm.c
parente711a294b23d4132a1ff3a0039948e2ca39e3735 (diff)
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>
Diffstat (limited to 'src/lib/ecore_drm/ecore_drm.c')
-rw-r--r--src/lib/ecore_drm/ecore_drm.c308
1 files changed, 14 insertions, 294 deletions
diff --git a/src/lib/ecore_drm/ecore_drm.c b/src/lib/ecore_drm/ecore_drm.c
index 0c938cb7c2..6900e67229 100644
--- a/src/lib/ecore_drm/ecore_drm.c
+++ b/src/lib/ecore_drm/ecore_drm.c
@@ -3,256 +3,14 @@
3#endif 3#endif
4 4
5#include "ecore_drm_private.h" 5#include "ecore_drm_private.h"
6#include <sys/wait.h>
7#include <sys/socket.h>
8#include <signal.h>
9
10#define RIGHTS_LEN CMSG_LEN(sizeof(int))
11
12#define IOVSET(_iov, _addr, _len) \
13 (_iov)->iov_base = (void *)(_addr); \
14 (_iov)->iov_len = (_len);
15 6
16/* local variables */ 7/* local variables */
17static int _ecore_drm_init_count = 0; 8static int _ecore_drm_init_count = 0;
18static int _ecore_drm_sockets[2] = { -1, -1 }; 9static char *sid;
19static struct cmsghdr *cmsgptr = NULL;
20 10
21/* external variables */ 11/* external variables */
22struct udev *udev; 12struct udev *udev;
23int _ecore_drm_log_dom = -1; 13int _ecore_drm_log_dom = -1;
24#ifdef LOG_TO_FILE
25FILE *lg;
26#endif
27
28static Eina_Bool
29_ecore_drm_sockets_create(void)
30{
31 if (_ecore_drm_sockets[0] > -1) return EINA_TRUE;
32
33 /* create a pair of sequenced sockets (fixed-length)
34 * NB: when reading from one of these, it is required that we read
35 * an entire packet with each read() call */
36 if (socketpair(AF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK,
37 0, _ecore_drm_sockets) < 0)
38 {
39 ERR("Socketpair Failed: %m");
40 return EINA_FALSE;
41 }
42
43 /* NB: We don't want cloexec for the sockets. That would cause them to be
44 * closed when we exec the child process but we need them open so that
45 * we can pass messages */
46 /* if (fcntl(_ecore_drm_sockets[0], F_SETFD, FD_CLOEXEC) < 0) */
47 /* { */
48 /* ERR("Failed to set CLOEXEC: %m"); */
49 /* return EINA_FALSE; */
50 /* } */
51
52 /* DBG("Parent Socket: %d", _ecore_drm_sockets[0]); */
53 /* DBG("Child Socket: %d", _ecore_drm_sockets[1]); */
54
55 return EINA_TRUE;
56}
57
58static Eina_Bool
59_ecore_drm_launcher_spawn(void)
60{
61 pid_t pid;
62
63 if ((pid = fork()) < 0) return EINA_FALSE;
64
65 if (pid == 0)
66 {
67 char renv[64], wenv[64], buff[PATH_MAX];
68 char *args[1] = { NULL };
69 sigset_t mask;
70
71 /* read socket for slave is 1 */
72 snprintf(renv, sizeof(renv), "ECORE_DRM_LAUNCHER_SOCKET_READ=%d",
73 _ecore_drm_sockets[1]);
74
75 /* write socket for slave is 0 */
76 snprintf(wenv, sizeof(wenv), "ECORE_DRM_LAUNCHER_SOCKET_WRITE=%d",
77 _ecore_drm_sockets[0]);
78
79 /* assemble exec path */
80 snprintf(buff, sizeof(buff),
81 "%s/ecore_drm/bin/%s/ecore_drm_launch",
82 PACKAGE_LIB_DIR, MODULE_ARCH);
83
84 /* don't give our signal mask to the child */
85 sigemptyset(&mask);
86 sigaddset(&mask, SIGTERM);
87 sigaddset(&mask, SIGCHLD);
88 sigaddset(&mask, SIGINT);
89 sigaddset(&mask, SIGTTIN);
90 sigaddset(&mask, SIGTTOU);
91 sigprocmask(SIG_UNBLOCK, &mask, NULL);
92
93 /* NB: We need to use execve here so that capabilities are inherited.
94 * Also, this should set Our (ecore_drm) effective uid to be the
95 * owner of the launched process (setuid in this case) */
96 char *ev[3] = { strdup(renv), strdup(wenv), NULL };
97 execve(buff, args, ev);
98 }
99 else
100 {
101 int status;
102
103 while (waitpid(pid, &status, WNOHANG) < 0)
104 if (errno != EINTR) break;
105
106 return EINA_TRUE;
107 }
108
109 return EINA_FALSE;
110}
111
112static ssize_t
113_ecore_drm_socket_send(int opcode, int fd, void *data, size_t bytes)
114{
115 Ecore_Drm_Message dmsg;
116 struct iovec iov[2];
117 struct msghdr msg;
118 ssize_t size;
119 int *iptr;
120
121 /* Simplified version of sending messages. We don't need to send any
122 * 'credentials' with this as it is just basically an IPC to send over
123 * our request to the slave process */
124
125 /* NB: Hmm, don't think we need to set any socket options here */
126
127 memset(&dmsg, 0, sizeof(dmsg));
128
129 IOVSET(iov + 0, &dmsg, sizeof(dmsg));
130 IOVSET(iov + 1, &data, bytes);
131
132 dmsg.opcode = opcode;
133 dmsg.size = bytes;
134
135 msg.msg_name = NULL;
136 msg.msg_namelen = 0;
137 msg.msg_iov = iov;
138 msg.msg_iovlen = 2;
139 msg.msg_flags = 0;
140
141 if ((!cmsgptr) && (!(cmsgptr = malloc(RIGHTS_LEN))))
142 return -1;
143
144 cmsgptr->cmsg_level = SOL_SOCKET;
145 cmsgptr->cmsg_type = SCM_RIGHTS;
146 cmsgptr->cmsg_len = RIGHTS_LEN;
147
148 msg.msg_control = cmsgptr;
149 msg.msg_controllen = RIGHTS_LEN;
150
151 iptr = (int *)(CMSG_DATA(cmsgptr));
152 if (fd > -1) *iptr = fd;
153 else *iptr = _ecore_drm_sockets[1];
154
155 errno = 0;
156 size = sendmsg(_ecore_drm_sockets[1], &msg, MSG_EOR);
157 if (errno != 0)
158 {
159 DBG("Error Sending Message: %m");
160 }
161
162 /* DBG("Sent %li bytes to Socket %d", size, _ecore_drm_sockets[1]); */
163
164 return size;
165}
166
167static int
168_ecore_drm_socket_receive(int opcode EINA_UNUSED, int *fd, void **data, size_t bytes)
169{
170 int ret = ECORE_DRM_OP_FAILURE;
171 Ecore_Drm_Message dmsg;
172 struct cmsghdr *cmsg;
173 struct iovec iov[2];
174 struct msghdr msg;
175 char buff[CMSG_SPACE(sizeof(fd))];
176 int *iptr;
177 /* ssize_t size; */
178
179 memset(&dmsg, 0, sizeof(dmsg));
180 memset(&buff, 0, sizeof(buff));
181
182 IOVSET(iov + 0, &dmsg, sizeof(dmsg));
183 IOVSET(iov + 1, &buff, sizeof(buff));
184
185 msg.msg_name = NULL;
186 msg.msg_namelen = 0;
187 msg.msg_iov = iov;
188 msg.msg_iovlen = 2;
189 msg.msg_flags = 0;
190
191 if ((!cmsgptr) && (!(cmsgptr = malloc(RIGHTS_LEN))))
192 return -1;
193
194 msg.msg_control = cmsgptr;
195 msg.msg_controllen = RIGHTS_LEN;
196
197 errno = 0;
198 recvmsg(_ecore_drm_sockets[0], &msg, 0);
199 if (errno != 0)
200 {
201 ERR("Failed to receive message: %m");
202 return -1;
203 }
204
205 /* DBG("Received %li bytes from %d", size, _ecore_drm_sockets[0]); */
206
207 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
208 cmsg = CMSG_NXTHDR(&msg, cmsg))
209 {
210 if (cmsg->cmsg_level != SOL_SOCKET)
211 continue;
212
213 switch (cmsg->cmsg_type)
214 {
215 case SCM_RIGHTS:
216 iptr = (int *)(CMSG_DATA(cmsg));
217 if (fd) *fd = *iptr;
218 switch (dmsg.opcode)
219 {
220 case ECORE_DRM_OP_DEVICE_OPEN:
221 case ECORE_DRM_OP_DEVICE_CLOSE:
222 case ECORE_DRM_OP_TTY_OPEN:
223 case ECORE_DRM_OP_DEVICE_MASTER_DROP:
224 case ECORE_DRM_OP_DEVICE_MASTER_SET:
225 if ((fd) && (*fd >= 0)) ret = ECORE_DRM_OP_SUCCESS;
226 if (data) memcpy(*data, buff, bytes);
227 break;
228 default:
229 break;
230 }
231 break;
232 default:
233 break;
234 }
235 }
236
237 return ret;
238}
239
240void
241_ecore_drm_message_send(int opcode, int fd, void *data, size_t bytes)
242{
243 _ecore_drm_socket_send(opcode, fd, data, bytes);
244}
245
246Eina_Bool
247_ecore_drm_message_receive(int opcode, int *fd, void **data, size_t bytes)
248{
249 int ret = ECORE_DRM_OP_FAILURE;
250
251 ret = _ecore_drm_socket_receive(opcode, fd, data, bytes);
252 if (ret != ECORE_DRM_OP_SUCCESS) return EINA_FALSE;
253
254 return EINA_TRUE;
255}
256 14
257/** 15/**
258 * @defgroup Ecore_Drm_Init_Group Drm Library Init and Shutdown Functions 16 * @defgroup Ecore_Drm_Init_Group Drm Library Init and Shutdown Functions
@@ -295,30 +53,6 @@ ecore_drm_init(void)
295 /* set logging level */ 53 /* set logging level */
296 eina_log_level_set(EINA_LOG_LEVEL_DBG); 54 eina_log_level_set(EINA_LOG_LEVEL_DBG);
297 55
298 setvbuf(stdout, NULL, _IONBF, 0);
299 setvbuf(stderr, NULL, _IONBF, 0);
300
301 /* optionally log output to a file */
302#ifdef LOG_TO_FILE
303 int log_fd;
304 char log_path[PATH_MAX];
305 mode_t um;
306
307 /* assemble logging file path */
308 strcpy(log_path, "/tmp/ecore_drm_XXXXXX");
309
310 /* create temporary logging file */
311 um = umask(S_IRWXG | S_IRWXO);
312 log_fd = mkstemp(log_path);
313 umask(um);
314
315 /* try to open logging file */
316 if (!(lg = fdopen(log_fd, "w")))
317 goto log_err;
318
319 eina_log_print_cb_set(eina_log_print_cb_file, lg);
320#endif
321
322 /* try to create logging domain */ 56 /* try to create logging domain */
323 _ecore_drm_log_dom = 57 _ecore_drm_log_dom =
324 eina_log_domain_register("ecore_drm", ECORE_DRM_DEFAULT_LOG_COLOR); 58 eina_log_domain_register("ecore_drm", ECORE_DRM_DEFAULT_LOG_COLOR);
@@ -332,39 +66,28 @@ ecore_drm_init(void)
332 if (!eina_log_domain_level_check(_ecore_drm_log_dom, EINA_LOG_LEVEL_DBG)) 66 if (!eina_log_domain_level_check(_ecore_drm_log_dom, EINA_LOG_LEVEL_DBG))
333 eina_log_domain_level_set("ecore_drm", EINA_LOG_LEVEL_DBG); 67 eina_log_domain_level_set("ecore_drm", EINA_LOG_LEVEL_DBG);
334 68
335 /* try to init udev */ 69 /* get sd-login properties we need */
336 if (!(udev = udev_new())) 70 if (sd_pid_get_session(getpid(), &sid) < 0) goto log_err;
337 goto udev_err;
338 71
339 /* try to create the socketpair */ 72 /* try to init dbus */
340 if (!_ecore_drm_sockets_create()) 73 if (!_ecore_drm_dbus_init(sid)) goto dbus_err;
341 goto sock_err;
342 74
343 /* try to run Spartacus */ 75 /* try to init udev */
344 if (!_ecore_drm_launcher_spawn()) 76 if (!(udev = udev_new())) goto udev_err;
345 goto spawn_err;
346 77
347 /* return init count */ 78 /* return init count */
348 return _ecore_drm_init_count; 79 return _ecore_drm_init_count;
349 80
350spawn_err:
351 close(_ecore_drm_sockets[0]);
352 close(_ecore_drm_sockets[1]);
353sock_err:
354 if (udev) udev_unref(udev);
355udev_err: 81udev_err:
82 _ecore_drm_dbus_shutdown();
83dbus_err:
356 ecore_event_shutdown(); 84 ecore_event_shutdown();
357 ecore_shutdown(); 85 ecore_shutdown();
358 eina_log_domain_unregister(_ecore_drm_log_dom); 86 eina_log_domain_unregister(_ecore_drm_log_dom);
359 _ecore_drm_log_dom = -1; 87 _ecore_drm_log_dom = -1;
88 free(sid);
360log_err: 89log_err:
361#ifdef LOG_TO_FILE
362 if (lg) fclose(lg);
363#endif
364
365 /* shutdown eina */
366 eina_shutdown(); 90 eina_shutdown();
367
368 return --_ecore_drm_init_count; 91 return --_ecore_drm_init_count;
369} 92}
370 93
@@ -385,9 +108,8 @@ ecore_drm_shutdown(void)
385 /* close udev handle */ 108 /* close udev handle */
386 if (udev) udev_unref(udev); 109 if (udev) udev_unref(udev);
387 110
388 /* close sockets */ 111 /* cleanup dbus */
389 close(_ecore_drm_sockets[0]); 112 _ecore_drm_dbus_shutdown();
390 close(_ecore_drm_sockets[1]);
391 113
392 /* shutdown ecore_event */ 114 /* shutdown ecore_event */
393 ecore_event_shutdown(); 115 ecore_event_shutdown();
@@ -399,13 +121,11 @@ ecore_drm_shutdown(void)
399 eina_log_domain_unregister(_ecore_drm_log_dom); 121 eina_log_domain_unregister(_ecore_drm_log_dom);
400 _ecore_drm_log_dom = -1; 122 _ecore_drm_log_dom = -1;
401 123
402#ifdef LOG_TO_FILE
403 if (lg) fclose(lg);
404#endif
405
406 /* shutdown eina */ 124 /* shutdown eina */
407 eina_shutdown(); 125 eina_shutdown();
408 126
127 free(sid);
128
409 /* return init count */ 129 /* return init count */
410 return _ecore_drm_init_count; 130 return _ecore_drm_init_count;
411} 131}