request_key.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /* request_key.c: request a key from userspace
  2. *
  3. * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/sched.h>
  13. #include <linux/kmod.h>
  14. #include <linux/err.h>
  15. #include "internal.h"
  16. struct key_construction {
  17. struct list_head link; /* link in construction queue */
  18. struct key *key; /* key being constructed */
  19. };
  20. /* when waiting for someone else's keys, you get added to this */
  21. DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
  22. /*****************************************************************************/
  23. /*
  24. * request userspace finish the construction of a key
  25. * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
  26. * - if callout_info is an empty string, it'll be rendered as a "-" instead
  27. */
  28. static int call_request_key(struct key *key,
  29. const char *op,
  30. const char *callout_info)
  31. {
  32. struct task_struct *tsk = current;
  33. unsigned long flags;
  34. key_serial_t prkey, sskey;
  35. char *argv[10], *envp[3], uid_str[12], gid_str[12];
  36. char key_str[12], keyring_str[3][12];
  37. int i;
  38. /* record the UID and GID */
  39. sprintf(uid_str, "%d", current->fsuid);
  40. sprintf(gid_str, "%d", current->fsgid);
  41. /* we say which key is under construction */
  42. sprintf(key_str, "%d", key->serial);
  43. /* we specify the process's default keyrings */
  44. sprintf(keyring_str[0], "%d",
  45. tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
  46. prkey = 0;
  47. if (tsk->signal->process_keyring)
  48. prkey = tsk->signal->process_keyring->serial;
  49. sskey = 0;
  50. spin_lock_irqsave(&tsk->sighand->siglock, flags);
  51. if (tsk->signal->session_keyring)
  52. sskey = tsk->signal->session_keyring->serial;
  53. spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
  54. if (!sskey)
  55. sskey = tsk->user->session_keyring->serial;
  56. sprintf(keyring_str[1], "%d", prkey);
  57. sprintf(keyring_str[2], "%d", sskey);
  58. /* set up a minimal environment */
  59. i = 0;
  60. envp[i++] = "HOME=/";
  61. envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
  62. envp[i] = NULL;
  63. /* set up the argument list */
  64. i = 0;
  65. argv[i++] = "/sbin/request-key";
  66. argv[i++] = (char *) op;
  67. argv[i++] = key_str;
  68. argv[i++] = uid_str;
  69. argv[i++] = gid_str;
  70. argv[i++] = keyring_str[0];
  71. argv[i++] = keyring_str[1];
  72. argv[i++] = keyring_str[2];
  73. argv[i++] = callout_info[0] ? (char *) callout_info : "-";
  74. argv[i] = NULL;
  75. /* do it */
  76. return call_usermodehelper(argv[0], argv, envp, 1);
  77. } /* end call_request_key() */
  78. /*****************************************************************************/
  79. /*
  80. * call out to userspace for the key
  81. * - called with the construction sem held, but the sem is dropped here
  82. * - we ignore program failure and go on key status instead
  83. */
  84. static struct key *__request_key_construction(struct key_type *type,
  85. const char *description,
  86. const char *callout_info)
  87. {
  88. struct key_construction cons;
  89. struct timespec now;
  90. struct key *key;
  91. int ret, negated;
  92. /* create a key and add it to the queue */
  93. key = key_alloc(type, description,
  94. current->fsuid, current->fsgid, KEY_USR_ALL, 0);
  95. if (IS_ERR(key))
  96. goto alloc_failed;
  97. set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
  98. cons.key = key;
  99. list_add_tail(&cons.link, &key->user->consq);
  100. /* we drop the construction sem here on behalf of the caller */
  101. up_write(&key_construction_sem);
  102. /* make the call */
  103. ret = call_request_key(key, "create", callout_info);
  104. if (ret < 0)
  105. goto request_failed;
  106. /* if the key wasn't instantiated, then we want to give an error */
  107. ret = -ENOKEY;
  108. if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
  109. goto request_failed;
  110. down_write(&key_construction_sem);
  111. list_del(&cons.link);
  112. up_write(&key_construction_sem);
  113. /* also give an error if the key was negatively instantiated */
  114. check_not_negative:
  115. if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
  116. key_put(key);
  117. key = ERR_PTR(-ENOKEY);
  118. }
  119. out:
  120. return key;
  121. request_failed:
  122. /* it wasn't instantiated
  123. * - remove from construction queue
  124. * - mark the key as dead
  125. */
  126. negated = 0;
  127. down_write(&key_construction_sem);
  128. list_del(&cons.link);
  129. /* check it didn't get instantiated between the check and the down */
  130. if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
  131. set_bit(KEY_FLAG_NEGATIVE, &key->flags);
  132. set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
  133. negated = 1;
  134. }
  135. clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
  136. up_write(&key_construction_sem);
  137. if (!negated)
  138. goto check_not_negative; /* surprisingly, the key got
  139. * instantiated */
  140. /* set the timeout and store in the session keyring if we can */
  141. now = current_kernel_time();
  142. key->expiry = now.tv_sec + key_negative_timeout;
  143. if (current->signal->session_keyring) {
  144. unsigned long flags;
  145. struct key *keyring;
  146. spin_lock_irqsave(&current->sighand->siglock, flags);
  147. keyring = current->signal->session_keyring;
  148. atomic_inc(&keyring->usage);
  149. spin_unlock_irqrestore(&current->sighand->siglock, flags);
  150. key_link(keyring, key);
  151. key_put(keyring);
  152. }
  153. key_put(key);
  154. /* notify anyone who was waiting */
  155. wake_up_all(&request_key_conswq);
  156. key = ERR_PTR(ret);
  157. goto out;
  158. alloc_failed:
  159. up_write(&key_construction_sem);
  160. goto out;
  161. } /* end __request_key_construction() */
  162. /*****************************************************************************/
  163. /*
  164. * call out to userspace to request the key
  165. * - we check the construction queue first to see if an appropriate key is
  166. * already being constructed by userspace
  167. */
  168. static struct key *request_key_construction(struct key_type *type,
  169. const char *description,
  170. struct key_user *user,
  171. const char *callout_info)
  172. {
  173. struct key_construction *pcons;
  174. struct key *key, *ckey;
  175. DECLARE_WAITQUEUE(myself, current);
  176. /* see if there's such a key under construction already */
  177. down_write(&key_construction_sem);
  178. list_for_each_entry(pcons, &user->consq, link) {
  179. ckey = pcons->key;
  180. if (ckey->type != type)
  181. continue;
  182. if (type->match(ckey, description))
  183. goto found_key_under_construction;
  184. }
  185. /* see about getting userspace to construct the key */
  186. key = __request_key_construction(type, description, callout_info);
  187. error:
  188. return key;
  189. /* someone else has the same key under construction
  190. * - we want to keep an eye on their key
  191. */
  192. found_key_under_construction:
  193. atomic_inc(&ckey->usage);
  194. up_write(&key_construction_sem);
  195. /* wait for the key to be completed one way or another */
  196. add_wait_queue(&request_key_conswq, &myself);
  197. for (;;) {
  198. set_current_state(TASK_UNINTERRUPTIBLE);
  199. if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags))
  200. break;
  201. schedule();
  202. }
  203. set_current_state(TASK_RUNNING);
  204. remove_wait_queue(&request_key_conswq, &myself);
  205. /* we'll need to search this process's keyrings to see if the key is
  206. * now there since we can't automatically assume it's also available
  207. * there */
  208. key_put(ckey);
  209. ckey = NULL;
  210. key = NULL; /* request a retry */
  211. goto error;
  212. } /* end request_key_construction() */
  213. /*****************************************************************************/
  214. /*
  215. * request a key
  216. * - search the process's keyrings
  217. * - check the list of keys being created or updated
  218. * - call out to userspace for a key if requested (supplementary info can be
  219. * passed)
  220. */
  221. struct key *request_key(struct key_type *type,
  222. const char *description,
  223. const char *callout_info)
  224. {
  225. struct key_user *user;
  226. struct key *key;
  227. /* search all the process keyrings for a key */
  228. key = search_process_keyrings_aux(type, description, type->match);
  229. if (PTR_ERR(key) == -EAGAIN) {
  230. /* the search failed, but the keyrings were searchable, so we
  231. * should consult userspace if we can */
  232. key = ERR_PTR(-ENOKEY);
  233. if (!callout_info)
  234. goto error;
  235. /* - get hold of the user's construction queue */
  236. user = key_user_lookup(current->fsuid);
  237. if (!user) {
  238. key = ERR_PTR(-ENOMEM);
  239. goto error;
  240. }
  241. for (;;) {
  242. /* ask userspace (returns NULL if it waited on a key
  243. * being constructed) */
  244. key = request_key_construction(type, description,
  245. user, callout_info);
  246. if (key)
  247. break;
  248. /* someone else made the key we want, so we need to
  249. * search again as it might now be available to us */
  250. key = search_process_keyrings_aux(type, description,
  251. type->match);
  252. if (PTR_ERR(key) != -EAGAIN)
  253. break;
  254. }
  255. key_user_put(user);
  256. }
  257. error:
  258. return key;
  259. } /* end request_key() */
  260. EXPORT_SYMBOL(request_key);
  261. /*****************************************************************************/
  262. /*
  263. * validate a key
  264. */
  265. int key_validate(struct key *key)
  266. {
  267. struct timespec now;
  268. int ret = 0;
  269. if (key) {
  270. /* check it's still accessible */
  271. ret = -EKEYREVOKED;
  272. if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
  273. test_bit(KEY_FLAG_DEAD, &key->flags))
  274. goto error;
  275. /* check it hasn't expired */
  276. ret = 0;
  277. if (key->expiry) {
  278. now = current_kernel_time();
  279. if (now.tv_sec >= key->expiry)
  280. ret = -EKEYEXPIRED;
  281. }
  282. }
  283. error:
  284. return ret;
  285. } /* end key_validate() */
  286. EXPORT_SYMBOL(key_validate);