diff options
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 107 |
1 files changed, 84 insertions, 23 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 299f0ae11cf0..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() */ |
@@ -1007,6 +1023,48 @@ error: | |||
1007 | 1023 | ||
1008 | /*****************************************************************************/ | 1024 | /*****************************************************************************/ |
1009 | /* | 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 | /* | ||
1010 | * the key control system call | 1068 | * the key control system call |
1011 | */ | 1069 | */ |
1012 | 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, |
@@ -1082,6 +1140,9 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | |||
1082 | return keyctl_set_timeout((key_serial_t) arg2, | 1140 | return keyctl_set_timeout((key_serial_t) arg2, |
1083 | (unsigned) arg3); | 1141 | (unsigned) arg3); |
1084 | 1142 | ||
1143 | case KEYCTL_ASSUME_AUTHORITY: | ||
1144 | return keyctl_assume_authority((key_serial_t) arg2); | ||
1145 | |||
1085 | default: | 1146 | default: |
1086 | return -EOPNOTSUPP; | 1147 | return -EOPNOTSUPP; |
1087 | } | 1148 | } |