diff options
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 151 |
1 files changed, 128 insertions, 23 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index b7a468fabdf9..3d2ebae029c1 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -834,6 +834,17 @@ long keyctl_instantiate_key(key_serial_t id, | |||
834 | if (plen > 32767) | 834 | if (plen > 32767) |
835 | goto error; | 835 | goto error; |
836 | 836 | ||
837 | /* the appropriate instantiation authorisation key must have been | ||
838 | * assumed before calling this */ | ||
839 | ret = -EPERM; | ||
840 | instkey = current->request_key_auth; | ||
841 | if (!instkey) | ||
842 | goto error; | ||
843 | |||
844 | rka = instkey->payload.data; | ||
845 | if (rka->target_key->serial != id) | ||
846 | goto error; | ||
847 | |||
837 | /* pull the payload in if one was supplied */ | 848 | /* pull the payload in if one was supplied */ |
838 | payload = NULL; | 849 | payload = NULL; |
839 | 850 | ||
@@ -848,15 +859,6 @@ long keyctl_instantiate_key(key_serial_t id, | |||
848 | goto error2; | 859 | goto error2; |
849 | } | 860 | } |
850 | 861 | ||
851 | /* find the instantiation authorisation key */ | ||
852 | instkey = key_get_instantiation_authkey(id); | ||
853 | if (IS_ERR(instkey)) { | ||
854 | ret = PTR_ERR(instkey); | ||
855 | goto error2; | ||
856 | } | ||
857 | |||
858 | rka = instkey->payload.data; | ||
859 | |||
860 | /* find the destination keyring amongst those belonging to the | 862 | /* find the destination keyring amongst those belonging to the |
861 | * requesting task */ | 863 | * requesting task */ |
862 | keyring_ref = NULL; | 864 | keyring_ref = NULL; |
@@ -865,7 +867,7 @@ long keyctl_instantiate_key(key_serial_t id, | |||
865 | KEY_WRITE); | 867 | KEY_WRITE); |
866 | if (IS_ERR(keyring_ref)) { | 868 | if (IS_ERR(keyring_ref)) { |
867 | ret = PTR_ERR(keyring_ref); | 869 | ret = PTR_ERR(keyring_ref); |
868 | goto error3; | 870 | goto error2; |
869 | } | 871 | } |
870 | } | 872 | } |
871 | 873 | ||
@@ -874,11 +876,17 @@ long keyctl_instantiate_key(key_serial_t id, | |||
874 | key_ref_to_ptr(keyring_ref), instkey); | 876 | key_ref_to_ptr(keyring_ref), instkey); |
875 | 877 | ||
876 | key_ref_put(keyring_ref); | 878 | key_ref_put(keyring_ref); |
877 | error3: | 879 | |
878 | key_put(instkey); | 880 | /* discard the assumed authority if it's just been disabled by |
879 | error2: | 881 | * instantiation of the key */ |
882 | if (ret == 0) { | ||
883 | key_put(current->request_key_auth); | ||
884 | current->request_key_auth = NULL; | ||
885 | } | ||
886 | |||
887 | error2: | ||
880 | kfree(payload); | 888 | kfree(payload); |
881 | error: | 889 | error: |
882 | return ret; | 890 | return ret; |
883 | 891 | ||
884 | } /* end keyctl_instantiate_key() */ | 892 | } /* end keyctl_instantiate_key() */ |
@@ -895,14 +903,16 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
895 | key_ref_t keyring_ref; | 903 | key_ref_t keyring_ref; |
896 | long ret; | 904 | long ret; |
897 | 905 | ||
898 | /* find the instantiation authorisation key */ | 906 | /* the appropriate instantiation authorisation key must have been |
899 | instkey = key_get_instantiation_authkey(id); | 907 | * assumed before calling this */ |
900 | if (IS_ERR(instkey)) { | 908 | ret = -EPERM; |
901 | ret = PTR_ERR(instkey); | 909 | instkey = current->request_key_auth; |
910 | if (!instkey) | ||
902 | goto error; | 911 | goto error; |
903 | } | ||
904 | 912 | ||
905 | rka = instkey->payload.data; | 913 | rka = instkey->payload.data; |
914 | if (rka->target_key->serial != id) | ||
915 | goto error; | ||
906 | 916 | ||
907 | /* find the destination keyring if present (which must also be | 917 | /* find the destination keyring if present (which must also be |
908 | * writable) */ | 918 | * writable) */ |
@@ -911,7 +921,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
911 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 921 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); |
912 | if (IS_ERR(keyring_ref)) { | 922 | if (IS_ERR(keyring_ref)) { |
913 | ret = PTR_ERR(keyring_ref); | 923 | ret = PTR_ERR(keyring_ref); |
914 | goto error2; | 924 | goto error; |
915 | } | 925 | } |
916 | } | 926 | } |
917 | 927 | ||
@@ -920,9 +930,15 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
920 | key_ref_to_ptr(keyring_ref), instkey); | 930 | key_ref_to_ptr(keyring_ref), instkey); |
921 | 931 | ||
922 | key_ref_put(keyring_ref); | 932 | key_ref_put(keyring_ref); |
923 | error2: | 933 | |
924 | key_put(instkey); | 934 | /* discard the assumed authority if it's just been disabled by |
925 | error: | 935 | * instantiation of the key */ |
936 | if (ret == 0) { | ||
937 | key_put(current->request_key_auth); | ||
938 | current->request_key_auth = NULL; | ||
939 | } | ||
940 | |||
941 | error: | ||
926 | return ret; | 942 | return ret; |
927 | 943 | ||
928 | } /* end keyctl_negate_key() */ | 944 | } /* end keyctl_negate_key() */ |
@@ -967,6 +983,88 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) | |||
967 | 983 | ||
968 | /*****************************************************************************/ | 984 | /*****************************************************************************/ |
969 | /* | 985 | /* |
986 | * set or clear the timeout for a key | ||
987 | */ | ||
988 | long keyctl_set_timeout(key_serial_t id, unsigned timeout) | ||
989 | { | ||
990 | struct timespec now; | ||
991 | struct key *key; | ||
992 | key_ref_t key_ref; | ||
993 | time_t expiry; | ||
994 | long ret; | ||
995 | |||
996 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | ||
997 | if (IS_ERR(key_ref)) { | ||
998 | ret = PTR_ERR(key_ref); | ||
999 | goto error; | ||
1000 | } | ||
1001 | |||
1002 | key = key_ref_to_ptr(key_ref); | ||
1003 | |||
1004 | /* make the changes with the locks held to prevent races */ | ||
1005 | down_write(&key->sem); | ||
1006 | |||
1007 | expiry = 0; | ||
1008 | if (timeout > 0) { | ||
1009 | now = current_kernel_time(); | ||
1010 | expiry = now.tv_sec + timeout; | ||
1011 | } | ||
1012 | |||
1013 | key->expiry = expiry; | ||
1014 | |||
1015 | up_write(&key->sem); | ||
1016 | key_put(key); | ||
1017 | |||
1018 | ret = 0; | ||
1019 | error: | ||
1020 | return ret; | ||
1021 | |||
1022 | } /* end keyctl_set_timeout() */ | ||
1023 | |||
1024 | /*****************************************************************************/ | ||
1025 | /* | ||
1026 | * assume the authority to instantiate the specified key | ||
1027 | */ | ||
1028 | long keyctl_assume_authority(key_serial_t id) | ||
1029 | { | ||
1030 | struct key *authkey; | ||
1031 | long ret; | ||
1032 | |||
1033 | /* special key IDs aren't permitted */ | ||
1034 | ret = -EINVAL; | ||
1035 | if (id < 0) | ||
1036 | goto error; | ||
1037 | |||
1038 | /* we divest ourselves of authority if given an ID of 0 */ | ||
1039 | if (id == 0) { | ||
1040 | key_put(current->request_key_auth); | ||
1041 | current->request_key_auth = NULL; | ||
1042 | ret = 0; | ||
1043 | goto error; | ||
1044 | } | ||
1045 | |||
1046 | /* attempt to assume the authority temporarily granted to us whilst we | ||
1047 | * instantiate the specified key | ||
1048 | * - the authorisation key must be in the current task's keyrings | ||
1049 | * somewhere | ||
1050 | */ | ||
1051 | authkey = key_get_instantiation_authkey(id); | ||
1052 | if (IS_ERR(authkey)) { | ||
1053 | ret = PTR_ERR(authkey); | ||
1054 | goto error; | ||
1055 | } | ||
1056 | |||
1057 | key_put(current->request_key_auth); | ||
1058 | current->request_key_auth = authkey; | ||
1059 | ret = authkey->serial; | ||
1060 | |||
1061 | error: | ||
1062 | return ret; | ||
1063 | |||
1064 | } /* end keyctl_assume_authority() */ | ||
1065 | |||
1066 | /*****************************************************************************/ | ||
1067 | /* | ||
970 | * the key control system call | 1068 | * the key control system call |
971 | */ | 1069 | */ |
972 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | 1070 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, |
@@ -1038,6 +1136,13 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | |||
1038 | case KEYCTL_SET_REQKEY_KEYRING: | 1136 | case KEYCTL_SET_REQKEY_KEYRING: |
1039 | return keyctl_set_reqkey_keyring(arg2); | 1137 | return keyctl_set_reqkey_keyring(arg2); |
1040 | 1138 | ||
1139 | case KEYCTL_SET_TIMEOUT: | ||
1140 | return keyctl_set_timeout((key_serial_t) arg2, | ||
1141 | (unsigned) arg3); | ||
1142 | |||
1143 | case KEYCTL_ASSUME_AUTHORITY: | ||
1144 | return keyctl_assume_authority((key_serial_t) arg2); | ||
1145 | |||
1041 | default: | 1146 | default: |
1042 | return -EOPNOTSUPP; | 1147 | return -EOPNOTSUPP; |
1043 | } | 1148 | } |