diff options
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 176 |
1 files changed, 118 insertions, 58 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index cedb7326de29..fea262860ea0 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* keyctl.c: userspace keyctl operations | 1 | /* keyctl.c: userspace keyctl operations |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -49,6 +49,13 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
49 | goto error; | 49 | goto error; |
50 | type[31] = '\0'; | 50 | type[31] = '\0'; |
51 | 51 | ||
52 | if (!type[0]) | ||
53 | goto error; | ||
54 | |||
55 | ret = -EPERM; | ||
56 | if (type[0] == '.') | ||
57 | goto error; | ||
58 | |||
52 | ret = -EFAULT; | 59 | ret = -EFAULT; |
53 | dlen = strnlen_user(_description, PAGE_SIZE - 1); | 60 | dlen = strnlen_user(_description, PAGE_SIZE - 1); |
54 | if (dlen <= 0) | 61 | if (dlen <= 0) |
@@ -82,7 +89,7 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
82 | } | 89 | } |
83 | 90 | ||
84 | /* find the target keyring (which must be writable) */ | 91 | /* find the target keyring (which must be writable) */ |
85 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 92 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
86 | if (IS_ERR(keyring)) { | 93 | if (IS_ERR(keyring)) { |
87 | ret = PTR_ERR(keyring); | 94 | ret = PTR_ERR(keyring); |
88 | goto error3; | 95 | goto error3; |
@@ -181,7 +188,7 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
181 | /* get the destination keyring if specified */ | 188 | /* get the destination keyring if specified */ |
182 | dest = NULL; | 189 | dest = NULL; |
183 | if (destringid) { | 190 | if (destringid) { |
184 | dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); | 191 | dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); |
185 | if (IS_ERR(dest)) { | 192 | if (IS_ERR(dest)) { |
186 | ret = PTR_ERR(dest); | 193 | ret = PTR_ERR(dest); |
187 | goto error3; | 194 | goto error3; |
@@ -196,23 +203,15 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
196 | } | 203 | } |
197 | 204 | ||
198 | /* do the search */ | 205 | /* do the search */ |
199 | key = request_key(ktype, description, callout_info); | 206 | key = request_key_and_link(ktype, description, callout_info, dest); |
200 | if (IS_ERR(key)) { | 207 | if (IS_ERR(key)) { |
201 | ret = PTR_ERR(key); | 208 | ret = PTR_ERR(key); |
202 | goto error5; | 209 | goto error5; |
203 | } | 210 | } |
204 | 211 | ||
205 | /* link the resulting key to the destination keyring */ | ||
206 | if (dest) { | ||
207 | ret = key_link(dest, key); | ||
208 | if (ret < 0) | ||
209 | goto error6; | ||
210 | } | ||
211 | |||
212 | ret = key->serial; | 212 | ret = key->serial; |
213 | 213 | ||
214 | error6: | 214 | key_put(key); |
215 | key_put(key); | ||
216 | error5: | 215 | error5: |
217 | key_type_put(ktype); | 216 | key_type_put(ktype); |
218 | error4: | 217 | error4: |
@@ -237,7 +236,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) | |||
237 | struct key *key; | 236 | struct key *key; |
238 | long ret; | 237 | long ret; |
239 | 238 | ||
240 | key = lookup_user_key(id, create, 0, KEY_SEARCH); | 239 | key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH); |
241 | if (IS_ERR(key)) { | 240 | if (IS_ERR(key)) { |
242 | ret = PTR_ERR(key); | 241 | ret = PTR_ERR(key); |
243 | goto error; | 242 | goto error; |
@@ -324,7 +323,7 @@ long keyctl_update_key(key_serial_t id, | |||
324 | } | 323 | } |
325 | 324 | ||
326 | /* find the target key (which must be writable) */ | 325 | /* find the target key (which must be writable) */ |
327 | key = lookup_user_key(id, 0, 0, KEY_WRITE); | 326 | key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); |
328 | if (IS_ERR(key)) { | 327 | if (IS_ERR(key)) { |
329 | ret = PTR_ERR(key); | 328 | ret = PTR_ERR(key); |
330 | goto error2; | 329 | goto error2; |
@@ -352,7 +351,7 @@ long keyctl_revoke_key(key_serial_t id) | |||
352 | struct key *key; | 351 | struct key *key; |
353 | long ret; | 352 | long ret; |
354 | 353 | ||
355 | key = lookup_user_key(id, 0, 0, KEY_WRITE); | 354 | key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); |
356 | if (IS_ERR(key)) { | 355 | if (IS_ERR(key)) { |
357 | ret = PTR_ERR(key); | 356 | ret = PTR_ERR(key); |
358 | goto error; | 357 | goto error; |
@@ -378,7 +377,7 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
378 | struct key *keyring; | 377 | struct key *keyring; |
379 | long ret; | 378 | long ret; |
380 | 379 | ||
381 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 380 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
382 | if (IS_ERR(keyring)) { | 381 | if (IS_ERR(keyring)) { |
383 | ret = PTR_ERR(keyring); | 382 | ret = PTR_ERR(keyring); |
384 | goto error; | 383 | goto error; |
@@ -404,13 +403,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) | |||
404 | struct key *keyring, *key; | 403 | struct key *keyring, *key; |
405 | long ret; | 404 | long ret; |
406 | 405 | ||
407 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 406 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
408 | if (IS_ERR(keyring)) { | 407 | if (IS_ERR(keyring)) { |
409 | ret = PTR_ERR(keyring); | 408 | ret = PTR_ERR(keyring); |
410 | goto error; | 409 | goto error; |
411 | } | 410 | } |
412 | 411 | ||
413 | key = lookup_user_key(id, 1, 0, KEY_LINK); | 412 | key = lookup_user_key(NULL, id, 1, 0, KEY_LINK); |
414 | if (IS_ERR(key)) { | 413 | if (IS_ERR(key)) { |
415 | ret = PTR_ERR(key); | 414 | ret = PTR_ERR(key); |
416 | goto error2; | 415 | goto error2; |
@@ -438,13 +437,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) | |||
438 | struct key *keyring, *key; | 437 | struct key *keyring, *key; |
439 | long ret; | 438 | long ret; |
440 | 439 | ||
441 | keyring = lookup_user_key(ringid, 0, 0, KEY_WRITE); | 440 | keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE); |
442 | if (IS_ERR(keyring)) { | 441 | if (IS_ERR(keyring)) { |
443 | ret = PTR_ERR(keyring); | 442 | ret = PTR_ERR(keyring); |
444 | goto error; | 443 | goto error; |
445 | } | 444 | } |
446 | 445 | ||
447 | key = lookup_user_key(id, 0, 0, 0); | 446 | key = lookup_user_key(NULL, id, 0, 0, 0); |
448 | if (IS_ERR(key)) { | 447 | if (IS_ERR(key)) { |
449 | ret = PTR_ERR(key); | 448 | ret = PTR_ERR(key); |
450 | goto error2; | 449 | goto error2; |
@@ -475,16 +474,29 @@ long keyctl_describe_key(key_serial_t keyid, | |||
475 | char __user *buffer, | 474 | char __user *buffer, |
476 | size_t buflen) | 475 | size_t buflen) |
477 | { | 476 | { |
478 | struct key *key; | 477 | struct key *key, *instkey; |
479 | char *tmpbuf; | 478 | char *tmpbuf; |
480 | long ret; | 479 | long ret; |
481 | 480 | ||
482 | key = lookup_user_key(keyid, 0, 1, KEY_VIEW); | 481 | key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); |
483 | if (IS_ERR(key)) { | 482 | if (IS_ERR(key)) { |
483 | /* viewing a key under construction is permitted if we have the | ||
484 | * authorisation token handy */ | ||
485 | if (PTR_ERR(key) == -EACCES) { | ||
486 | instkey = key_get_instantiation_authkey(keyid); | ||
487 | if (!IS_ERR(instkey)) { | ||
488 | key_put(instkey); | ||
489 | key = lookup_user_key(NULL, keyid, 0, 1, 0); | ||
490 | if (!IS_ERR(key)) | ||
491 | goto okay; | ||
492 | } | ||
493 | } | ||
494 | |||
484 | ret = PTR_ERR(key); | 495 | ret = PTR_ERR(key); |
485 | goto error; | 496 | goto error; |
486 | } | 497 | } |
487 | 498 | ||
499 | okay: | ||
488 | /* calculate how much description we're going to return */ | 500 | /* calculate how much description we're going to return */ |
489 | ret = -ENOMEM; | 501 | ret = -ENOMEM; |
490 | tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 502 | tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
@@ -568,7 +580,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
568 | goto error2; | 580 | goto error2; |
569 | 581 | ||
570 | /* get the keyring at which to begin the search */ | 582 | /* get the keyring at which to begin the search */ |
571 | keyring = lookup_user_key(ringid, 0, 0, KEY_SEARCH); | 583 | keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); |
572 | if (IS_ERR(keyring)) { | 584 | if (IS_ERR(keyring)) { |
573 | ret = PTR_ERR(keyring); | 585 | ret = PTR_ERR(keyring); |
574 | goto error2; | 586 | goto error2; |
@@ -577,7 +589,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
577 | /* get the destination keyring if specified */ | 589 | /* get the destination keyring if specified */ |
578 | dest = NULL; | 590 | dest = NULL; |
579 | if (destringid) { | 591 | if (destringid) { |
580 | dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); | 592 | dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); |
581 | if (IS_ERR(dest)) { | 593 | if (IS_ERR(dest)) { |
582 | ret = PTR_ERR(dest); | 594 | ret = PTR_ERR(dest); |
583 | goto error3; | 595 | goto error3; |
@@ -656,24 +668,23 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
656 | long ret; | 668 | long ret; |
657 | 669 | ||
658 | /* find the key first */ | 670 | /* find the key first */ |
659 | key = lookup_user_key(keyid, 0, 0, 0); | 671 | key = lookup_user_key(NULL, keyid, 0, 0, 0); |
660 | if (!IS_ERR(key)) { | 672 | if (!IS_ERR(key)) { |
661 | /* see if we can read it directly */ | 673 | /* see if we can read it directly */ |
662 | if (key_permission(key, KEY_READ)) | 674 | if (key_permission(key, KEY_READ)) |
663 | goto can_read_key; | 675 | goto can_read_key; |
664 | 676 | ||
665 | /* can't; see if it's searchable from this process's | 677 | /* we can't; see if it's searchable from this process's |
666 | * keyrings */ | 678 | * keyrings |
667 | ret = -ENOKEY; | 679 | * - we automatically take account of the fact that it may be |
668 | if (key_permission(key, KEY_SEARCH)) { | 680 | * dangling off an instantiation key |
669 | /* okay - we do have search permission on the key | 681 | */ |
670 | * itself, but do we have the key? */ | 682 | skey = search_process_keyrings(key->type, key, |
671 | skey = search_process_keyrings_aux(key->type, key, | 683 | keyctl_read_key_same, current); |
672 | keyctl_read_key_same); | 684 | if (!IS_ERR(skey)) |
673 | if (!IS_ERR(skey)) | 685 | goto can_read_key2; |
674 | goto can_read_key2; | 686 | |
675 | } | 687 | ret = PTR_ERR(skey); |
676 | |||
677 | goto error2; | 688 | goto error2; |
678 | } | 689 | } |
679 | 690 | ||
@@ -719,7 +730,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
719 | if (uid == (uid_t) -1 && gid == (gid_t) -1) | 730 | if (uid == (uid_t) -1 && gid == (gid_t) -1) |
720 | goto error; | 731 | goto error; |
721 | 732 | ||
722 | key = lookup_user_key(id, 1, 1, 0); | 733 | key = lookup_user_key(NULL, id, 1, 1, 0); |
723 | if (IS_ERR(key)) { | 734 | if (IS_ERR(key)) { |
724 | ret = PTR_ERR(key); | 735 | ret = PTR_ERR(key); |
725 | goto error; | 736 | goto error; |
@@ -776,7 +787,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
776 | if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) | 787 | if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) |
777 | goto error; | 788 | goto error; |
778 | 789 | ||
779 | key = lookup_user_key(id, 1, 1, 0); | 790 | key = lookup_user_key(NULL, id, 1, 1, 0); |
780 | if (IS_ERR(key)) { | 791 | if (IS_ERR(key)) { |
781 | ret = PTR_ERR(key); | 792 | ret = PTR_ERR(key); |
782 | goto error; | 793 | goto error; |
@@ -809,7 +820,8 @@ long keyctl_instantiate_key(key_serial_t id, | |||
809 | size_t plen, | 820 | size_t plen, |
810 | key_serial_t ringid) | 821 | key_serial_t ringid) |
811 | { | 822 | { |
812 | struct key *key, *keyring; | 823 | struct request_key_auth *rka; |
824 | struct key *instkey, *keyring; | ||
813 | void *payload; | 825 | void *payload; |
814 | long ret; | 826 | long ret; |
815 | 827 | ||
@@ -831,18 +843,21 @@ long keyctl_instantiate_key(key_serial_t id, | |||
831 | goto error2; | 843 | goto error2; |
832 | } | 844 | } |
833 | 845 | ||
834 | /* find the target key (which must be writable) */ | 846 | /* find the instantiation authorisation key */ |
835 | key = lookup_user_key(id, 0, 1, KEY_WRITE); | 847 | instkey = key_get_instantiation_authkey(id); |
836 | if (IS_ERR(key)) { | 848 | if (IS_ERR(instkey)) { |
837 | ret = PTR_ERR(key); | 849 | ret = PTR_ERR(instkey); |
838 | goto error2; | 850 | goto error2; |
839 | } | 851 | } |
840 | 852 | ||
841 | /* find the destination keyring if present (which must also be | 853 | rka = instkey->payload.data; |
842 | * writable) */ | 854 | |
855 | /* find the destination keyring amongst those belonging to the | ||
856 | * requesting task */ | ||
843 | keyring = NULL; | 857 | keyring = NULL; |
844 | if (ringid) { | 858 | if (ringid) { |
845 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 859 | keyring = lookup_user_key(rka->context, ringid, 1, 0, |
860 | KEY_WRITE); | ||
846 | if (IS_ERR(keyring)) { | 861 | if (IS_ERR(keyring)) { |
847 | ret = PTR_ERR(keyring); | 862 | ret = PTR_ERR(keyring); |
848 | goto error3; | 863 | goto error3; |
@@ -850,11 +865,12 @@ long keyctl_instantiate_key(key_serial_t id, | |||
850 | } | 865 | } |
851 | 866 | ||
852 | /* instantiate the key and link it into a keyring */ | 867 | /* instantiate the key and link it into a keyring */ |
853 | ret = key_instantiate_and_link(key, payload, plen, keyring); | 868 | ret = key_instantiate_and_link(rka->target_key, payload, plen, |
869 | keyring, instkey); | ||
854 | 870 | ||
855 | key_put(keyring); | 871 | key_put(keyring); |
856 | error3: | 872 | error3: |
857 | key_put(key); | 873 | key_put(instkey); |
858 | error2: | 874 | error2: |
859 | kfree(payload); | 875 | kfree(payload); |
860 | error: | 876 | error: |
@@ -869,21 +885,24 @@ long keyctl_instantiate_key(key_serial_t id, | |||
869 | */ | 885 | */ |
870 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 886 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
871 | { | 887 | { |
872 | struct key *key, *keyring; | 888 | struct request_key_auth *rka; |
889 | struct key *instkey, *keyring; | ||
873 | long ret; | 890 | long ret; |
874 | 891 | ||
875 | /* find the target key (which must be writable) */ | 892 | /* find the instantiation authorisation key */ |
876 | key = lookup_user_key(id, 0, 1, KEY_WRITE); | 893 | instkey = key_get_instantiation_authkey(id); |
877 | if (IS_ERR(key)) { | 894 | if (IS_ERR(instkey)) { |
878 | ret = PTR_ERR(key); | 895 | ret = PTR_ERR(instkey); |
879 | goto error; | 896 | goto error; |
880 | } | 897 | } |
881 | 898 | ||
899 | rka = instkey->payload.data; | ||
900 | |||
882 | /* find the destination keyring if present (which must also be | 901 | /* find the destination keyring if present (which must also be |
883 | * writable) */ | 902 | * writable) */ |
884 | keyring = NULL; | 903 | keyring = NULL; |
885 | if (ringid) { | 904 | if (ringid) { |
886 | keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); | 905 | keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
887 | if (IS_ERR(keyring)) { | 906 | if (IS_ERR(keyring)) { |
888 | ret = PTR_ERR(keyring); | 907 | ret = PTR_ERR(keyring); |
889 | goto error2; | 908 | goto error2; |
@@ -891,11 +910,11 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
891 | } | 910 | } |
892 | 911 | ||
893 | /* instantiate the key and link it into a keyring */ | 912 | /* instantiate the key and link it into a keyring */ |
894 | ret = key_negate_and_link(key, timeout, keyring); | 913 | ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey); |
895 | 914 | ||
896 | key_put(keyring); | 915 | key_put(keyring); |
897 | error2: | 916 | error2: |
898 | key_put(key); | 917 | key_put(instkey); |
899 | error: | 918 | error: |
900 | return ret; | 919 | return ret; |
901 | 920 | ||
@@ -903,6 +922,44 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
903 | 922 | ||
904 | /*****************************************************************************/ | 923 | /*****************************************************************************/ |
905 | /* | 924 | /* |
925 | * set the default keyring in which request_key() will cache keys | ||
926 | * - return the old setting | ||
927 | */ | ||
928 | long keyctl_set_reqkey_keyring(int reqkey_defl) | ||
929 | { | ||
930 | int ret; | ||
931 | |||
932 | switch (reqkey_defl) { | ||
933 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | ||
934 | ret = install_thread_keyring(current); | ||
935 | if (ret < 0) | ||
936 | return ret; | ||
937 | goto set; | ||
938 | |||
939 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | ||
940 | ret = install_process_keyring(current); | ||
941 | if (ret < 0) | ||
942 | return ret; | ||
943 | |||
944 | case KEY_REQKEY_DEFL_DEFAULT: | ||
945 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | ||
946 | case KEY_REQKEY_DEFL_USER_KEYRING: | ||
947 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | ||
948 | set: | ||
949 | current->jit_keyring = reqkey_defl; | ||
950 | |||
951 | case KEY_REQKEY_DEFL_NO_CHANGE: | ||
952 | return current->jit_keyring; | ||
953 | |||
954 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | ||
955 | default: | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | |||
959 | } /* end keyctl_set_reqkey_keyring() */ | ||
960 | |||
961 | /*****************************************************************************/ | ||
962 | /* | ||
906 | * the key control system call | 963 | * the key control system call |
907 | */ | 964 | */ |
908 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | 965 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, |
@@ -971,6 +1028,9 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | |||
971 | (unsigned) arg3, | 1028 | (unsigned) arg3, |
972 | (key_serial_t) arg4); | 1029 | (key_serial_t) arg4); |
973 | 1030 | ||
1031 | case KEYCTL_SET_REQKEY_KEYRING: | ||
1032 | return keyctl_set_reqkey_keyring(arg2); | ||
1033 | |||
974 | default: | 1034 | default: |
975 | return -EOPNOTSUPP; | 1035 | return -EOPNOTSUPP; |
976 | } | 1036 | } |