hurdmsg.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /* Copyright (C) 1992-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #include <hurd.h>
  15. #include <hurd/msg_server.h>
  16. #include <hurd/fd.h>
  17. #include <unistd.h>
  18. #include <limits.h>
  19. #include <string.h>
  20. #include <argz.h>
  21. #define AUTHCHECK \
  22. if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
  23. return EPERM
  24. /* Snarfing and frobbing the init ports. */
  25. kern_return_t
  26. _S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which,
  27. mach_port_t *result, mach_msg_type_name_t *result_type)
  28. {
  29. error_t err;
  30. AUTHCHECK;
  31. *result_type = MACH_MSG_TYPE_MOVE_SEND;
  32. /* This function adds a new user reference for the *RESULT it gives back.
  33. Our reply message uses a move-send right that consumes this reference. */
  34. err = _hurd_ports_get (which, result);
  35. if (!err && MACH_PORT_VALID (auth))
  36. __mach_port_deallocate (__mach_task_self (), auth);
  37. return err;
  38. }
  39. kern_return_t
  40. _S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
  41. int which, mach_port_t port)
  42. {
  43. error_t err;
  44. AUTHCHECK;
  45. err = _hurd_ports_set (which, port);
  46. if (!err && MACH_PORT_VALID (port))
  47. __mach_port_deallocate (__mach_task_self (), port);
  48. if (!err && MACH_PORT_VALID (auth))
  49. __mach_port_deallocate (__mach_task_self (), auth);
  50. return err;
  51. }
  52. kern_return_t
  53. _S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
  54. mach_port_t **ports,
  55. mach_msg_type_name_t *ports_type,
  56. mach_msg_type_number_t *nports)
  57. {
  58. mach_msg_type_number_t i;
  59. error_t err;
  60. AUTHCHECK;
  61. if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports,
  62. _hurd_nports * sizeof (mach_port_t), 1))
  63. return err;
  64. *nports = _hurd_nports;
  65. for (i = 0; i < _hurd_nports; ++i)
  66. /* This function adds a new user ref for the *RESULT it gives back.
  67. Our reply message uses move-send rights that consumes this ref. */
  68. if (err = _hurd_ports_get (i, &(*ports)[i]))
  69. {
  70. /* Died part way through. Deallocate the ports already fetched. */
  71. while (i-- > 0)
  72. __mach_port_deallocate (__mach_task_self (), (*ports)[i]);
  73. __vm_deallocate (__mach_task_self (),
  74. (vm_address_t) *ports,
  75. *nports * sizeof (mach_port_t));
  76. return err;
  77. }
  78. *ports_type = MACH_MSG_TYPE_MOVE_SEND;
  79. if (MACH_PORT_VALID (auth))
  80. __mach_port_deallocate (__mach_task_self (), auth);
  81. return 0;
  82. }
  83. kern_return_t
  84. _S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
  85. const mach_port_t *ports, mach_msg_type_number_t nports)
  86. {
  87. mach_msg_type_number_t i;
  88. error_t err;
  89. AUTHCHECK;
  90. for (i = 0; i < _hurd_nports; ++i)
  91. {
  92. if (err = _hurd_ports_set (i, ports[i]))
  93. return err;
  94. else
  95. __mach_port_deallocate (__mach_task_self (), ports[i]);
  96. }
  97. if (MACH_PORT_VALID (auth))
  98. __mach_port_deallocate (__mach_task_self (), auth);
  99. return 0;
  100. }
  101. /* Snarfing and frobbing the init ints. */
  102. static kern_return_t
  103. get_int (int which, int *value)
  104. {
  105. switch (which)
  106. {
  107. case INIT_UMASK:
  108. *value = _hurd_umask;
  109. return 0;
  110. case INIT_SIGPENDING:
  111. {
  112. struct hurd_sigstate *ss = _hurd_global_sigstate;
  113. __spin_lock (&ss->lock);
  114. *value = ss->pending;
  115. __spin_unlock (&ss->lock);
  116. return 0;
  117. }
  118. case INIT_SIGIGN:
  119. {
  120. struct hurd_sigstate *ss = _hurd_global_sigstate;
  121. sigset_t ign;
  122. int sig;
  123. __spin_lock (&ss->lock);
  124. __sigemptyset (&ign);
  125. for (sig = 1; sig < NSIG; ++sig)
  126. if (ss->actions[sig].sa_handler == SIG_IGN)
  127. __sigaddset (&ign, sig);
  128. __spin_unlock (&ss->lock);
  129. *value = ign;
  130. return 0;
  131. }
  132. default:
  133. return EINVAL;
  134. }
  135. }
  136. kern_return_t
  137. _S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
  138. int which, int *value)
  139. {
  140. error_t err;
  141. AUTHCHECK;
  142. err = get_int (which, value);
  143. if (err)
  144. return err;
  145. if (MACH_PORT_VALID (auth))
  146. __mach_port_deallocate (__mach_task_self (), auth);
  147. return 0;
  148. }
  149. kern_return_t
  150. _S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
  151. int **values, mach_msg_type_number_t *nvalues)
  152. {
  153. error_t err;
  154. mach_msg_type_number_t i;
  155. AUTHCHECK;
  156. if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
  157. INIT_INT_MAX * sizeof (int), 1))
  158. return err;
  159. *nvalues = INIT_INT_MAX;
  160. for (i = 0; i < INIT_INT_MAX; ++i)
  161. switch (err = get_int (i, &(*values)[i]))
  162. {
  163. case 0: /* Success. */
  164. break;
  165. case EINVAL: /* Unknown index. */
  166. (*values)[i] = 0;
  167. break;
  168. default: /* Lossage. */
  169. __vm_deallocate (__mach_task_self (),
  170. (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
  171. return err;
  172. }
  173. if (MACH_PORT_VALID (auth))
  174. __mach_port_deallocate (__mach_task_self (), auth);
  175. return 0;
  176. }
  177. static kern_return_t
  178. set_int (int which, int value)
  179. {
  180. switch (which)
  181. {
  182. case INIT_UMASK:
  183. _hurd_umask = value;
  184. return 0;
  185. /* These are pretty odd things to do. But you asked for it. */
  186. case INIT_SIGPENDING:
  187. {
  188. struct hurd_sigstate *ss = _hurd_global_sigstate;
  189. __spin_lock (&ss->lock);
  190. ss->pending = value;
  191. __spin_unlock (&ss->lock);
  192. return 0;
  193. }
  194. case INIT_SIGIGN:
  195. {
  196. struct hurd_sigstate *ss = _hurd_global_sigstate;
  197. int sig;
  198. const sigset_t ign = value;
  199. __spin_lock (&ss->lock);
  200. for (sig = 1; sig < NSIG; ++sig)
  201. {
  202. if (__sigismember (&ign, sig))
  203. ss->actions[sig].sa_handler = SIG_IGN;
  204. else if (ss->actions[sig].sa_handler == SIG_IGN)
  205. ss->actions[sig].sa_handler = SIG_DFL;
  206. }
  207. __spin_unlock (&ss->lock);
  208. return 0;
  209. case INIT_TRACEMASK:
  210. _hurdsig_traced = value;
  211. return 0;
  212. }
  213. default:
  214. return EINVAL;
  215. }
  216. }
  217. kern_return_t
  218. _S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
  219. int which, int value)
  220. {
  221. error_t err;
  222. AUTHCHECK;
  223. err = set_int (which, value);
  224. if (err)
  225. return err;
  226. if (MACH_PORT_VALID (auth))
  227. __mach_port_deallocate (__mach_task_self (), auth);
  228. return 0;
  229. }
  230. kern_return_t
  231. _S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
  232. const int *values, mach_msg_type_number_t nvalues)
  233. {
  234. error_t err;
  235. mach_msg_type_number_t i;
  236. AUTHCHECK;
  237. for (i = 0; i < INIT_INT_MAX; ++i)
  238. switch (err = set_int (i, values[i]))
  239. {
  240. case 0: /* Success. */
  241. break;
  242. case EINVAL: /* Unknown index. */
  243. break;
  244. default: /* Lossage. */
  245. return err;
  246. }
  247. if (MACH_PORT_VALID (auth))
  248. __mach_port_deallocate (__mach_task_self (), auth);
  249. return 0;
  250. }
  251. kern_return_t
  252. _S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which,
  253. mach_port_t *result, mach_msg_type_name_t *result_type)
  254. {
  255. AUTHCHECK;
  256. /* This creates a new user reference for the send right.
  257. Our reply message will move that reference to the caller. */
  258. *result = __getdport (which);
  259. if (*result == MACH_PORT_NULL)
  260. return errno;
  261. *result_type = MACH_MSG_TYPE_MOVE_SEND;
  262. if (MACH_PORT_VALID (auth))
  263. __mach_port_deallocate (__mach_task_self (), auth);
  264. return 0;
  265. }
  266. kern_return_t
  267. _S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
  268. int which, mach_port_t port)
  269. {
  270. error_t err;
  271. AUTHCHECK;
  272. /* We consume the reference if successful. */
  273. err = HURD_FD_USE (which,
  274. ({
  275. int flags = (descriptor->flags & FD_CLOEXEC)
  276. ? O_CLOEXEC : 0;
  277. _hurd_port2fd (descriptor, port, flags);
  278. 0;
  279. }));
  280. if (err)
  281. return err;
  282. if (MACH_PORT_VALID (auth))
  283. __mach_port_deallocate (__mach_task_self (), auth);
  284. return 0;
  285. }
  286. /* Snarfing and frobbing environment variables. */
  287. kern_return_t
  288. _S_msg_get_env_variable (mach_port_t msgport,
  289. const_string_t variable,
  290. char **data, mach_msg_type_number_t *datalen)
  291. {
  292. error_t err;
  293. mach_msg_type_number_t valuelen;
  294. const char *value = getenv (variable);
  295. if (value == NULL)
  296. return ENOENT;
  297. valuelen = strlen (value);
  298. if (valuelen > *datalen)
  299. {
  300. if (err = __vm_allocate (__mach_task_self (),
  301. (vm_address_t *) data, valuelen, 1))
  302. return err;
  303. }
  304. memcpy (*data, value, valuelen);
  305. *datalen = valuelen;
  306. return 0;
  307. }
  308. kern_return_t
  309. _S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
  310. const_string_t variable,
  311. const_string_t value,
  312. int replace)
  313. {
  314. AUTHCHECK;
  315. if (__setenv (variable, value, replace)) /* XXX name space */
  316. return errno;
  317. if (MACH_PORT_VALID (auth))
  318. __mach_port_deallocate (__mach_task_self (), auth);
  319. return 0;
  320. }
  321. kern_return_t
  322. _S_msg_get_environment (mach_port_t msgport,
  323. char **data, mach_msg_type_number_t *datalen)
  324. {
  325. /* Pack the environment into an array with nulls separating elements. */
  326. if (__environ != NULL)
  327. {
  328. char *ap, **p;
  329. size_t envlen = 0;
  330. for (p = __environ; *p != NULL; ++p)
  331. envlen += strlen (*p) + 1;
  332. if (envlen > *datalen)
  333. {
  334. if (__vm_allocate (__mach_task_self (),
  335. (vm_address_t *) data, envlen, 1))
  336. return ENOMEM;
  337. }
  338. ap = *data;
  339. for (p = __environ; *p != NULL; ++p)
  340. ap = __memccpy (ap, *p, '\0', ULONG_MAX);
  341. *datalen = envlen;
  342. }
  343. else
  344. *datalen = 0;
  345. return 0;
  346. }
  347. kern_return_t
  348. _S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
  349. const char *data, mach_msg_type_number_t datalen)
  350. {
  351. int _hurd_split_args (char *, mach_msg_type_number_t, char **);
  352. int envc;
  353. char **envp;
  354. AUTHCHECK;
  355. envc = __argz_count (data, datalen);
  356. envp = malloc ((envc + 1) * sizeof (char *));
  357. if (envp == NULL)
  358. return errno;
  359. __argz_extract (data, datalen, envp);
  360. __environ = envp; /* XXX cooperate with loadenv et al */
  361. if (MACH_PORT_VALID (auth))
  362. __mach_port_deallocate (__mach_task_self (), auth);
  363. return 0;
  364. }
  365. kern_return_t
  366. _S_msg_get_dtable (mach_port_t process,
  367. mach_port_t auth,
  368. portarray_t *dtable,
  369. mach_msg_type_name_t *dtablePoly,
  370. mach_msg_type_number_t *dtableCnt)
  371. {
  372. mach_port_t *ports;
  373. mach_msg_type_number_t i;
  374. error_t err;
  375. AUTHCHECK;
  376. HURD_CRITICAL_BEGIN;
  377. __mutex_lock (&_hurd_dtable_lock);
  378. if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) &ports,
  379. _hurd_dtablesize * sizeof(mach_port_t), 1))
  380. goto out;
  381. for (i = 0; i < _hurd_dtablesize; i++)
  382. {
  383. struct hurd_fd *cell = _hurd_dtable[i];
  384. if (cell == NULL)
  385. ports[i] = MACH_PORT_NULL;
  386. else
  387. {
  388. __spin_lock (&cell->port.lock);
  389. if (cell->port.port == MACH_PORT_NULL)
  390. ports[i] = MACH_PORT_NULL;
  391. else
  392. {
  393. ports[i] = cell->port.port;
  394. /* We will move this send right. */
  395. __mach_port_mod_refs (__mach_task_self (), ports[i],
  396. MACH_PORT_RIGHT_SEND, +1);
  397. }
  398. __spin_unlock (&cell->port.lock);
  399. }
  400. }
  401. *dtable = ports;
  402. *dtablePoly = MACH_MSG_TYPE_MOVE_SEND;
  403. *dtableCnt = _hurd_dtablesize;
  404. out:
  405. __mutex_unlock (&_hurd_dtable_lock);
  406. HURD_CRITICAL_END;
  407. if (!err && MACH_PORT_VALID (auth))
  408. __mach_port_deallocate (__mach_task_self (), auth);
  409. return err;
  410. }
  411. /* XXX */
  412. kern_return_t
  413. _S_msg_set_dtable (mach_port_t process,
  414. mach_port_t refport,
  415. const_portarray_t dtable,
  416. mach_msg_type_number_t dtableCnt)
  417. { return EOPNOTSUPP; }