#include <linux/compat.h>
#include "internal.h"
-/*****************************************************************************/
/*
* the key control system call, 32-bit compatibility version for 64-bit archs
* - this should only be called if the 64-bit arch uses weird pointers in
default:
return -EOPNOTSUPP;
}
-
-} /* end compat_sys_keyctl() */
+}
out:
encrypted_shash_release();
return ret;
-
}
static void __exit cleanup_encrypted(void)
}
#endif
-/*****************************************************************************/
/*
* get the key quota record for a user, allocating a new record if one doesn't
* already exist
kfree(candidate);
out:
return user;
+}
-} /* end key_user_lookup() */
-
-/*****************************************************************************/
/*
* dispose of a user structure
*/
kfree(user);
}
+}
-} /* end key_user_put() */
-
-/*****************************************************************************/
/*
* assign a key the next unique serial number
* - these are assigned randomly to avoid security issues through covert
if (key->serial < xkey->serial)
goto attempt_insertion;
}
+}
-} /* end key_alloc_serial() */
-
-/*****************************************************************************/
/*
* allocate a key of the specified type
* - update the user's quota to reflect the existence of the key
key_user_put(user);
key = ERR_PTR(-EDQUOT);
goto error;
-
-} /* end key_alloc() */
+}
EXPORT_SYMBOL(key_alloc);
-/*****************************************************************************/
/*
* reserve an amount of quota for the key's payload
*/
key->datalen = datalen;
return ret;
-
-} /* end key_payload_reserve() */
+}
EXPORT_SYMBOL(key_payload_reserve);
-/*****************************************************************************/
/*
* instantiate a key and link it into the target keyring atomically
* - called with the target keyring's semaphore writelocked
wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT);
return ret;
+}
-} /* end __key_instantiate_and_link() */
-
-/*****************************************************************************/
/*
* instantiate a key and link it into the target keyring atomically
*/
__key_link_end(keyring, key->type, prealloc);
return ret;
-
-} /* end key_instantiate_and_link() */
+}
EXPORT_SYMBOL(key_instantiate_and_link);
-/*****************************************************************************/
/*
* negatively instantiate a key and link it into the target keyring atomically
*/
wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT);
return ret == 0 ? link_ret : ret;
-
-} /* end key_negate_and_link() */
+}
EXPORT_SYMBOL(key_negate_and_link);
-/*****************************************************************************/
/*
* do cleaning up in process context so that we don't have to disable
* interrupts all over the place
/* there may, of course, be more than one key to destroy */
goto go_again;
+}
-} /* end key_cleanup() */
-
-/*****************************************************************************/
/*
* dispose of a reference to a key
* - when all the references are gone, we schedule the cleanup task to come and
if (atomic_dec_and_test(&key->usage))
schedule_work(&key_cleanup_task);
}
-
-} /* end key_put() */
+}
EXPORT_SYMBOL(key_put);
-/*****************************************************************************/
/*
* find a key by its serial number
*/
error:
spin_unlock(&key_serial_lock);
return key;
+}
-} /* end key_lookup() */
-
-/*****************************************************************************/
/*
* find and lock the specified key type against removal
* - we return with the sem readlocked
found_kernel_type:
return ktype;
+}
-} /* end key_type_lookup() */
-
-/*****************************************************************************/
/*
* unlock a key type
*/
void key_type_put(struct key_type *ktype)
{
up_read(&key_types_sem);
+}
-} /* end key_type_put() */
-
-/*****************************************************************************/
/*
* attempt to update an existing key
* - the key has an incremented refcount
key_put(key);
key_ref = ERR_PTR(ret);
goto out;
+}
-} /* end __key_update() */
-
-/*****************************************************************************/
/*
* search the specified keyring for a key of the same description; if one is
* found, update it, otherwise add a new one
key_ref = __key_update(key_ref, payload, plen);
goto error;
-
-} /* end key_create_or_update() */
+}
EXPORT_SYMBOL(key_create_or_update);
-/*****************************************************************************/
/*
* update a key
*/
error:
return ret;
-
-} /* end key_update() */
+}
EXPORT_SYMBOL(key_update);
-/*****************************************************************************/
/*
* revoke a key
*/
}
up_write(&key->sem);
-
-} /* end key_revoke() */
+}
EXPORT_SYMBOL(key_revoke);
-/*****************************************************************************/
/*
* register a type of key
*/
out:
up_write(&key_types_sem);
return ret;
-
-} /* end register_key_type() */
+}
EXPORT_SYMBOL(register_key_type);
-/*****************************************************************************/
/*
* unregister a type of key
*/
up_write(&key_types_sem);
key_schedule_gc(0);
-
-} /* end unregister_key_type() */
+}
EXPORT_SYMBOL(unregister_key_type);
-/*****************************************************************************/
/*
* initialise the key management stuff
*/
rb_insert_color(&root_key_user.node,
&key_user_tree);
-
-} /* end key_init() */
+}
return 0;
}
-/*****************************************************************************/
/*
* extract the description of a new key from userspace and either add it as a
* new key to the specified keyring or update a matching key in that keyring
kfree(description);
error:
return ret;
+}
-} /* end sys_add_key() */
-
-/*****************************************************************************/
/*
* search the process keyrings for a matching key
* - nested keyrings may also be searched if they have Search permission
kfree(description);
error:
return ret;
+}
-} /* end sys_request_key() */
-
-/*****************************************************************************/
/*
* get the ID of the specified process keyring
* - the keyring must have search permission to be found
} /* end keyctl_get_keyring_ID() */
-/*****************************************************************************/
/*
* join the session keyring
* - implements keyctl(KEYCTL_JOIN_SESSION_KEYRING)
error:
return ret;
+}
-} /* end keyctl_join_session_keyring() */
-
-/*****************************************************************************/
/*
* update a key's data payload
* - the key must be writable
kfree(payload);
error:
return ret;
+}
-} /* end keyctl_update_key() */
-
-/*****************************************************************************/
/*
* revoke a key
* - the key must be writable
key_ref_put(key_ref);
error:
return ret;
+}
-} /* end keyctl_revoke_key() */
-
-/*****************************************************************************/
/*
* clear the specified process keyring
* - the keyring must be writable
key_ref_put(keyring_ref);
error:
return ret;
+}
-} /* end keyctl_keyring_clear() */
-
-/*****************************************************************************/
/*
* link a key into a keyring
* - the keyring must be writable
key_ref_put(keyring_ref);
error:
return ret;
+}
-} /* end keyctl_keyring_link() */
-
-/*****************************************************************************/
/*
* unlink the first attachment of a key from a keyring
* - the keyring must be writable
key_ref_put(keyring_ref);
error:
return ret;
+}
-} /* end keyctl_keyring_unlink() */
-
-/*****************************************************************************/
/*
* describe a user key
* - the key must have view permission
key_ref_put(key_ref);
error:
return ret;
+}
-} /* end keyctl_describe_key() */
-
-/*****************************************************************************/
/*
* search the specified keyring for a matching key
* - the start keyring must be searchable
kfree(description);
error:
return ret;
+}
-} /* end keyctl_keyring_search() */
-
-/*****************************************************************************/
/*
* read a user key's payload
* - the keyring must be readable or the key must be searchable from the
key_put(key);
error:
return ret;
+}
-} /* end keyctl_read_key() */
-
-/*****************************************************************************/
/*
* change the ownership of a key
* - the keyring owned by the changer
zapowner = newowner;
ret = -EDQUOT;
goto error_put;
+}
-} /* end keyctl_chown_key() */
-
-/*****************************************************************************/
/*
* change the permission mask on a key
* - the keyring owned by the changer
key_put(key);
error:
return ret;
-
-} /* end keyctl_setperm_key() */
+}
/*
* get the destination keyring for instantiation
return commit_creds(new);
}
-/*****************************************************************************/
/*
* instantiate the key with the specified payload, and, if one is given, link
* the key into the keyring
vfree(payload);
error:
return ret;
+}
-} /* end keyctl_instantiate_key() */
-
-/*****************************************************************************/
/*
* negatively instantiate the key with the given timeout (in seconds), and, if
* one is given, link the key into the keyring
error:
return ret;
+}
-} /* end keyctl_negate_key() */
-
-/*****************************************************************************/
/*
* set the default keyring in which request_key() will cache keys
* - return the old setting
error:
abort_creds(new);
return ret;
+}
-} /* end keyctl_set_reqkey_keyring() */
-
-/*****************************************************************************/
/*
* set or clear the timeout for a key
*/
ret = 0;
error:
return ret;
+}
-} /* end keyctl_set_timeout() */
-
-/*****************************************************************************/
/*
* assume the authority to instantiate the specified key
*/
ret = authkey->serial;
error:
return ret;
-
-} /* end keyctl_assume_authority() */
+}
/*
* get the security label of a key
#endif /* !TIF_NOTIFY_RESUME */
}
-/*****************************************************************************/
/*
* the key control system call
*/
default:
return -EOPNOTSUPP;
}
-
-} /* end sys_keyctl() */
+}
*/
static DECLARE_RWSEM(keyring_serialise_link_sem);
-/*****************************************************************************/
/*
* publish the name of a keyring so that it can be found by name (if it has
* one)
write_unlock(&keyring_name_lock);
}
+}
-} /* end keyring_publish_name() */
-
-/*****************************************************************************/
/*
* initialise a keyring
* - we object if we were given any data
}
return ret;
+}
-} /* end keyring_instantiate() */
-
-/*****************************************************************************/
/*
* match keyrings on their name
*/
{
return keyring->description &&
strcmp(keyring->description, description) == 0;
+}
-} /* end keyring_match() */
-
-/*****************************************************************************/
/*
* dispose of the data dangling from the corpse of a keyring
*/
key_put(klist->keys[loop]);
kfree(klist);
}
+}
-} /* end keyring_destroy() */
-
-/*****************************************************************************/
/*
* describe the keyring
*/
else
seq_puts(m, ": empty");
rcu_read_unlock();
+}
-} /* end keyring_describe() */
-
-/*****************************************************************************/
/*
* read a list of key IDs from the keyring's contents
* - the keyring's semaphore is read-locked
error:
return ret;
+}
-} /* end keyring_read() */
-
-/*****************************************************************************/
/*
* allocate a keyring and link into the destination keyring
*/
}
return keyring;
+}
-} /* end keyring_alloc() */
-
-/*****************************************************************************/
/*
* search the supplied keyring tree for a key that matches the criterion
* - perform a breadth-then-depth search up to the prescribed limit
rcu_read_unlock();
error:
return key_ref;
+}
-} /* end keyring_search_aux() */
-
-/*****************************************************************************/
/*
* search the supplied keyring tree for a key that matches the criterion
* - perform a breadth-then-depth search up to the prescribed limit
return keyring_search_aux(keyring, current->cred,
type, description, type->match);
-
-} /* end keyring_search() */
+}
EXPORT_SYMBOL(keyring_search);
-/*****************************************************************************/
/*
* search the given keyring only (no recursion)
* - keyring must be locked by caller
atomic_inc(&key->usage);
rcu_read_unlock();
return make_key_ref(key, possessed);
+}
-} /* end __keyring_search_one() */
-
-/*****************************************************************************/
/*
* find a keyring with the specified name
* - all named keyrings are searched
out:
read_unlock(&keyring_name_lock);
return keyring;
+}
-} /* end find_keyring_by_name() */
-
-/*****************************************************************************/
/*
* see if a cycle will will be created by inserting acyclic tree B in acyclic
* tree A at the topmost level (ie: as a direct child of A)
cycle_detected:
ret = -EDEADLK;
goto error;
-
-} /* end keyring_detect_cycle() */
+}
/*
* dispose of a keyring list after the RCU grace period, freeing the unlinked
EXPORT_SYMBOL(key_link);
-/*****************************************************************************/
/*
* unlink the first link to a key from a keyring
*/
ret = -ENOMEM;
up_write(&keyring->sem);
goto error;
-
-} /* end key_unlink() */
+}
EXPORT_SYMBOL(key_unlink);
-/*****************************************************************************/
/*
* dispose of a keyring list after the RCU grace period, releasing the keys it
* links to
key_put(klist->keys[loop]);
kfree(klist);
+}
-} /* end keyring_clear_rcu_disposal() */
-
-/*****************************************************************************/
/*
* clear the specified process keyring
* - implements keyctl(KEYCTL_CLEAR)
}
return ret;
-
-} /* end keyring_clear() */
+}
EXPORT_SYMBOL(keyring_clear);
-/*****************************************************************************/
/*
* dispose of the links from a revoked keyring
* - called with the key sem write-locked
rcu_assign_pointer(keyring->payload.subscriptions, NULL);
call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
}
-
-} /* end keyring_revoke() */
+}
/*
* Determine whether a key is dead
#include <linux/security.h>
#include "internal.h"
-/*****************************************************************************/
/**
* key_task_permission - Check a key can be used
* @key_ref: The key to check
/* let LSM be the final arbiter */
return security_key_permission(key_ref, cred, perm);
-
-} /* end key_task_permission() */
+}
EXPORT_SYMBOL(key_task_permission);
-/*****************************************************************************/
/*
* validate a key
*/
error:
return ret;
-
-} /* end key_validate() */
+}
EXPORT_SYMBOL(key_validate);
.release = seq_release,
};
-/*****************************************************************************/
/*
* declare the /proc files
*/
panic("Cannot create /proc/key-users\n");
return 0;
-
-} /* end key_proc_init() */
+}
__initcall(key_proc_init);
-/*****************************************************************************/
/*
* implement "/proc/keys" to provides a list of the keys on the system
*/
return __key_user_next(n);
}
-/*****************************************************************************/
/*
* implement "/proc/key-users" to provides a list of the key users
*/
maxbytes);
return 0;
-
}
.user_ns = &init_user_ns,
};
-/*****************************************************************************/
/*
* install user and user session keyrings for a particular UID
*/
return commit_creds(new);
}
-/*****************************************************************************/
/*
* the filesystem user ID changed
*/
tsk->cred->thread_keyring->uid = tsk->cred->fsuid;
up_write(&tsk->cred->thread_keyring->sem);
}
+}
-} /* end key_fsuid_changed() */
-
-/*****************************************************************************/
/*
* the filesystem group ID changed
*/
tsk->cred->thread_keyring->gid = tsk->cred->fsgid;
up_write(&tsk->cred->thread_keyring->sem);
}
+}
-} /* end key_fsgid_changed() */
-
-/*****************************************************************************/
/*
* search only my process keyrings for the first matching key
* - we use the supplied match function to see if the description (or other
return key_ref;
}
-/*****************************************************************************/
/*
* search the process keyrings for the first matching key
* - we use the supplied match function to see if the description (or other
found:
return key_ref;
+}
-} /* end search_process_keyrings() */
-
-/*****************************************************************************/
/*
* see if the key we're looking at is the target key
*/
int lookup_user_key_possessed(const struct key *key, const void *target)
{
return key == target;
+}
-} /* end lookup_user_key_possessed() */
-
-/*****************************************************************************/
/*
* lookup a key given a key ID from userspace with a given permissions mask
* - don't create special keyrings unless so requested
reget_creds:
put_cred(cred);
goto try_again;
+}
-} /* end lookup_user_key() */
-
-/*****************************************************************************/
/*
* join the named keyring as the session keyring if possible, or attempt to
* create a new one of that name if not
.read = request_key_auth_read,
};
-/*****************************************************************************/
/*
* instantiate a request-key authorisation key
*/
{
key->payload.data = (struct request_key_auth *) data;
return 0;
+}
-} /* end request_key_auth_instantiate() */
-
-/*****************************************************************************/
/*
* reading a request-key authorisation key retrieves the callout information
*/
seq_puts(m, "key:");
seq_puts(m, key->description);
seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
+}
-} /* end request_key_auth_describe() */
-
-/*****************************************************************************/
/*
* read the callout_info data
* - the key's semaphore is read-locked
}
return ret;
+}
-} /* end request_key_auth_read() */
-
-/*****************************************************************************/
/*
* handle revocation of an authorisation token key
* - called with the key sem write-locked
put_cred(rka->cred);
rka->cred = NULL;
}
+}
-} /* end request_key_auth_revoke() */
-
-/*****************************************************************************/
/*
* destroy an instantiation authorisation token key
*/
key_put(rka->dest_keyring);
kfree(rka->callout_info);
kfree(rka);
+}
-} /* end request_key_auth_destroy() */
-
-/*****************************************************************************/
/*
* create an authorisation token for /sbin/request-key or whoever to gain
* access to the caller's security data
kfree(rka);
kleave("= %d", ret);
return ERR_PTR(ret);
+}
-} /* end request_key_auth_new() */
-
-/*****************************************************************************/
/*
* see if an authorisation key is associated with a particular key
*/
key_serial_t id = (key_serial_t)(unsigned long) _id;
return rka->target_key->serial == id;
+}
-} /* end key_get_instantiation_authkey_match() */
-
-/*****************************************************************************/
/*
* get the authorisation key for instantiation of a specific key if attached to
* the current process's keyrings
error:
return authkey;
-
-} /* end key_get_instantiation_authkey() */
+}
EXPORT_SYMBOL_GPL(key_type_user);
-/*****************************************************************************/
/*
* instantiate a user defined key
*/
error:
return ret;
-
-} /* end user_instantiate() */
+}
EXPORT_SYMBOL_GPL(user_instantiate);
-/*****************************************************************************/
/*
* dispose of the old data from an updated user defined key
*/
upayload = container_of(rcu, struct user_key_payload, rcu);
kfree(upayload);
+}
-} /* end user_update_rcu_disposal() */
-
-/*****************************************************************************/
/*
* update a user defined key
* - the key's semaphore is write-locked
error:
return ret;
-
-} /* end user_update() */
+}
EXPORT_SYMBOL_GPL(user_update);
-/*****************************************************************************/
/*
* match users on their name
*/
int user_match(const struct key *key, const void *description)
{
return strcmp(key->description, description) == 0;
-
-} /* end user_match() */
+}
EXPORT_SYMBOL_GPL(user_match);
-/*****************************************************************************/
/*
* dispose of the links from a revoked keyring
* - called with the key sem write-locked
rcu_assign_pointer(key->payload.data, NULL);
call_rcu(&upayload->rcu, user_update_rcu_disposal);
}
-
-} /* end user_revoke() */
+}
EXPORT_SYMBOL(user_revoke);
-/*****************************************************************************/
/*
* dispose of the data dangling from the corpse of a user key
*/
struct user_key_payload *upayload = key->payload.data;
kfree(upayload);
-
-} /* end user_destroy() */
+}
EXPORT_SYMBOL_GPL(user_destroy);
-/*****************************************************************************/
/*
* describe the user key
*/
seq_puts(m, key->description);
seq_printf(m, ": %u", key->datalen);
-
-} /* end user_describe() */
+}
EXPORT_SYMBOL_GPL(user_describe);
-/*****************************************************************************/
/*
* read the key data
* - the key's semaphore is read-locked
}
return ret;
-
-} /* end user_read() */
+}
EXPORT_SYMBOL_GPL(user_read);