manifest.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. #define _GNU_SOURCE 1
  4. #ifndef __GNUC__
  5. #define __GNUC__ 1
  6. #endif
  7. #ifdef IN_PAL
  8. # include "pal_defs.h"
  9. # include "pal_linux_defs.h"
  10. # include "pal.h"
  11. # include "pal_internal.h"
  12. # include "pal_linux.h"
  13. # include "pal_debug.h"
  14. # include "pal_error.h"
  15. #else
  16. # include "internal.h"
  17. #endif
  18. #include "graphene.h"
  19. #include "pal_security.h"
  20. #include "api.h"
  21. #include <sys/socket.h>
  22. #include <linux/unistd.h>
  23. #include <asm/fcntl.h>
  24. #include <asm/mman.h>
  25. #include <asm/errno.h>
  26. static inline int is_file_uri (const char * uri)
  27. {
  28. return strpartcmp_static(uri, "file:");
  29. }
  30. static inline const char * file_uri_to_path (const char * uri, int len)
  31. {
  32. int prefix_len = static_strlen("file:");
  33. char * path;
  34. if (len == prefix_len) {
  35. path = malloc(2);
  36. if (!path)
  37. return NULL;
  38. path[0] = '.';
  39. path[1] = 0;
  40. return path;
  41. }
  42. path = malloc(len - prefix_len + 1);
  43. if (!path)
  44. return NULL;
  45. memcpy(path, uri + prefix_len, len - prefix_len + 1);
  46. return path;
  47. }
  48. static const char * __get_path (struct config_store * config, const char * key)
  49. {
  50. char uri[CONFIG_MAX];
  51. if (get_config(config, key, uri, CONFIG_MAX) <= 0 ||
  52. !is_file_uri(uri))
  53. return NULL;
  54. return file_uri_to_path(uri, strlen(uri));
  55. }
  56. #define PRELOAD_MAX 16
  57. int get_preload_paths (struct config_store * config, const char *** paths)
  58. {
  59. char cfgbuf[CONFIG_MAX];
  60. if (get_config(config, "loader.preload", cfgbuf, CONFIG_MAX) <= 0)
  61. return 0;
  62. const char * p = cfgbuf, * n;
  63. const char * preload_paths[PRELOAD_MAX];
  64. int npreload = 0;
  65. while (*p && npreload < PRELOAD_MAX) {
  66. for (n = p ; *n && *n != ',' ; n++);
  67. if (!is_file_uri(p))
  68. goto next;
  69. if (!(preload_paths[npreload++] = file_uri_to_path(p, n - p)))
  70. return -ENOMEM;
  71. next:
  72. p = *n ? n + 1 : n;
  73. }
  74. *paths = malloc(sizeof(const char *) * npreload);
  75. if (!(*paths))
  76. return -ENOMEM;
  77. memcpy((*paths), preload_paths, sizeof(const char *) * npreload);
  78. return npreload;
  79. }
  80. int get_fs_paths (struct config_store * config, const char *** paths)
  81. {
  82. char * keys;
  83. int nkeys;
  84. ssize_t cfgsize;
  85. cfgsize = get_config_entries_size(config, "fs.mount");
  86. if (cfgsize)
  87. return 0;
  88. keys = __alloca(cfgsize);
  89. if ((nkeys = get_config_entries(config, "fs.mount", keys, cfgsize)) < 0)
  90. nkeys = 0;
  91. *paths = malloc(sizeof(const char *) * (1 + nkeys));
  92. if (!(*paths))
  93. return -ENOMEM;
  94. (*paths)[0] = ".";
  95. int npaths = 1;
  96. if (!nkeys)
  97. goto out;
  98. char key[CONFIG_MAX], * k = keys, * n;
  99. char * tmp;
  100. tmp = strcpy_static(key, "fs.mount.", CONFIG_MAX);
  101. for (int i = 0 ; i < nkeys ; i++) {
  102. for (n = k ; *n ; n++);
  103. int len = n - k;
  104. memcpy(tmp, k, len);
  105. strcpy_static(tmp + len, ".uri", (key + CONFIG_MAX) - (tmp + len));
  106. const char * path = __get_path(config, key);
  107. if (path)
  108. (*paths)[npaths++] = path;
  109. k = n + 1;
  110. }
  111. out:
  112. return npaths;
  113. }
  114. int get_net_rules (struct config_store * config,
  115. struct graphene_net_rule ** net_rules,
  116. int * nbind_rules)
  117. {
  118. char * binds, * peers;
  119. int nbinds, npeers;
  120. int nrules = 0;
  121. ssize_t cfgsize;
  122. cfgsize = get_config_entries_size(config, "net.allow_bind");
  123. if (cfgsize < 0)
  124. return 0;
  125. binds = __alloca(cfgsize);
  126. if ((nbinds = get_config_entries(config, "net.allow_bind", binds, cfgsize)) < 0)
  127. return 0;
  128. cfgsize = get_config_entries_size(config, "net.allow_peer");
  129. if (cfgsize < 0)
  130. return 0;
  131. peers = __alloca(cfgsize);
  132. if ((npeers = get_config_entries(config, "net.allow_peer", peers, cfgsize)) < 0)
  133. return 0;
  134. struct graphene_net_rule * rules =
  135. malloc(sizeof(struct graphene_net_rule) * (nbinds + npeers));
  136. if (!rules)
  137. return -ENOMEM;
  138. for (int t = 0 ; t < 2 ; t ++) {
  139. char key[CONFIG_MAX], * k, * n;
  140. char * tmp;
  141. int nadded;
  142. if (t == 0) {
  143. if (!nbinds)
  144. continue;
  145. k = binds;
  146. nadded = nbinds;
  147. tmp = strcpy_static(key, "net.allow_bind.", CONFIG_MAX);
  148. } else {
  149. if (!npeers)
  150. continue;
  151. k = peers;
  152. nadded = npeers;
  153. tmp = strcpy_static(key, "net.allow_peer.", CONFIG_MAX);
  154. }
  155. for (int i = 0 ; i < nadded ; i++) {
  156. struct graphene_net_rule * r = &rules[nrules];
  157. char cfgbuf[CONFIG_MAX];
  158. for (n = k ; *n ; n++);
  159. int len = n - k;
  160. memcpy(tmp, k, len + 1);
  161. tmp[len] = 0;
  162. ssize_t cfglen = get_config(config, key, cfgbuf, CONFIG_MAX);
  163. if (cfglen <= 0)
  164. goto next;
  165. char * c = cfgbuf, * end = cfgbuf + cfglen;
  166. char * addr = c, * num;
  167. int addrlen;
  168. r->family = AF_INET;
  169. if (*c == '[') {
  170. r->family = AF_INET6;
  171. addr++;
  172. for ( ; c < end && *c != ']' ; c++);
  173. if (c == end)
  174. goto next;
  175. addrlen = c - addr;
  176. c++;
  177. if (c == end || *c != ':')
  178. goto next;
  179. } else {
  180. for ( ; c < end && *c != ':' ; c++);
  181. if (c == end)
  182. goto next;
  183. addrlen = c - addr;
  184. }
  185. c++;
  186. if (c == end)
  187. goto next;
  188. num = c;
  189. for ( ; c < end && *c >= '0' && *c <= '9' ; c++);
  190. if (c == num)
  191. goto next;
  192. r->addr.port_end = r->addr.port_begin = atoi(num);
  193. if (c < end && *c == '-') {
  194. num = (++c);
  195. for ( ; c < end && *c >= '0' && *c <= '9' ; c++);
  196. if (c == num)
  197. goto next;
  198. r->addr.port_end = atoi(num);
  199. }
  200. if (r->family == AF_INET) {
  201. if (!inet_pton4(addr, addrlen, &r->addr.addr))
  202. goto next;
  203. } else {
  204. if (!inet_pton6(addr, addrlen, &r->addr.addr))
  205. goto next;
  206. }
  207. nrules++;
  208. next:
  209. k = n + 1;
  210. }
  211. if (t == 0)
  212. *nbind_rules = nrules;
  213. }
  214. *net_rules = rules;
  215. return nrules;
  216. }
  217. int ioctl_set_graphene (struct config_store * config, int ndefault,
  218. const struct graphene_user_policy * default_policies)
  219. {
  220. int ro = GRAPHENE_FS_READ, rw = ro | GRAPHENE_FS_WRITE;
  221. int ret = 0;
  222. const char ** preload_paths = NULL;
  223. const char ** fs_paths = NULL;
  224. struct graphene_net_rule * net_rules = NULL;
  225. int npreload = 0, nfs = 0, net = 0, bind_rules = 0;
  226. int fd = -1;
  227. int n = 0;
  228. npreload = get_preload_paths(config, &preload_paths);
  229. if (npreload < 0) {
  230. ret = npreload;
  231. goto out;
  232. }
  233. nfs = get_fs_paths(config, &fs_paths);
  234. if (nfs < 0) {
  235. ret = nfs;
  236. goto out;
  237. }
  238. net = get_net_rules(config, &net_rules, &bind_rules);
  239. if (net < 0) {
  240. ret = net;
  241. goto out;
  242. }
  243. struct graphene_policies * p =
  244. __alloca(sizeof(struct graphene_policies) +
  245. sizeof(struct graphene_user_policy) *
  246. (ndefault + npreload + nfs + net));
  247. memcpy(&p->policies[n], default_policies,
  248. sizeof(struct graphene_user_policy) * ndefault);
  249. n += ndefault;
  250. for (int i = 0 ; i < npreload ; i++) {
  251. p->policies[n].type = GRAPHENE_FS_PATH | ro;
  252. p->policies[n].value = preload_paths[i];
  253. n++;
  254. }
  255. for (int i = 0 ; i < nfs ; i++) {
  256. p->policies[n].type = GRAPHENE_FS_PATH | GRAPHENE_FS_RECURSIVE | rw;
  257. p->policies[n].value = fs_paths[i];
  258. n++;
  259. }
  260. for (int i = 0 ; i < net ; i++) {
  261. p->policies[n].type = GRAPHENE_NET_RULE;
  262. if (i < bind_rules)
  263. p->policies[n].type |= GRAPHENE_NET_BIND;
  264. p->policies[n].value = &net_rules[i];
  265. n++;
  266. }
  267. p->npolicies = n;
  268. fd = INLINE_SYSCALL(open, 3, GRAPHENE_FILE, O_RDONLY, 0);
  269. if (IS_ERR(fd)) {
  270. ret = -ERRNO(fd);
  271. goto out;
  272. }
  273. ret = INLINE_SYSCALL(ioctl, 3, fd, GRAPHENE_SET_TASK, p);
  274. ret = IS_ERR(ret) ? -ERRNO(ret) : 0;
  275. out:
  276. if (fd != -1)
  277. INLINE_SYSCALL(close, 1, fd);
  278. if (preload_paths) {
  279. for (int i = 0 ; i < npreload ; i++)
  280. free((void *) preload_paths[i]);
  281. free(preload_paths);
  282. }
  283. if (fs_paths) {
  284. for (int i = 0 ; i < nfs ; i++)
  285. free((void *) fs_paths[i]);
  286. free(fs_paths);
  287. }
  288. if (net_rules)
  289. free(net_rules);
  290. return ret;
  291. }