diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/compat.c | 3 | ||||
-rw-r--r-- | security/keys/internal.h | 1 | ||||
-rw-r--r-- | security/keys/keyctl.c | 44 |
3 files changed, 48 insertions, 0 deletions
diff --git a/security/keys/compat.c b/security/keys/compat.c index 3303673c636..e8e7ef4a290 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c | |||
@@ -74,6 +74,9 @@ asmlinkage long compat_sys_keyctl(u32 option, | |||
74 | case KEYCTL_SET_REQKEY_KEYRING: | 74 | case KEYCTL_SET_REQKEY_KEYRING: |
75 | return keyctl_set_reqkey_keyring(arg2); | 75 | return keyctl_set_reqkey_keyring(arg2); |
76 | 76 | ||
77 | case KEYCTL_SET_TIMEOUT: | ||
78 | return keyctl_set_timeout(arg2, arg3); | ||
79 | |||
77 | default: | 80 | default: |
78 | return -EOPNOTSUPP; | 81 | return -EOPNOTSUPP; |
79 | } | 82 | } |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 39cba97c5eb..51f37c0bdb3 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -136,6 +136,7 @@ extern long keyctl_instantiate_key(key_serial_t, const void __user *, | |||
136 | size_t, key_serial_t); | 136 | size_t, key_serial_t); |
137 | extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t); | 137 | extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t); |
138 | extern long keyctl_set_reqkey_keyring(int); | 138 | extern long keyctl_set_reqkey_keyring(int); |
139 | extern long keyctl_set_timeout(key_serial_t, unsigned); | ||
139 | 140 | ||
140 | 141 | ||
141 | /* | 142 | /* |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index b7a468fabdf..299f0ae11cf 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -967,6 +967,46 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) | |||
967 | 967 | ||
968 | /*****************************************************************************/ | 968 | /*****************************************************************************/ |
969 | /* | 969 | /* |
970 | * set or clear the timeout for a key | ||
971 | */ | ||
972 | long keyctl_set_timeout(key_serial_t id, unsigned timeout) | ||
973 | { | ||
974 | struct timespec now; | ||
975 | struct key *key; | ||
976 | key_ref_t key_ref; | ||
977 | time_t expiry; | ||
978 | long ret; | ||
979 | |||
980 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | ||
981 | if (IS_ERR(key_ref)) { | ||
982 | ret = PTR_ERR(key_ref); | ||
983 | goto error; | ||
984 | } | ||
985 | |||
986 | key = key_ref_to_ptr(key_ref); | ||
987 | |||
988 | /* make the changes with the locks held to prevent races */ | ||
989 | down_write(&key->sem); | ||
990 | |||
991 | expiry = 0; | ||
992 | if (timeout > 0) { | ||
993 | now = current_kernel_time(); | ||
994 | expiry = now.tv_sec + timeout; | ||
995 | } | ||
996 | |||
997 | key->expiry = expiry; | ||
998 | |||
999 | up_write(&key->sem); | ||
1000 | key_put(key); | ||
1001 | |||
1002 | ret = 0; | ||
1003 | error: | ||
1004 | return ret; | ||
1005 | |||
1006 | } /* end keyctl_set_timeout() */ | ||
1007 | |||
1008 | /*****************************************************************************/ | ||
1009 | /* | ||
970 | * the key control system call | 1010 | * the key control system call |
971 | */ | 1011 | */ |
972 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | 1012 | asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, |
@@ -1038,6 +1078,10 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3, | |||
1038 | case KEYCTL_SET_REQKEY_KEYRING: | 1078 | case KEYCTL_SET_REQKEY_KEYRING: |
1039 | return keyctl_set_reqkey_keyring(arg2); | 1079 | return keyctl_set_reqkey_keyring(arg2); |
1040 | 1080 | ||
1081 | case KEYCTL_SET_TIMEOUT: | ||
1082 | return keyctl_set_timeout((key_serial_t) arg2, | ||
1083 | (unsigned) arg3); | ||
1084 | |||
1041 | default: | 1085 | default: |
1042 | return -EOPNOTSUPP; | 1086 | return -EOPNOTSUPP; |
1043 | } | 1087 | } |