diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:14 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:14 -0500 |
commit | 8bbf4976b59fc9fc2861e79cab7beb3f6d647640 (patch) | |
tree | 9bd621217cbdfcf94aca5b220de7363254d7fc23 /security/keys/keyctl.c | |
parent | e9e349b051d98799b743ebf248cc2d986fedf090 (diff) |
KEYS: Alter use of key instantiation link-to-keyring argument
Alter the use of the key instantiation and negation functions' link-to-keyring
arguments. Currently this specifies a keyring in the target process to link
the key into, creating the keyring if it doesn't exist. This, however, can be
a problem for copy-on-write credentials as it means that the instantiating
process can alter the credentials of the requesting process.
This patch alters the behaviour such that:
(1) If keyctl_instantiate_key() or keyctl_negate_key() are given a specific
keyring by ID (ringid >= 0), then that keyring will be used.
(2) If keyctl_instantiate_key() or keyctl_negate_key() are given one of the
special constants that refer to the requesting process's keyrings
(KEY_SPEC_*_KEYRING, all <= 0), then:
(a) If sys_request_key() was given a keyring to use (destringid) then the
key will be attached to that keyring.
(b) If sys_request_key() was given a NULL keyring, then the key being
instantiated will be attached to the default keyring as set by
keyctl_set_reqkey_keyring().
(3) No extra link will be made.
Decision point (1) follows current behaviour, and allows those instantiators
who've searched for a specifically named keyring in the requestor's keyring so
as to partition the keys by type to still have their named keyrings.
Decision point (2) allows the requestor to make sure that the key or keys that
get produced by request_key() go where they want, whilst allowing the
instantiator to request that the key is retained. This is mainly useful for
situations where the instantiator makes a secondary request, the key for which
should be retained by the initial requestor:
+-----------+ +--------------+ +--------------+
| | | | | |
| Requestor |------->| Instantiator |------->| Instantiator |
| | | | | |
+-----------+ +--------------+ +--------------+
request_key() request_key()
This might be useful, for example, in Kerberos, where the requestor requests a
ticket, and then the ticket instantiator requests the TGT, which someone else
then has to go and fetch. The TGT, however, should be retained in the
keyrings of the requestor, not the first instantiator. To make this explict
an extra special keyring constant is also added.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 118 |
1 files changed, 71 insertions, 47 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 3f09e5b2a784..fcce331eca72 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -103,7 +103,7 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /* find the target keyring (which must be writable) */ | 105 | /* find the target keyring (which must be writable) */ |
106 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 106 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); |
107 | if (IS_ERR(keyring_ref)) { | 107 | if (IS_ERR(keyring_ref)) { |
108 | ret = PTR_ERR(keyring_ref); | 108 | ret = PTR_ERR(keyring_ref); |
109 | goto error3; | 109 | goto error3; |
@@ -185,7 +185,7 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
185 | /* get the destination keyring if specified */ | 185 | /* get the destination keyring if specified */ |
186 | dest_ref = NULL; | 186 | dest_ref = NULL; |
187 | if (destringid) { | 187 | if (destringid) { |
188 | dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); | 188 | dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE); |
189 | if (IS_ERR(dest_ref)) { | 189 | if (IS_ERR(dest_ref)) { |
190 | ret = PTR_ERR(dest_ref); | 190 | ret = PTR_ERR(dest_ref); |
191 | goto error3; | 191 | goto error3; |
@@ -235,7 +235,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) | |||
235 | key_ref_t key_ref; | 235 | key_ref_t key_ref; |
236 | long ret; | 236 | long ret; |
237 | 237 | ||
238 | key_ref = lookup_user_key(NULL, id, create, 0, KEY_SEARCH); | 238 | key_ref = lookup_user_key(id, create, 0, KEY_SEARCH); |
239 | if (IS_ERR(key_ref)) { | 239 | if (IS_ERR(key_ref)) { |
240 | ret = PTR_ERR(key_ref); | 240 | ret = PTR_ERR(key_ref); |
241 | goto error; | 241 | goto error; |
@@ -308,7 +308,7 @@ long keyctl_update_key(key_serial_t id, | |||
308 | } | 308 | } |
309 | 309 | ||
310 | /* find the target key (which must be writable) */ | 310 | /* find the target key (which must be writable) */ |
311 | key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); | 311 | key_ref = lookup_user_key(id, 0, 0, KEY_WRITE); |
312 | if (IS_ERR(key_ref)) { | 312 | if (IS_ERR(key_ref)) { |
313 | ret = PTR_ERR(key_ref); | 313 | ret = PTR_ERR(key_ref); |
314 | goto error2; | 314 | goto error2; |
@@ -336,7 +336,7 @@ long keyctl_revoke_key(key_serial_t id) | |||
336 | key_ref_t key_ref; | 336 | key_ref_t key_ref; |
337 | long ret; | 337 | long ret; |
338 | 338 | ||
339 | key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); | 339 | key_ref = lookup_user_key(id, 0, 0, KEY_WRITE); |
340 | if (IS_ERR(key_ref)) { | 340 | if (IS_ERR(key_ref)) { |
341 | ret = PTR_ERR(key_ref); | 341 | ret = PTR_ERR(key_ref); |
342 | goto error; | 342 | goto error; |
@@ -362,7 +362,7 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
362 | key_ref_t keyring_ref; | 362 | key_ref_t keyring_ref; |
363 | long ret; | 363 | long ret; |
364 | 364 | ||
365 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 365 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); |
366 | if (IS_ERR(keyring_ref)) { | 366 | if (IS_ERR(keyring_ref)) { |
367 | ret = PTR_ERR(keyring_ref); | 367 | ret = PTR_ERR(keyring_ref); |
368 | goto error; | 368 | goto error; |
@@ -388,13 +388,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) | |||
388 | key_ref_t keyring_ref, key_ref; | 388 | key_ref_t keyring_ref, key_ref; |
389 | long ret; | 389 | long ret; |
390 | 390 | ||
391 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 391 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); |
392 | if (IS_ERR(keyring_ref)) { | 392 | if (IS_ERR(keyring_ref)) { |
393 | ret = PTR_ERR(keyring_ref); | 393 | ret = PTR_ERR(keyring_ref); |
394 | goto error; | 394 | goto error; |
395 | } | 395 | } |
396 | 396 | ||
397 | key_ref = lookup_user_key(NULL, id, 1, 0, KEY_LINK); | 397 | key_ref = lookup_user_key(id, 1, 0, KEY_LINK); |
398 | if (IS_ERR(key_ref)) { | 398 | if (IS_ERR(key_ref)) { |
399 | ret = PTR_ERR(key_ref); | 399 | ret = PTR_ERR(key_ref); |
400 | goto error2; | 400 | goto error2; |
@@ -422,13 +422,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) | |||
422 | key_ref_t keyring_ref, key_ref; | 422 | key_ref_t keyring_ref, key_ref; |
423 | long ret; | 423 | long ret; |
424 | 424 | ||
425 | keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE); | 425 | keyring_ref = lookup_user_key(ringid, 0, 0, KEY_WRITE); |
426 | if (IS_ERR(keyring_ref)) { | 426 | if (IS_ERR(keyring_ref)) { |
427 | ret = PTR_ERR(keyring_ref); | 427 | ret = PTR_ERR(keyring_ref); |
428 | goto error; | 428 | goto error; |
429 | } | 429 | } |
430 | 430 | ||
431 | key_ref = lookup_user_key(NULL, id, 0, 0, 0); | 431 | key_ref = lookup_user_key(id, 0, 0, 0); |
432 | if (IS_ERR(key_ref)) { | 432 | if (IS_ERR(key_ref)) { |
433 | ret = PTR_ERR(key_ref); | 433 | ret = PTR_ERR(key_ref); |
434 | goto error2; | 434 | goto error2; |
@@ -464,7 +464,7 @@ long keyctl_describe_key(key_serial_t keyid, | |||
464 | char *tmpbuf; | 464 | char *tmpbuf; |
465 | long ret; | 465 | long ret; |
466 | 466 | ||
467 | key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); | 467 | key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW); |
468 | if (IS_ERR(key_ref)) { | 468 | if (IS_ERR(key_ref)) { |
469 | /* viewing a key under construction is permitted if we have the | 469 | /* viewing a key under construction is permitted if we have the |
470 | * authorisation token handy */ | 470 | * authorisation token handy */ |
@@ -472,7 +472,7 @@ long keyctl_describe_key(key_serial_t keyid, | |||
472 | instkey = key_get_instantiation_authkey(keyid); | 472 | instkey = key_get_instantiation_authkey(keyid); |
473 | if (!IS_ERR(instkey)) { | 473 | if (!IS_ERR(instkey)) { |
474 | key_put(instkey); | 474 | key_put(instkey); |
475 | key_ref = lookup_user_key(NULL, keyid, | 475 | key_ref = lookup_user_key(keyid, |
476 | 0, 1, 0); | 476 | 0, 1, 0); |
477 | if (!IS_ERR(key_ref)) | 477 | if (!IS_ERR(key_ref)) |
478 | goto okay; | 478 | goto okay; |
@@ -557,7 +557,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
557 | } | 557 | } |
558 | 558 | ||
559 | /* get the keyring at which to begin the search */ | 559 | /* get the keyring at which to begin the search */ |
560 | keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); | 560 | keyring_ref = lookup_user_key(ringid, 0, 0, KEY_SEARCH); |
561 | if (IS_ERR(keyring_ref)) { | 561 | if (IS_ERR(keyring_ref)) { |
562 | ret = PTR_ERR(keyring_ref); | 562 | ret = PTR_ERR(keyring_ref); |
563 | goto error2; | 563 | goto error2; |
@@ -566,7 +566,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
566 | /* get the destination keyring if specified */ | 566 | /* get the destination keyring if specified */ |
567 | dest_ref = NULL; | 567 | dest_ref = NULL; |
568 | if (destringid) { | 568 | if (destringid) { |
569 | dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); | 569 | dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE); |
570 | if (IS_ERR(dest_ref)) { | 570 | if (IS_ERR(dest_ref)) { |
571 | ret = PTR_ERR(dest_ref); | 571 | ret = PTR_ERR(dest_ref); |
572 | goto error3; | 572 | goto error3; |
@@ -636,7 +636,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
636 | long ret; | 636 | long ret; |
637 | 637 | ||
638 | /* find the key first */ | 638 | /* find the key first */ |
639 | key_ref = lookup_user_key(NULL, keyid, 0, 0, 0); | 639 | key_ref = lookup_user_key(keyid, 0, 0, 0); |
640 | if (IS_ERR(key_ref)) { | 640 | if (IS_ERR(key_ref)) { |
641 | ret = -ENOKEY; | 641 | ret = -ENOKEY; |
642 | goto error; | 642 | goto error; |
@@ -699,7 +699,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
699 | if (uid == (uid_t) -1 && gid == (gid_t) -1) | 699 | if (uid == (uid_t) -1 && gid == (gid_t) -1) |
700 | goto error; | 700 | goto error; |
701 | 701 | ||
702 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | 702 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); |
703 | if (IS_ERR(key_ref)) { | 703 | if (IS_ERR(key_ref)) { |
704 | ret = PTR_ERR(key_ref); | 704 | ret = PTR_ERR(key_ref); |
705 | goto error; | 705 | goto error; |
@@ -804,7 +804,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
804 | if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) | 804 | if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) |
805 | goto error; | 805 | goto error; |
806 | 806 | ||
807 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | 807 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); |
808 | if (IS_ERR(key_ref)) { | 808 | if (IS_ERR(key_ref)) { |
809 | ret = PTR_ERR(key_ref); | 809 | ret = PTR_ERR(key_ref); |
810 | goto error; | 810 | goto error; |
@@ -829,6 +829,43 @@ error: | |||
829 | 829 | ||
830 | } /* end keyctl_setperm_key() */ | 830 | } /* end keyctl_setperm_key() */ |
831 | 831 | ||
832 | /* | ||
833 | * get the destination keyring for instantiation | ||
834 | */ | ||
835 | static long get_instantiation_keyring(key_serial_t ringid, | ||
836 | struct request_key_auth *rka, | ||
837 | struct key **_dest_keyring) | ||
838 | { | ||
839 | key_ref_t dkref; | ||
840 | |||
841 | /* just return a NULL pointer if we weren't asked to make a link */ | ||
842 | if (ringid == 0) { | ||
843 | *_dest_keyring = NULL; | ||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | /* if a specific keyring is nominated by ID, then use that */ | ||
848 | if (ringid > 0) { | ||
849 | dkref = lookup_user_key(ringid, 1, 0, KEY_WRITE); | ||
850 | if (IS_ERR(dkref)) | ||
851 | return PTR_ERR(dkref); | ||
852 | *_dest_keyring = key_ref_to_ptr(dkref); | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | if (ringid == KEY_SPEC_REQKEY_AUTH_KEY) | ||
857 | return -EINVAL; | ||
858 | |||
859 | /* otherwise specify the destination keyring recorded in the | ||
860 | * authorisation key (any KEY_SPEC_*_KEYRING) */ | ||
861 | if (ringid >= KEY_SPEC_REQUESTOR_KEYRING) { | ||
862 | *_dest_keyring = rka->dest_keyring; | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | return -ENOKEY; | ||
867 | } | ||
868 | |||
832 | /*****************************************************************************/ | 869 | /*****************************************************************************/ |
833 | /* | 870 | /* |
834 | * instantiate the key with the specified payload, and, if one is given, link | 871 | * instantiate the key with the specified payload, and, if one is given, link |
@@ -840,8 +877,7 @@ long keyctl_instantiate_key(key_serial_t id, | |||
840 | key_serial_t ringid) | 877 | key_serial_t ringid) |
841 | { | 878 | { |
842 | struct request_key_auth *rka; | 879 | struct request_key_auth *rka; |
843 | struct key *instkey; | 880 | struct key *instkey, *dest_keyring; |
844 | key_ref_t keyring_ref; | ||
845 | void *payload; | 881 | void *payload; |
846 | long ret; | 882 | long ret; |
847 | bool vm = false; | 883 | bool vm = false; |
@@ -883,21 +919,15 @@ long keyctl_instantiate_key(key_serial_t id, | |||
883 | 919 | ||
884 | /* find the destination keyring amongst those belonging to the | 920 | /* find the destination keyring amongst those belonging to the |
885 | * requesting task */ | 921 | * requesting task */ |
886 | keyring_ref = NULL; | 922 | ret = get_instantiation_keyring(ringid, rka, &dest_keyring); |
887 | if (ringid) { | 923 | if (ret < 0) |
888 | keyring_ref = lookup_user_key(rka->context, ringid, 1, 0, | 924 | goto error2; |
889 | KEY_WRITE); | ||
890 | if (IS_ERR(keyring_ref)) { | ||
891 | ret = PTR_ERR(keyring_ref); | ||
892 | goto error2; | ||
893 | } | ||
894 | } | ||
895 | 925 | ||
896 | /* instantiate the key and link it into a keyring */ | 926 | /* instantiate the key and link it into a keyring */ |
897 | ret = key_instantiate_and_link(rka->target_key, payload, plen, | 927 | ret = key_instantiate_and_link(rka->target_key, payload, plen, |
898 | key_ref_to_ptr(keyring_ref), instkey); | 928 | dest_keyring, instkey); |
899 | 929 | ||
900 | key_ref_put(keyring_ref); | 930 | key_put(dest_keyring); |
901 | 931 | ||
902 | /* discard the assumed authority if it's just been disabled by | 932 | /* discard the assumed authority if it's just been disabled by |
903 | * instantiation of the key */ | 933 | * instantiation of the key */ |
@@ -924,8 +954,7 @@ error: | |||
924 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 954 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
925 | { | 955 | { |
926 | struct request_key_auth *rka; | 956 | struct request_key_auth *rka; |
927 | struct key *instkey; | 957 | struct key *instkey, *dest_keyring; |
928 | key_ref_t keyring_ref; | ||
929 | long ret; | 958 | long ret; |
930 | 959 | ||
931 | /* the appropriate instantiation authorisation key must have been | 960 | /* the appropriate instantiation authorisation key must have been |
@@ -941,20 +970,15 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
941 | 970 | ||
942 | /* find the destination keyring if present (which must also be | 971 | /* find the destination keyring if present (which must also be |
943 | * writable) */ | 972 | * writable) */ |
944 | keyring_ref = NULL; | 973 | ret = get_instantiation_keyring(ringid, rka, &dest_keyring); |
945 | if (ringid) { | 974 | if (ret < 0) |
946 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 975 | goto error; |
947 | if (IS_ERR(keyring_ref)) { | ||
948 | ret = PTR_ERR(keyring_ref); | ||
949 | goto error; | ||
950 | } | ||
951 | } | ||
952 | 976 | ||
953 | /* instantiate the key and link it into a keyring */ | 977 | /* instantiate the key and link it into a keyring */ |
954 | ret = key_negate_and_link(rka->target_key, timeout, | 978 | ret = key_negate_and_link(rka->target_key, timeout, |
955 | key_ref_to_ptr(keyring_ref), instkey); | 979 | dest_keyring, instkey); |
956 | 980 | ||
957 | key_ref_put(keyring_ref); | 981 | key_put(dest_keyring); |
958 | 982 | ||
959 | /* discard the assumed authority if it's just been disabled by | 983 | /* discard the assumed authority if it's just been disabled by |
960 | * instantiation of the key */ | 984 | * instantiation of the key */ |
@@ -979,13 +1003,13 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) | |||
979 | 1003 | ||
980 | switch (reqkey_defl) { | 1004 | switch (reqkey_defl) { |
981 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 1005 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
982 | ret = install_thread_keyring(current); | 1006 | ret = install_thread_keyring(); |
983 | if (ret < 0) | 1007 | if (ret < 0) |
984 | return ret; | 1008 | return ret; |
985 | goto set; | 1009 | goto set; |
986 | 1010 | ||
987 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 1011 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
988 | ret = install_process_keyring(current); | 1012 | ret = install_process_keyring(); |
989 | if (ret < 0) | 1013 | if (ret < 0) |
990 | return ret; | 1014 | return ret; |
991 | 1015 | ||
@@ -1018,7 +1042,7 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout) | |||
1018 | time_t expiry; | 1042 | time_t expiry; |
1019 | long ret; | 1043 | long ret; |
1020 | 1044 | ||
1021 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | 1045 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); |
1022 | if (IS_ERR(key_ref)) { | 1046 | if (IS_ERR(key_ref)) { |
1023 | ret = PTR_ERR(key_ref); | 1047 | ret = PTR_ERR(key_ref); |
1024 | goto error; | 1048 | goto error; |
@@ -1105,7 +1129,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1105 | char *context; | 1129 | char *context; |
1106 | long ret; | 1130 | long ret; |
1107 | 1131 | ||
1108 | key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); | 1132 | key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW); |
1109 | if (IS_ERR(key_ref)) { | 1133 | if (IS_ERR(key_ref)) { |
1110 | if (PTR_ERR(key_ref) != -EACCES) | 1134 | if (PTR_ERR(key_ref) != -EACCES) |
1111 | return PTR_ERR(key_ref); | 1135 | return PTR_ERR(key_ref); |
@@ -1117,7 +1141,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1117 | return PTR_ERR(key_ref); | 1141 | return PTR_ERR(key_ref); |
1118 | key_put(instkey); | 1142 | key_put(instkey); |
1119 | 1143 | ||
1120 | key_ref = lookup_user_key(NULL, keyid, 0, 1, 0); | 1144 | key_ref = lookup_user_key(keyid, 0, 1, 0); |
1121 | if (IS_ERR(key_ref)) | 1145 | if (IS_ERR(key_ref)) |
1122 | return PTR_ERR(key_ref); | 1146 | return PTR_ERR(key_ref); |
1123 | } | 1147 | } |